HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

关于高德地图打包APP之后无法定位的问题

1.首先查看是否高德KEY失效
2.在查看配置是否和官方文档相同

  1. 其次查看是否申请的是的Android的key;注意打包APP一定要使用Android的Key,否则打包之后定位无效

1.首先查看是否高德KEY失效
2.在查看配置是否和官方文档相同

  1. 其次查看是否申请的是的Android的key;注意打包APP一定要使用Android的Key,否则打包之后定位无效

tabbar

移动APP

请问uni-app里面的tabbar这个能够去动态的改变数量吗?现在有这个需求但是自己写的又有点卡顿,所有官方大大们有没有什么解决方案。

请问uni-app里面的tabbar这个能够去动态的改变数量吗?现在有这个需求但是自己写的又有点卡顿,所有官方大大们有没有什么解决方案。

微信小程序语音识别

想着既然自己踩了几天坑解决了问题,那就花点时间整理给有需要的人,这样社区有用的帖子才会越来越多。

一 问题背景
微信小程序端需要解决语音识别的功能。
二 思路
当时的思路有一个,就是使用小程序的录音和上传api,将录音文件上传到后台,后台调用第三方语音接口将识别的内容再返回给小程序,这样实现我觉得应该也可以。但是百度发现了小程序的团队开发的第三方插件,试了一下可以用。
三 实现方法
1登陆小程序管理后台,设置->第三方设置(拖到下方插件管理)->添加插件->搜索“同声传译”


2在manifest.json文件中,小程序节点下添加插件。

"mp-weixin" : {  
        /* 小程序特有相关 */  
        "appid" : "wx59f6366a9db5ced5",  
        "setting" : {  
            "urlCheck" : true  
        },  
        "usingComponents" : true,  
        "plugins" : {  
            "WechatSI" : {  
                "version" : "0.3.1",  
                "provider" : "wx069ba97219f66d99"  
            }  
        }  
    },

3在功能页面中使用就可以了

<template>  
    <view>  
        <!-- #ifndef H5 -->  
        <cu-custom bgColor="bg-gradual-green">  
            <block slot="content">语音识别</block>  
        </cu-custom>  
        <!-- #endif -->  

        <view class="voicepad">  
            {{voiceState}}  
        </view>  
        <button class="cu-btn  bg-green voicebtn " @touchstart="touchStart" @touchend="touchEnd"><text class="cuIcon-voicefill"></text></button>  
    </view>  
</template>  

<script>  
    var plugin = requirePlugin("WechatSI")  
    let manager = plugin.getRecordRecognitionManager();  

    export default {  
        data() {  
            return {  
                voiceState: "你可以这样说..."  
            }  
        },  
        onShow() {  

        },    
        onLoad() {  
            this.initRecord();  
        },  
        methods: {  
            touchStart: function() {  
                // uni.vibrateLong({  
                //  success:function(){  
                //  }  
                // });  
                        manager.start({  
                            duration: 60000,  
                            lang: "zh_CN"  
                        });  
            },  
            touchEnd: function() {  
                uni.showToast()  
                manager.stop();  
            },  
            /**  
             * 初始化语音识别回调  
             * 绑定语音播放开始事件  
             */  
            initRecord: function() {  
                manager.onStart = function(res) {  
                    this.voiceState ="onStart:"+ res.msg+"正在录音"  
                };  
                //有新的识别内容返回,则会调用此事件  
                manager.onRecognize = (res) => {  
                    this.voiceState = "onRecognize"+res.result;  
                }  

                // 识别结束事件  
                manager.onStop = (res) => {  

                    this.voiceState ="onStop"+ res.result;  
                }  

                // 识别错误事件  
                manager.onError = (res) => {  

                    this.voiceState = "onError"+res.msg;  

                }  
            },  
        }  
    }  
</script>  

<style>  
.voicebtn{height:130upx;display: block;width:130upx;line-height:130upx;border-radius: 65upx;font-size: 50upx;position: absolute;top:1060upx;left:310upx;}  
.voicepad{height: 250upx;width:680upx;background: #fff;margin: 30upx auto;border-radius: 8upx;color: #CCCCCC;padding:20upx;font-size: 35upx;}  
</style>  
继续阅读 »

想着既然自己踩了几天坑解决了问题,那就花点时间整理给有需要的人,这样社区有用的帖子才会越来越多。

一 问题背景
微信小程序端需要解决语音识别的功能。
二 思路
当时的思路有一个,就是使用小程序的录音和上传api,将录音文件上传到后台,后台调用第三方语音接口将识别的内容再返回给小程序,这样实现我觉得应该也可以。但是百度发现了小程序的团队开发的第三方插件,试了一下可以用。
三 实现方法
1登陆小程序管理后台,设置->第三方设置(拖到下方插件管理)->添加插件->搜索“同声传译”


2在manifest.json文件中,小程序节点下添加插件。

"mp-weixin" : {  
        /* 小程序特有相关 */  
        "appid" : "wx59f6366a9db5ced5",  
        "setting" : {  
            "urlCheck" : true  
        },  
        "usingComponents" : true,  
        "plugins" : {  
            "WechatSI" : {  
                "version" : "0.3.1",  
                "provider" : "wx069ba97219f66d99"  
            }  
        }  
    },

3在功能页面中使用就可以了

<template>  
    <view>  
        <!-- #ifndef H5 -->  
        <cu-custom bgColor="bg-gradual-green">  
            <block slot="content">语音识别</block>  
        </cu-custom>  
        <!-- #endif -->  

        <view class="voicepad">  
            {{voiceState}}  
        </view>  
        <button class="cu-btn  bg-green voicebtn " @touchstart="touchStart" @touchend="touchEnd"><text class="cuIcon-voicefill"></text></button>  
    </view>  
</template>  

<script>  
    var plugin = requirePlugin("WechatSI")  
    let manager = plugin.getRecordRecognitionManager();  

    export default {  
        data() {  
            return {  
                voiceState: "你可以这样说..."  
            }  
        },  
        onShow() {  

        },    
        onLoad() {  
            this.initRecord();  
        },  
        methods: {  
            touchStart: function() {  
                // uni.vibrateLong({  
                //  success:function(){  
                //  }  
                // });  
                        manager.start({  
                            duration: 60000,  
                            lang: "zh_CN"  
                        });  
            },  
            touchEnd: function() {  
                uni.showToast()  
                manager.stop();  
            },  
            /**  
             * 初始化语音识别回调  
             * 绑定语音播放开始事件  
             */  
            initRecord: function() {  
                manager.onStart = function(res) {  
                    this.voiceState ="onStart:"+ res.msg+"正在录音"  
                };  
                //有新的识别内容返回,则会调用此事件  
                manager.onRecognize = (res) => {  
                    this.voiceState = "onRecognize"+res.result;  
                }  

                // 识别结束事件  
                manager.onStop = (res) => {  

                    this.voiceState ="onStop"+ res.result;  
                }  

                // 识别错误事件  
                manager.onError = (res) => {  

                    this.voiceState = "onError"+res.msg;  

                }  
            },  
        }  
    }  
</script>  

<style>  
.voicebtn{height:130upx;display: block;width:130upx;line-height:130upx;border-radius: 65upx;font-size: 50upx;position: absolute;top:1060upx;left:310upx;}  
.voicepad{height: 250upx;width:680upx;background: #fff;margin: 30upx auto;border-radius: 8upx;color: #CCCCCC;padding:20upx;font-size: 35upx;}  
</style>  
收起阅读 »

Appstore审核反馈废弃UIWebview APIs问题的说明

itme90809 WKWebview uiwebview Appstore iOS

此文档将不再维护,请参考新文档:https://uniapp.dcloud.io/tutorial/app-ios-uiwebview

iOS有UIWebview和WKWebview两种webview。从iOS13开始苹果将UIWebview列为过期API。

2020年4月起App Store将不再接受使用UIWebView的新App上架、2020年12月起将不再接受使用UIWebView的App更新。

从HBuilderX 2.2.5起,iOS上默认均已经是WKWebview,除非开发者手动在代码中指定要用UIWebview,否则实际渲染的页面都是在WKWebview里渲染的。
不过,虽然实际页面是WKWebview渲染的,但App底层引擎源码里仍然有UIWebview的可选引用。Appstore的机审会发现二进制代码中包括对UIWebview的引用,从而引发告警。
从HBuilderX 2.6.6起,uiWebview从基础引擎中移除,变成可选模块(manifest里选择)。机审也没有提示了。

老HBuilder和HBuilderX 2.2.5之前的版本,App端策略如下:

  • 5+ APP(含wap2app)
    默认为UIWebview。
  • uni-app
    vue页面中web-view组件默认使用UIWebview,nvue页面中web-view组件使用WKWebview。

HBuilderX 2.2.5+版本已将iOS上所有webview的默认内核由UIWebview调整为WKWebview。

<a id="uiwebview"/>
HBuilderX 2.6.6+版本已将iOS中所有UIWebview代码从基础引擎中摘除,独立为UIWebview模块,如继续使用UIWebview则需在manifest中勾选使用UIWebview模块

配置使用UIWebview模块

打开项目的manifest.json文件,在“App模块配置”项中勾选“iOS UIWebview”:

配置后需提交云端打包生效

5+App(含wap2app)如何切换iOS默认使用UIWebview或WKWebview内核?

HBuilderX 2.2.5以前的版本,iOS上webview的默认为UIWebview,HBuilderX2.2.5及以后的版本默认改为WKWebview。
如果要修改默认值,可在manifest.json中配置。
在manifest.json文件源码视图中设置plus -> kernel -> ios 的值为 "WKWebview"或"UIWebview":

    "plus": {  
        "kernel": {  
            "ios": "UIWebview"    //或者 "WKWebview"  
        },  
        // ...  
    }

uni-app 如何配置web-view组件默认使用UIWebview或WKWebview内核?

HBuilderX 2.2.5以前的版本,iOS上vue页面中web-view组件或调用5+ API创建的Webview窗口默认为UIWebview,HBuilderX2.2.5及以后的版本默认改为WKWebview。
如果要修改默认值,可在manifest.json中配置。
在manifest.json文件源码视图中设置 app-plus -> kernel -> ios 的值为 "WKWebview"或"UIWebview":

    "app-plus": {  
        "kernel": {  
            "ios": "UIWebview"    //或者 "WKWebview"  
        },  
        // ...  
    }

nvue页面中的web-view组件强制使用WKWebview,不可配置

如何使用5+ API(plus.webview.create)创建Webview窗口时指定使用UIWebview或WKWebview内核?

创建Webvie窗口时可通过kernel属性指定内核,如下:

// 通过kernel属性指定Webview的内核  
var w = plus.webview.create('https://xxx.xxx.xxx', 'id', {  
    'kernel': 'UIWebview'       //或者'WKWebview'  
});

更多规范参考5+ API的 WebviewStyles

使用WKWebview的影响

使用WKWebview替换UIWebview将会影响以下功能:

  • 更严格的跨域访问限制
    WKWebview认为本地html通过js访问网络及本地文件都算跨域访问(这种情况UIWebview不是跨域),跨域时访问网络资源使用5+ API(plus.net)来替换xmlhttp等传统ajax写法;ajax也不能访问本地文件,需使用5+ API(plus.io)读取本地文件,后者有个单独文章可参考:https://ask.dcloud.net.cn/article/36858
    使用exif.js等三方库可能涉及跨目录的本地图片下载请求,图像方向获取和旋转Plus有专门的API,无需使用js库做。
  • 由于WKWebview不支持跨域访问,标准的xhr或jq的ajax,都无法跨域。mui框架中网络请求判断为跨域访问会自动调用5+ API(plus.net),如果在mui.plusReady触发前调用,因为5+ API没有准备好会报“Script error.filename:lineno:0”错误,这时必须保证mui的网络请求在mui.plusReady后调用,或者直接改用plus.net写法。
  • WKWebview下canvas也有跨域问题,比如canvas.toDataURL。
    如果canvas使用网络图像遇到跨域问题,需要服务端设置图像的响应头:Access-Control-Allow-Origin
    如果canvas使用本地图像遇到跨域问题,可以使用plus接口将图像转换为base64再使用,相关插件:https://ext.dcloud.net.cn/plugin?id=123
  • iOS手机内存不足时,如果是UIWebview的应用,系统会整体回收这个App,现象是在重新打开已打开过的App时App整体重启。而WKWebview则是单个页面回收,这带来的坏处就是内存不足时,会单个页面白屏。详见https://ask.dcloud.net.cn/article/35913。uni-app不涉及此问题,如果是5+App,方式1是在manifest切回UIWebview,暂时UIWebview还可以上架,只是会收到警告。方式2时监听白屏事件,自行恢复页面:https://ask.dcloud.net.cn/article/36540
  • iOS8、9上的WKWebview不支持websql,iOS10恢复支持
  • 不支持plus.navigator.setCookie
  • 不支持webview的overrideresource方法
  • wk第一次渲染速度略慢于uiwebview;
  • 由于资源拦截的API overrideresource 无法再使用,5+ APP(含wap2app)项目中,云打包时的js原生混淆功能会失效。如果要使用js原生混淆必须使用UIWebview。uni-app有单独的原生js加密方案,因为uni-app的js不运行在webview里,而是在独立的jscore里,所以不受影响。

但WKWebview的好处是:节省内存;滚动时懒加载的图片也可以实时渲染,而uiwebview在滚动停止后懒加载的图片才能显示。

如果同时在一个app里使用ui和wk两种webview,注意2种webview之间的cookie、localstorage、session不共享,但plus.storage是共享的。

uni-app中Webview的使用注意

uni-app的js运行在独立的jscore中,而不是Webview中,不存在跨域问题。
uni-app的渲染层,在iOS下是强制wkwebview。如果你编写了renderjs代码,在渲染层执行js,则同样会遇到跨域问题。此时尽量把与跨域相关的操作放到普通的js逻辑层操作。
除了渲染层,还有一个web-view组件的问题要注意:

  • uni-app的vue页面的web-view组件,从HBuilderX 2.2.5+起是WKWebview,之前版本默认是UIWebview
  • uni-app的非自定义组件模式的js逻辑层,在HBuilderX 2.2.5之前是UIWebview。升级到HBuilderX2.3+后可能导致网络跨域问题,fail{"statusCode":0,"errMsg":"request:fail abort"}。不过非自定义组件已于2019年11月1日起停止支持。

如果需要调整uni-app下web-view组件的渲染内核设置,将manifest.json源码视图的app-plus -> kernel -> ios 的值设为 UIWebview。

uni-app的nvue页面问题

nvue页面不使用webview渲染,但其中的web-view组件说明如下。

  • nvue的weex 组件模式
    weex模式下的web-view组件是weex自己实现的,它目前仍然使用UIWebview。官方会追踪weex的升级。
  • nvue的uni-app组件模式
    web-view组件使用WKWebview。不可修改为uiWebview。

三方SDK中UIWebview的使用

目前如下SDK中仍然使用了UIWebview,不管是5+App还是uni-app。

  • DCloud开屏广告
    HBuilderX 2.2.5版之前,点击广告打开的内置网页仍然使用UIWebview加载
    HBuilderX 2.2.5+版本已调整改为WKWebview。
  • 支付宝
    HBuilderX 2.6.10版本之前,支付宝SDK为15.5.7版本,包含了UIWebview
    HBuilderX 2.6.10+版本已更新支付宝SDK为15.7.4,没有使用UIWebview
  • 微信登录、分享、支付
    HBuilderX 2.6.6+版本已更新微信SDK为1.8.6.2版本,没有使用UIWebview。
    注意微信登录支付的SDK升级后,会强制要求通用链接。另见文档:https://ask.dcloud.net.cn/article/36445
  • 微博登录、分享
    HBuilderX 2.6.10版本之前,微博SDK为3.2.5版本,包含了UIWebview
    HBuilderX 2.6.10+版本已更新微博SDK为3.2.7版本,没有使用UIWebview
  • QQ登录、分享
    HBuilderX 2.3.4+版本已更新QQSDK为3.3.6,没有使用UIWebview。
  • 小米登录
    小米官方SDK中使用了UIWebview,如果提交appstore建议不要使用小米登录

5+App开发者建议直接升级为uni-app,一劳永逸,不会有跨域、白屏和无法加密等各种问题。

<a id="lixianuiwebview">离线打包配置UIWebview模块 </a>

如果开发者需要在离线打包工程中使用UIWebview功能,需要在自己的离线工程中配置UIWebview模块

注意事项

如果配置正确后,提交Appstore,仍然被提示含有UIWebview,那么请检查你的app是否使用了其他原生插件。
一般或者是配置错误,或者是三方原生插件造成。

继续阅读 »

此文档将不再维护,请参考新文档:https://uniapp.dcloud.io/tutorial/app-ios-uiwebview

iOS有UIWebview和WKWebview两种webview。从iOS13开始苹果将UIWebview列为过期API。

2020年4月起App Store将不再接受使用UIWebView的新App上架、2020年12月起将不再接受使用UIWebView的App更新。

从HBuilderX 2.2.5起,iOS上默认均已经是WKWebview,除非开发者手动在代码中指定要用UIWebview,否则实际渲染的页面都是在WKWebview里渲染的。
不过,虽然实际页面是WKWebview渲染的,但App底层引擎源码里仍然有UIWebview的可选引用。Appstore的机审会发现二进制代码中包括对UIWebview的引用,从而引发告警。
从HBuilderX 2.6.6起,uiWebview从基础引擎中移除,变成可选模块(manifest里选择)。机审也没有提示了。

老HBuilder和HBuilderX 2.2.5之前的版本,App端策略如下:

  • 5+ APP(含wap2app)
    默认为UIWebview。
  • uni-app
    vue页面中web-view组件默认使用UIWebview,nvue页面中web-view组件使用WKWebview。

HBuilderX 2.2.5+版本已将iOS上所有webview的默认内核由UIWebview调整为WKWebview。

<a id="uiwebview"/>
HBuilderX 2.6.6+版本已将iOS中所有UIWebview代码从基础引擎中摘除,独立为UIWebview模块,如继续使用UIWebview则需在manifest中勾选使用UIWebview模块

配置使用UIWebview模块

打开项目的manifest.json文件,在“App模块配置”项中勾选“iOS UIWebview”:

配置后需提交云端打包生效

5+App(含wap2app)如何切换iOS默认使用UIWebview或WKWebview内核?

HBuilderX 2.2.5以前的版本,iOS上webview的默认为UIWebview,HBuilderX2.2.5及以后的版本默认改为WKWebview。
如果要修改默认值,可在manifest.json中配置。
在manifest.json文件源码视图中设置plus -> kernel -> ios 的值为 "WKWebview"或"UIWebview":

    "plus": {  
        "kernel": {  
            "ios": "UIWebview"    //或者 "WKWebview"  
        },  
        // ...  
    }

uni-app 如何配置web-view组件默认使用UIWebview或WKWebview内核?

HBuilderX 2.2.5以前的版本,iOS上vue页面中web-view组件或调用5+ API创建的Webview窗口默认为UIWebview,HBuilderX2.2.5及以后的版本默认改为WKWebview。
如果要修改默认值,可在manifest.json中配置。
在manifest.json文件源码视图中设置 app-plus -> kernel -> ios 的值为 "WKWebview"或"UIWebview":

    "app-plus": {  
        "kernel": {  
            "ios": "UIWebview"    //或者 "WKWebview"  
        },  
        // ...  
    }

nvue页面中的web-view组件强制使用WKWebview,不可配置

如何使用5+ API(plus.webview.create)创建Webview窗口时指定使用UIWebview或WKWebview内核?

创建Webvie窗口时可通过kernel属性指定内核,如下:

// 通过kernel属性指定Webview的内核  
var w = plus.webview.create('https://xxx.xxx.xxx', 'id', {  
    'kernel': 'UIWebview'       //或者'WKWebview'  
});

更多规范参考5+ API的 WebviewStyles

使用WKWebview的影响

使用WKWebview替换UIWebview将会影响以下功能:

  • 更严格的跨域访问限制
    WKWebview认为本地html通过js访问网络及本地文件都算跨域访问(这种情况UIWebview不是跨域),跨域时访问网络资源使用5+ API(plus.net)来替换xmlhttp等传统ajax写法;ajax也不能访问本地文件,需使用5+ API(plus.io)读取本地文件,后者有个单独文章可参考:https://ask.dcloud.net.cn/article/36858
    使用exif.js等三方库可能涉及跨目录的本地图片下载请求,图像方向获取和旋转Plus有专门的API,无需使用js库做。
  • 由于WKWebview不支持跨域访问,标准的xhr或jq的ajax,都无法跨域。mui框架中网络请求判断为跨域访问会自动调用5+ API(plus.net),如果在mui.plusReady触发前调用,因为5+ API没有准备好会报“Script error.filename:lineno:0”错误,这时必须保证mui的网络请求在mui.plusReady后调用,或者直接改用plus.net写法。
  • WKWebview下canvas也有跨域问题,比如canvas.toDataURL。
    如果canvas使用网络图像遇到跨域问题,需要服务端设置图像的响应头:Access-Control-Allow-Origin
    如果canvas使用本地图像遇到跨域问题,可以使用plus接口将图像转换为base64再使用,相关插件:https://ext.dcloud.net.cn/plugin?id=123
  • iOS手机内存不足时,如果是UIWebview的应用,系统会整体回收这个App,现象是在重新打开已打开过的App时App整体重启。而WKWebview则是单个页面回收,这带来的坏处就是内存不足时,会单个页面白屏。详见https://ask.dcloud.net.cn/article/35913。uni-app不涉及此问题,如果是5+App,方式1是在manifest切回UIWebview,暂时UIWebview还可以上架,只是会收到警告。方式2时监听白屏事件,自行恢复页面:https://ask.dcloud.net.cn/article/36540
  • iOS8、9上的WKWebview不支持websql,iOS10恢复支持
  • 不支持plus.navigator.setCookie
  • 不支持webview的overrideresource方法
  • wk第一次渲染速度略慢于uiwebview;
  • 由于资源拦截的API overrideresource 无法再使用,5+ APP(含wap2app)项目中,云打包时的js原生混淆功能会失效。如果要使用js原生混淆必须使用UIWebview。uni-app有单独的原生js加密方案,因为uni-app的js不运行在webview里,而是在独立的jscore里,所以不受影响。

但WKWebview的好处是:节省内存;滚动时懒加载的图片也可以实时渲染,而uiwebview在滚动停止后懒加载的图片才能显示。

如果同时在一个app里使用ui和wk两种webview,注意2种webview之间的cookie、localstorage、session不共享,但plus.storage是共享的。

uni-app中Webview的使用注意

uni-app的js运行在独立的jscore中,而不是Webview中,不存在跨域问题。
uni-app的渲染层,在iOS下是强制wkwebview。如果你编写了renderjs代码,在渲染层执行js,则同样会遇到跨域问题。此时尽量把与跨域相关的操作放到普通的js逻辑层操作。
除了渲染层,还有一个web-view组件的问题要注意:

  • uni-app的vue页面的web-view组件,从HBuilderX 2.2.5+起是WKWebview,之前版本默认是UIWebview
  • uni-app的非自定义组件模式的js逻辑层,在HBuilderX 2.2.5之前是UIWebview。升级到HBuilderX2.3+后可能导致网络跨域问题,fail{"statusCode":0,"errMsg":"request:fail abort"}。不过非自定义组件已于2019年11月1日起停止支持。

如果需要调整uni-app下web-view组件的渲染内核设置,将manifest.json源码视图的app-plus -> kernel -> ios 的值设为 UIWebview。

uni-app的nvue页面问题

nvue页面不使用webview渲染,但其中的web-view组件说明如下。

  • nvue的weex 组件模式
    weex模式下的web-view组件是weex自己实现的,它目前仍然使用UIWebview。官方会追踪weex的升级。
  • nvue的uni-app组件模式
    web-view组件使用WKWebview。不可修改为uiWebview。

三方SDK中UIWebview的使用

目前如下SDK中仍然使用了UIWebview,不管是5+App还是uni-app。

  • DCloud开屏广告
    HBuilderX 2.2.5版之前,点击广告打开的内置网页仍然使用UIWebview加载
    HBuilderX 2.2.5+版本已调整改为WKWebview。
  • 支付宝
    HBuilderX 2.6.10版本之前,支付宝SDK为15.5.7版本,包含了UIWebview
    HBuilderX 2.6.10+版本已更新支付宝SDK为15.7.4,没有使用UIWebview
  • 微信登录、分享、支付
    HBuilderX 2.6.6+版本已更新微信SDK为1.8.6.2版本,没有使用UIWebview。
    注意微信登录支付的SDK升级后,会强制要求通用链接。另见文档:https://ask.dcloud.net.cn/article/36445
  • 微博登录、分享
    HBuilderX 2.6.10版本之前,微博SDK为3.2.5版本,包含了UIWebview
    HBuilderX 2.6.10+版本已更新微博SDK为3.2.7版本,没有使用UIWebview
  • QQ登录、分享
    HBuilderX 2.3.4+版本已更新QQSDK为3.3.6,没有使用UIWebview。
  • 小米登录
    小米官方SDK中使用了UIWebview,如果提交appstore建议不要使用小米登录

5+App开发者建议直接升级为uni-app,一劳永逸,不会有跨域、白屏和无法加密等各种问题。

<a id="lixianuiwebview">离线打包配置UIWebview模块 </a>

如果开发者需要在离线打包工程中使用UIWebview功能,需要在自己的离线工程中配置UIWebview模块

注意事项

如果配置正确后,提交Appstore,仍然被提示含有UIWebview,那么请检查你的app是否使用了其他原生插件。
一般或者是配置错误,或者是三方原生插件造成。

收起阅读 »

uni-app 利用native调用Android NFC 读取RFID标签的UID

uuid NFC

manifest.json 权限:
"<uses-permission android:name=\"android.permission.INTERNET\"/>",
"<uses-permission android:name=\"android.permission.NFC\"/>",
"<uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\"/>",
nfc.vue代码如下,完全可运行:

<template>  
    <view>  
        <view class="uni-padding-wrap">  
            NFC  
            <view class="uni-common-mt" style="background:#FFF; padding:20upx;">  
                <text>  
                    UID:{{UID}}  
                    {{tip}}  
                </text>  
            </view>  
        </view>  
    </view>  
</template>  

<script>  
    var NfcAdapter;  
    export default {  
        data() {  
            return {  
                title: 'redNFC',  
                UID: '',  
                msg: '',  
                tip: '',  
            }  
        },  
        onLoad() {  
            console.log("onLoad");  

        },  
        onShow() {  
            console.log("onShow");  
            this.NFCInit();  
        },  
        onHide() {  
            console.log("onHide");  
            this.NFCReadUID();  
        },  
        methods: {  
            NFCInit() {  
                try {  
                    var main = plus.android.runtimeMainActivity();  
                    //console.log(main);  
                    var Intent = plus.android.importClass('android.content.Intent');  
                    // console.log(Intent);  
                    var Activity = plus.android.importClass('android.app.Activity');  
                    //console.log(Activity);  
                    var PendingIntent = plus.android.importClass('android.app.PendingIntent');  
                    // console.log(PendingIntent);                    
                    var IntentFilter = plus.android.importClass('android.content.IntentFilter');  
                    // console.log(IntentFilter);  
                    // var Uri = plus.android.importClass('android.net.Uri');                     
                    // var Bundle = plus.android.importClass('android.os.Bundle');                    
                    // var Handler = plus.android.importClass('android.os.Handler');  
                    //console.log(Handler);  
                    NfcAdapter = plus.android.importClass('android.nfc.NfcAdapter');  
                    //console.log(NfcAdapter);  
                    var _nfcAdapter = NfcAdapter.getDefaultAdapter(main)  
                    // console.log(_nfcAdapter);  

                    var ndef = new IntentFilter("android.nfc.action.NDEF_DISCOVERED"); //NfcAdapter.ACTION_NDEF_DISCOVERED  
                    // console.log(ndef);  
                    var tag = new IntentFilter("android.nfc.action.TAG_DISCOVERED"); //NfcAdapter.ACTION_TECH_DISCOVERED  
                    // console.log(tag);  
                    var tech = new IntentFilter("android.nfc.action.TECH_DISCOVERED");  
                    // console.log(tech);  
                    var intentFiltersArray = [ndef, tag, tech];  

                    var techListsArray = [  
                        ["android.nfc.tech.Ndef"],  
                        ["android.nfc.tech.IsoDep"],  
                        ["android.nfc.tech.NfcA"],  
                        ["android.nfc.tech.NfcB"],  
                        ["android.nfc.tech.NfcF"],  
                        ["android.nfc.tech.Nfcf"],  
                        ["android.nfc.tech.NfcV"],  
                        ["android.nfc.tech.NdefFormatable"],  
                        ["android.nfc.tech.MifareClassi"],  
                        ["android.nfc.tech.MifareUltralight"]  
                    ];  

                    var _intent = new Intent(main, main.getClass());  
                    // console.log(_intent);  
                    _intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);  

                    var pendingIntent = PendingIntent.getActivity(main, 0, _intent, 0);  
                    // console.log(pendingIntent);  

                    if (_nfcAdapter == null) {  
                        this.tip = '本设备不支持NFC!';  
                    } else if (_nfcAdapter.isEnabled() == false) {  
                        this.tip = 'NFC功能未打开!';  
                    } else {  
                        this.tip = 'NFC正常';  
                        _nfcAdapter.enableForegroundDispatch(main, pendingIntent, IntentFilter, techListsArray);  
                    }  
                } catch (e) {  
                    //TODO handle the exception  
                }  
            },  
            NFCReadUID() {  
                var main = plus.android.runtimeMainActivity();  
                var _intent = main.getIntent();  
                var _action = _intent.getAction();  
                // console.log("action type:" + _action);  

                if (NfcAdapter.ACTION_NDEF_DISCOVERED == _action || NfcAdapter.ACTION_TAG_DISCOVERED == _action || NfcAdapter.ACTION_TECH_DISCOVERED ==  
                    _action) {  
                    var Tag = plus.android.importClass('android.nfc.Tag');  
                    var tagFromIntent = _intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);  
                    var uid = _intent.getByteArrayExtra(NfcAdapter.EXTRA_ID);  
                    console.log(uid);  
                    this.UID = this.Bytes2HexString(uid);  
                    //console.log(this.UID);  
                }  
            },  
            //将byte[] 转为Hex,  
            Bytes2HexString(arrBytes) {  
                var str = "";  
                for (var i = 0; i < arrBytes.length; i++) {  
                    var tmp;  
                    var num = arrBytes[i];  
                    if (num < 0) {  
                        //Java中数值是以补码的形式存在的,应用程序展示的十进制是补码对应真值。补码的存在主要为了简化计算机底层的运算,将减法运算直接当加法来做  
                        tmp = (255 + num + 1).toString(16);  
                    } else {  
                        tmp = num.toString(16);  
                    }  
                    if (tmp.length == 1) {  
                        tmp = "0" + tmp;  
                    }  
                    str += tmp;  
                }  
                return str;  
            }  
        }  
    }  
</script>  

<style>  

</style>  
继续阅读 »

manifest.json 权限:
"<uses-permission android:name=\"android.permission.INTERNET\"/>",
"<uses-permission android:name=\"android.permission.NFC\"/>",
"<uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\"/>",
nfc.vue代码如下,完全可运行:

<template>  
    <view>  
        <view class="uni-padding-wrap">  
            NFC  
            <view class="uni-common-mt" style="background:#FFF; padding:20upx;">  
                <text>  
                    UID:{{UID}}  
                    {{tip}}  
                </text>  
            </view>  
        </view>  
    </view>  
</template>  

<script>  
    var NfcAdapter;  
    export default {  
        data() {  
            return {  
                title: 'redNFC',  
                UID: '',  
                msg: '',  
                tip: '',  
            }  
        },  
        onLoad() {  
            console.log("onLoad");  

        },  
        onShow() {  
            console.log("onShow");  
            this.NFCInit();  
        },  
        onHide() {  
            console.log("onHide");  
            this.NFCReadUID();  
        },  
        methods: {  
            NFCInit() {  
                try {  
                    var main = plus.android.runtimeMainActivity();  
                    //console.log(main);  
                    var Intent = plus.android.importClass('android.content.Intent');  
                    // console.log(Intent);  
                    var Activity = plus.android.importClass('android.app.Activity');  
                    //console.log(Activity);  
                    var PendingIntent = plus.android.importClass('android.app.PendingIntent');  
                    // console.log(PendingIntent);                    
                    var IntentFilter = plus.android.importClass('android.content.IntentFilter');  
                    // console.log(IntentFilter);  
                    // var Uri = plus.android.importClass('android.net.Uri');                     
                    // var Bundle = plus.android.importClass('android.os.Bundle');                    
                    // var Handler = plus.android.importClass('android.os.Handler');  
                    //console.log(Handler);  
                    NfcAdapter = plus.android.importClass('android.nfc.NfcAdapter');  
                    //console.log(NfcAdapter);  
                    var _nfcAdapter = NfcAdapter.getDefaultAdapter(main)  
                    // console.log(_nfcAdapter);  

                    var ndef = new IntentFilter("android.nfc.action.NDEF_DISCOVERED"); //NfcAdapter.ACTION_NDEF_DISCOVERED  
                    // console.log(ndef);  
                    var tag = new IntentFilter("android.nfc.action.TAG_DISCOVERED"); //NfcAdapter.ACTION_TECH_DISCOVERED  
                    // console.log(tag);  
                    var tech = new IntentFilter("android.nfc.action.TECH_DISCOVERED");  
                    // console.log(tech);  
                    var intentFiltersArray = [ndef, tag, tech];  

                    var techListsArray = [  
                        ["android.nfc.tech.Ndef"],  
                        ["android.nfc.tech.IsoDep"],  
                        ["android.nfc.tech.NfcA"],  
                        ["android.nfc.tech.NfcB"],  
                        ["android.nfc.tech.NfcF"],  
                        ["android.nfc.tech.Nfcf"],  
                        ["android.nfc.tech.NfcV"],  
                        ["android.nfc.tech.NdefFormatable"],  
                        ["android.nfc.tech.MifareClassi"],  
                        ["android.nfc.tech.MifareUltralight"]  
                    ];  

                    var _intent = new Intent(main, main.getClass());  
                    // console.log(_intent);  
                    _intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);  

                    var pendingIntent = PendingIntent.getActivity(main, 0, _intent, 0);  
                    // console.log(pendingIntent);  

                    if (_nfcAdapter == null) {  
                        this.tip = '本设备不支持NFC!';  
                    } else if (_nfcAdapter.isEnabled() == false) {  
                        this.tip = 'NFC功能未打开!';  
                    } else {  
                        this.tip = 'NFC正常';  
                        _nfcAdapter.enableForegroundDispatch(main, pendingIntent, IntentFilter, techListsArray);  
                    }  
                } catch (e) {  
                    //TODO handle the exception  
                }  
            },  
            NFCReadUID() {  
                var main = plus.android.runtimeMainActivity();  
                var _intent = main.getIntent();  
                var _action = _intent.getAction();  
                // console.log("action type:" + _action);  

                if (NfcAdapter.ACTION_NDEF_DISCOVERED == _action || NfcAdapter.ACTION_TAG_DISCOVERED == _action || NfcAdapter.ACTION_TECH_DISCOVERED ==  
                    _action) {  
                    var Tag = plus.android.importClass('android.nfc.Tag');  
                    var tagFromIntent = _intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);  
                    var uid = _intent.getByteArrayExtra(NfcAdapter.EXTRA_ID);  
                    console.log(uid);  
                    this.UID = this.Bytes2HexString(uid);  
                    //console.log(this.UID);  
                }  
            },  
            //将byte[] 转为Hex,  
            Bytes2HexString(arrBytes) {  
                var str = "";  
                for (var i = 0; i < arrBytes.length; i++) {  
                    var tmp;  
                    var num = arrBytes[i];  
                    if (num < 0) {  
                        //Java中数值是以补码的形式存在的,应用程序展示的十进制是补码对应真值。补码的存在主要为了简化计算机底层的运算,将减法运算直接当加法来做  
                        tmp = (255 + num + 1).toString(16);  
                    } else {  
                        tmp = num.toString(16);  
                    }  
                    if (tmp.length == 1) {  
                        tmp = "0" + tmp;  
                    }  
                    str += tmp;  
                }  
                return str;  
            }  
        }  
    }  
</script>  

<style>  

</style>  
收起阅读 »

Android Studio离线打包 替换新版本过程记录

uniapp离线打包

1.更新HBuilderX至最新版本,本地打包项目目录
2.下载官方最新SDK
3.打开AndroidStudio 导入SDK中 HBuilder-Hello目录(可自行修改名称)

  1. 替换app -> assets-> apps 目录下的文件包为自己的项目包
  2. 修改app -> assets-> data -> dcloud_control.xml文件 appid => 项目ID appver = "1.0.0"
  3. 修改AndroidMenifest.xml文件
  4. 修改build.grandle
  5. 修改 icon splash push 等图片
继续阅读 »

1.更新HBuilderX至最新版本,本地打包项目目录
2.下载官方最新SDK
3.打开AndroidStudio 导入SDK中 HBuilder-Hello目录(可自行修改名称)

  1. 替换app -> assets-> apps 目录下的文件包为自己的项目包
  2. 修改app -> assets-> data -> dcloud_control.xml文件 appid => 项目ID appver = "1.0.0"
  3. 修改AndroidMenifest.xml文件
  4. 修改build.grandle
  5. 修改 icon splash push 等图片
收起阅读 »

ajax请求的上拉加载更多案例

ajax mui
页面用的是jsp
<div class="mui-off-canvas-wrap mui-draggable">  
        <div class="mui-inner-wrap">  
            <!-- <header class="mui-bar mui-bar-nav">   
                <h1 class="mui-title"></h1>  
            </header> -->  
            <div id="pullrefresh" class="mui-content mui-scroll-wrapper">  
                <div class="mui-scroll">  
                    <ul class="mui-table-view">  
                        <li class="mui-table-view-cell" style="text-align: center;" id="total" value="${total/100}">  
                            合计:¥${total/100 }  
                        </li>  
                    </ul>  
                    <ul class="mui-table-view" id="ulId">  
                        <c:forEach items="${checks}" var="check">  
                            <li class="mui-table-view-cell" id="list${check.id }" value="${check.id}" onclick="detail(${check.id})">  
                                <p class="mui-badge">¥${check.money/100}</p> ${check.remark}  
                                <p class="mui-ellipsis">车牌号:${check.carId}</p>  
                                <p class='mui-ellipsis' id="createDate"><fmt:formatDate value="${check.create_date}" pattern="yyyy-MM-dd HH:mm:ss" /></p>  
                            </li>  
                        </c:forEach>  
                    </ul>  
                </div>  
            </div>  
        </div>  
    </div>  
    <script src="<%=basePath%>open/js/mui.min.js"></script>  
    <script type="text/javascript">  
            mui.init({  
              pullRefresh : {  
                container : "#pullrefresh",//待刷新区域标识,querySelector能定位的css选择器均可,比如:id、.class等  
                up : {  
                  contentrefresh : "正在加载...",//可选,正在加载状态时,上拉加载控件上显示的标题内容  
                  callback : getCheckInfo //必选,刷新函数,根据具体业务来编写,比如通过ajax从服务器获取新数据;  
                }  
              }  
            });  
            var page = 1;  

            // 上拉加载操作  
            function getCheckInfo() {  
                page++;  
                mui.ajax('url?token=<%=token%>&page=' + page, {  
                        dataType: 'json', //服务器返回json格式数据  
                        type: 'POST', //HTTP请求类型  
                        timeout: 10000, //超时时间设置为10秒;  
                        headers: {  
                            'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'  
                        },  
                        success: function(data) {  
                            setTimeout(function() {  
                                mui('#pullrefresh').pullRefresh().endPullupToRefresh((data.data.length==0)); // 参数为true代表没有更多数据了。  
                                var table = document.body.querySelector('#ulId');  
                                var cells = document.body.querySelectorAll('.mui-table-view-cell');  
                                var result = data.data;  
                                for (var i = 0; i < result.length; i++) {  
                                    var li = document.createElement('li');  
                                    li.className = 'mui-table-view-cell';  
                                    li.id = 'list' + result[i].id;  
                                    li.value = result[i].id;  
                                    li.innerHTML = '<p class="mui-badge">¥' + result[i].money/100 + '</p>' +  result[i].remark + '<p class="mui-ellipsis">车牌号:' + result[i].carId + '</p><p class="mui-ellipsis" id="createDate">' + result[i].create_date + '</p>';  
                                    table.appendChild(li);  
                                }  
                            },1500);  
                        },  
                        error: function(xhr, type, errorThrown) {  
                            console.log(errorThrown);  
                        }  
                    });  
            }  
            mui.init({  
              gestureConfig:{  
               tap: true, //默认为true  
               doubletap: true, //默认为false  
               longtap: true, //默认为false  
               swipe: true, //默认为true  
               drag: true, //默认为true  
               hold:false,//默认为false,不监听  
               release:false//默认为false,不监听  
              }  
            });  
            mui("#ulId").on("longtap","li",function(list) {  
                // 逻辑代码,例如跳转详情页、ajax  
                    mui.confirm( "是否删除该记录?", "提示", ["是", "否"], function(e) {  
                    if (e.index == 0) {  
                    if (list.path[1].value == undefined) {  
                        delCheck(list.path[0].value);  
                    } else {  
                        delCheck(list.path[1].value);  
                    }  

                    }  
                });  
            });  

            // 执行删除操作  
            function delCheck(id) {  
                mui.ajax('url?token=<%=token%>&id=' + id, {  
                    dataType: 'json', //服务器返回json格式数据  
                    type: 'POST', //HTTP请求类型  
                    timeout: 10000, //超时时间设置为10秒;  
                    headers: {  
                        'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'  
                    },  
                    success: function(data) {  
                        var total = data.data/100;  
                        if (parseInt(total, 10) === total) {  
                            total = total + '.0';  
                        }  
                        document.getElementById("list" + id).remove();  
                        mui.alert("删除成功!", "提示", "确定");  
                        document.getElementById("total").innerHTML = "合计:¥" + total;  
                        document.getElementById("total").value = total;  
                    },  
                    error: function(xhr, type, errorThrown) {  
                        console.log(errorThrown);  
                    }  
                });  
            };  
        </script>
继续阅读 »
页面用的是jsp
<div class="mui-off-canvas-wrap mui-draggable">  
        <div class="mui-inner-wrap">  
            <!-- <header class="mui-bar mui-bar-nav">   
                <h1 class="mui-title"></h1>  
            </header> -->  
            <div id="pullrefresh" class="mui-content mui-scroll-wrapper">  
                <div class="mui-scroll">  
                    <ul class="mui-table-view">  
                        <li class="mui-table-view-cell" style="text-align: center;" id="total" value="${total/100}">  
                            合计:¥${total/100 }  
                        </li>  
                    </ul>  
                    <ul class="mui-table-view" id="ulId">  
                        <c:forEach items="${checks}" var="check">  
                            <li class="mui-table-view-cell" id="list${check.id }" value="${check.id}" onclick="detail(${check.id})">  
                                <p class="mui-badge">¥${check.money/100}</p> ${check.remark}  
                                <p class="mui-ellipsis">车牌号:${check.carId}</p>  
                                <p class='mui-ellipsis' id="createDate"><fmt:formatDate value="${check.create_date}" pattern="yyyy-MM-dd HH:mm:ss" /></p>  
                            </li>  
                        </c:forEach>  
                    </ul>  
                </div>  
            </div>  
        </div>  
    </div>  
    <script src="<%=basePath%>open/js/mui.min.js"></script>  
    <script type="text/javascript">  
            mui.init({  
              pullRefresh : {  
                container : "#pullrefresh",//待刷新区域标识,querySelector能定位的css选择器均可,比如:id、.class等  
                up : {  
                  contentrefresh : "正在加载...",//可选,正在加载状态时,上拉加载控件上显示的标题内容  
                  callback : getCheckInfo //必选,刷新函数,根据具体业务来编写,比如通过ajax从服务器获取新数据;  
                }  
              }  
            });  
            var page = 1;  

            // 上拉加载操作  
            function getCheckInfo() {  
                page++;  
                mui.ajax('url?token=<%=token%>&page=' + page, {  
                        dataType: 'json', //服务器返回json格式数据  
                        type: 'POST', //HTTP请求类型  
                        timeout: 10000, //超时时间设置为10秒;  
                        headers: {  
                            'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'  
                        },  
                        success: function(data) {  
                            setTimeout(function() {  
                                mui('#pullrefresh').pullRefresh().endPullupToRefresh((data.data.length==0)); // 参数为true代表没有更多数据了。  
                                var table = document.body.querySelector('#ulId');  
                                var cells = document.body.querySelectorAll('.mui-table-view-cell');  
                                var result = data.data;  
                                for (var i = 0; i < result.length; i++) {  
                                    var li = document.createElement('li');  
                                    li.className = 'mui-table-view-cell';  
                                    li.id = 'list' + result[i].id;  
                                    li.value = result[i].id;  
                                    li.innerHTML = '<p class="mui-badge">¥' + result[i].money/100 + '</p>' +  result[i].remark + '<p class="mui-ellipsis">车牌号:' + result[i].carId + '</p><p class="mui-ellipsis" id="createDate">' + result[i].create_date + '</p>';  
                                    table.appendChild(li);  
                                }  
                            },1500);  
                        },  
                        error: function(xhr, type, errorThrown) {  
                            console.log(errorThrown);  
                        }  
                    });  
            }  
            mui.init({  
              gestureConfig:{  
               tap: true, //默认为true  
               doubletap: true, //默认为false  
               longtap: true, //默认为false  
               swipe: true, //默认为true  
               drag: true, //默认为true  
               hold:false,//默认为false,不监听  
               release:false//默认为false,不监听  
              }  
            });  
            mui("#ulId").on("longtap","li",function(list) {  
                // 逻辑代码,例如跳转详情页、ajax  
                    mui.confirm( "是否删除该记录?", "提示", ["是", "否"], function(e) {  
                    if (e.index == 0) {  
                    if (list.path[1].value == undefined) {  
                        delCheck(list.path[0].value);  
                    } else {  
                        delCheck(list.path[1].value);  
                    }  

                    }  
                });  
            });  

            // 执行删除操作  
            function delCheck(id) {  
                mui.ajax('url?token=<%=token%>&id=' + id, {  
                    dataType: 'json', //服务器返回json格式数据  
                    type: 'POST', //HTTP请求类型  
                    timeout: 10000, //超时时间设置为10秒;  
                    headers: {  
                        'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'  
                    },  
                    success: function(data) {  
                        var total = data.data/100;  
                        if (parseInt(total, 10) === total) {  
                            total = total + '.0';  
                        }  
                        document.getElementById("list" + id).remove();  
                        mui.alert("删除成功!", "提示", "确定");  
                        document.getElementById("total").innerHTML = "合计:¥" + total;  
                        document.getElementById("total").value = total;  
                    },  
                    error: function(xhr, type, errorThrown) {  
                        console.log(errorThrown);  
                    }  
                });  
            };  
        </script>
收起阅读 »

优秀的前端工程师找兼职

招聘 外包

我有4年前端开发经验,大学软件工程专业。

个人前端分享:
uni-app插件主页:https://ext.dcloud.net.cn/publisher?id=110853
jQuery插件主页:http://www.jq22.com/mem395541
CSDN-博客主页:https://blog.csdn.net/u013350495

掌握HTML5,CSS3,js,es6,Node.js,jQuery,Vue.js,小程序,Dcloud,APICloud技术。
掌握Bootstrap,layui,Element UI,YDUI等框架。

能手写响应式布局,弹性布局框架。能手写jQuery插件。精通工厂/构造/原型开发模式。

大学所学科目:C,JAVA,C#,ASP.NET,SQL server,my sql,软件工程,软件架构,软件测试,网络,信息安全,操作系统。

有良好的软件架构意识,有良好的沟通表达能力,有良好的团队合作意识,有良好的程序逻辑思维,以往合作过的客户评价良好。

联系方式:
QQ:1846492969,
邮箱:helang.love@qq.com

继续阅读 »

我有4年前端开发经验,大学软件工程专业。

个人前端分享:
uni-app插件主页:https://ext.dcloud.net.cn/publisher?id=110853
jQuery插件主页:http://www.jq22.com/mem395541
CSDN-博客主页:https://blog.csdn.net/u013350495

掌握HTML5,CSS3,js,es6,Node.js,jQuery,Vue.js,小程序,Dcloud,APICloud技术。
掌握Bootstrap,layui,Element UI,YDUI等框架。

能手写响应式布局,弹性布局框架。能手写jQuery插件。精通工厂/构造/原型开发模式。

大学所学科目:C,JAVA,C#,ASP.NET,SQL server,my sql,软件工程,软件架构,软件测试,网络,信息安全,操作系统。

有良好的软件架构意识,有良好的沟通表达能力,有良好的团队合作意识,有良好的程序逻辑思维,以往合作过的客户评价良好。

联系方式:
QQ:1846492969,
邮箱:helang.love@qq.com

收起阅读 »

un-app uni.navigateTo页面跳转做封装传参

uniapp

uni-app在页面跳转的时候是可以传参的,官方给的方法就是在路由后拼接传参地址

uni.navigateTo(OBJECT)

对于做开发的这种传参不太习惯,还是习惯了用一个字典作为传参数据
下面对uni.navigateTo做一下封装并带参数封装
首先单独写一个js文件用来封装页面跳转(注意:动画那些没有写进来,如果想要可以自己加)

navTo.js

const togo = function(url,data){  
    url += (url.indexOf('?') < 0 ? '?' : '&') + param(data)  

    uni.navigateTo({    
        url  
    })   
}  

export function param(data) {  
  let url = ''  
  for (var k in data) {  
    let value = data[k] !== undefined ? data[k] : ''  
    url += '&' + k + '=' + encodeURIComponent(value)  
  }  
  return url ? url.substring(1) : ''  
}  

exprot {togo}

然后在main.js中注册全局变量

import * as navTo from '@/assets/navTo'  
Vue.prototype.$navTo = navTo

最后调用(在vue页面)

<view @click="$navTo.togo('/pages/index/index',{type:1,name:'YanGo'})"></view>  

//或者在methods钩子也可以  

methods: {  
    to(){  
        let url = '/pages/index/index'  
        let param = {  
            type:1,  
            name: 'YanGo'  
        }  
        this.$navTo.togo(url,param)  
    }  
}
继续阅读 »

uni-app在页面跳转的时候是可以传参的,官方给的方法就是在路由后拼接传参地址

uni.navigateTo(OBJECT)

对于做开发的这种传参不太习惯,还是习惯了用一个字典作为传参数据
下面对uni.navigateTo做一下封装并带参数封装
首先单独写一个js文件用来封装页面跳转(注意:动画那些没有写进来,如果想要可以自己加)

navTo.js

const togo = function(url,data){  
    url += (url.indexOf('?') < 0 ? '?' : '&') + param(data)  

    uni.navigateTo({    
        url  
    })   
}  

export function param(data) {  
  let url = ''  
  for (var k in data) {  
    let value = data[k] !== undefined ? data[k] : ''  
    url += '&' + k + '=' + encodeURIComponent(value)  
  }  
  return url ? url.substring(1) : ''  
}  

exprot {togo}

然后在main.js中注册全局变量

import * as navTo from '@/assets/navTo'  
Vue.prototype.$navTo = navTo

最后调用(在vue页面)

<view @click="$navTo.togo('/pages/index/index',{type:1,name:'YanGo'})"></view>  

//或者在methods钩子也可以  

methods: {  
    to(){  
        let url = '/pages/index/index'  
        let param = {  
            type:1,  
            name: 'YanGo'  
        }  
        this.$navTo.togo(url,param)  
    }  
}
收起阅读 »

uni-app 设置tabBar后ios底部被tab遮挡的解决方案

uniapp

在配置原生tabBar后发现ios端的tab页面底部被遮挡了,也不知道怎么原因,后来在pages.json把globalStyle.app-plus设置的"background": "#f5f5f5"去掉就好了,很奇怪,还不知道怎么原因,如果有知道原因的童鞋欢迎指点一下


"globalStyle": {  
    "app-plus": {  
        // "background": "#f5f5f5"  
    }  
}

把 "background": "#f5f5f5"去掉就好了,有遇到的童鞋可以试试。

继续阅读 »

在配置原生tabBar后发现ios端的tab页面底部被遮挡了,也不知道怎么原因,后来在pages.json把globalStyle.app-plus设置的"background": "#f5f5f5"去掉就好了,很奇怪,还不知道怎么原因,如果有知道原因的童鞋欢迎指点一下


"globalStyle": {  
    "app-plus": {  
        // "background": "#f5f5f5"  
    }  
}

把 "background": "#f5f5f5"去掉就好了,有遇到的童鞋可以试试。

收起阅读 »

为什么 阿里巴巴图标库 引用进来的字体 无法使用 iconfont无法使用

字体

这个原因我找了好久,之前的文件引入可以用,新的文件用不了,我一直在往iconfont里面加图标

社区搜了好多文章,后面看到了一个官方的回复

就是这个

“40k以下的,uni-app会自动转base64” 划重点

好吧 我一直往里面加图标结果文件越来越大,之前可以用是因为小于40k 自动转换了,大于40k怎么办 我分了两个文件引入,没办法 人比较懒

继续阅读 »

这个原因我找了好久,之前的文件引入可以用,新的文件用不了,我一直在往iconfont里面加图标

社区搜了好多文章,后面看到了一个官方的回复

就是这个

“40k以下的,uni-app会自动转base64” 划重点

好吧 我一直往里面加图标结果文件越来越大,之前可以用是因为小于40k 自动转换了,大于40k怎么办 我分了两个文件引入,没办法 人比较懒

收起阅读 »

谈一下uniapp,自定义camera,来进行人脸识别的

uniapp模板 uniapp uniapp插件 Camera

本人,小白一个,大神可忽略本内容

由于uniapp,在打包成APP的时候不能自定义相机,很多人脸识别的项目,在APP里面只能使用原生,本人也不会原生,很是苦逼,很羡慕能开发原生的,但是也想搞一下人脸识别,迫于无奈,研究属于自己的一套,h5的人脸识别,喜欢的可以研究研究。

自定义相机启动界面

自定义摄像头界面大小,遮罩等

人脸放到框内,自动拍照,保存base64,也快手动拍照

识别到人脸以后,大家可以自行发挥了,如,人脸对比等...

<script>

    //激活摄像头  
    navigator.getUserMedia  = navigator.getUserMedia ||  
      navigator.webkitGetUserMedia ||  
      navigator.mozGetUserMedia ||  
      navigator.msGetUserMedia;  
    navigator.getUserMedia({video:true}, gotStream, noStream);  

    function gotStream(stream) {  
      myVideo.src = URL.createObjectURL(stream);  
      myVideo.onerror = function () {  
        stream.stop();  
      };  
      stream.onended = noStream;  
      myVideo.onloadedmetadata = function () {  
        console.log('摄像头成功打开!');  
      };  
    }  

    function noStream(err){  
        console.log(err);  
    }  

    //激活摄像头end  
    var saveArray = {};  
    window.onload = function () {  
        var video = document.getElementById('video');  
        var canvas = document.getElementById('canvas');  
        var context = canvas.getContext('2d');  

        var tracker = new tracking.ObjectTracker('face');  
        tracker.setInitialScale(4);  
        tracker.setStepSize(2);  
        tracker.setEdgesDensity(0.1);  

        tracking.track('#video', tracker, {camera: true});  

        tracker.on('track', function (event) {  
            context.clearRect(0, 0, canvas.width, canvas.height);  

            event.data.forEach(function (rect) {  
                context.strokeStyle = '#fff';  
                context.strokeRect(rect.x, rect.y, rect.width, rect.height);  
                //context.font = '11px Helvetica';   
                context.fillStyle = "#fff";  

                   context.fillText('x: ' + rect.x + 'px', rect.x + rect.width + 5, rect.y + 11);  
                   context.fillText('y: ' + rect.y + 'px', rect.x + rect.width + 5, rect.y + 22);  

                saveArray.x = rect.x;  
                saveArray.y = rect.y;  
                saveArray.width = rect.width;  
                saveArray.height = rect.height;  

            });  
        });  
        setInterval(function () {    
            //console.log(saveArray);  
            if (saveArray.x > 80 &&  
                    saveArray.x + saveArray.width < 260 &&  
                    saveArray.y > 90 &&  
                    saveArray.y + saveArray.height < 260 &&  
                    saveArray.width < 150  
                    && saveArray.height < 150) {  
                console.log(saveArray);  
                getPhoto();  
                for (var key in saveArray) {  
                    delete saveArray[key];  
                }  
            }   
        }, 2000);  
        function getPhoto() {  

            context2.drawImage(video, 100, 120, 260, 380, 0, 0, 170, 255); //将video对象内指定的区域捕捉绘制到画布上指定的区域,实现拍照。  

        }  

        var btn = document.getElementById("btn");  
        btn.onclick= function () {  
            getPhoto();  
        }  

        var canvas1 = document.getElementById('canvas1');  
        var context1 = canvas1.getContext('2d');  
        var can = document.getElementById('shortCut');  
        var context2 = can.getContext('2d');  
        context1.strokeStyle = "#69fff1";  
          context1.moveTo(63, 66); //上线 x,y  
          context1.lineTo(257, 66); //右  
          context1.lineTo(257, 321); //下  
          context1.lineTo(63, 321);//左  
          context1.lineTo(63, 66);//左  
        context1.stroke();  

        var img = document.getElementById("img")  

        function convertCanvasToImage(canvas) {  
            var image = new Image();  
            image.src = canvas.toDataURL("image/png");  
            return image;  
        }  

        var keepImg = document.getElementById("keepImg");  
        keepImg.onclick = function () {  
            var photoImg = document.createElement("img");  
            photoImg.src = convertCanvasToImage(can).src;  
            img.appendChild(photoImg);  

            console.log(convertCanvasToImage(can).src);  
        }  

    };  

</script>  
继续阅读 »

本人,小白一个,大神可忽略本内容

由于uniapp,在打包成APP的时候不能自定义相机,很多人脸识别的项目,在APP里面只能使用原生,本人也不会原生,很是苦逼,很羡慕能开发原生的,但是也想搞一下人脸识别,迫于无奈,研究属于自己的一套,h5的人脸识别,喜欢的可以研究研究。

自定义相机启动界面

自定义摄像头界面大小,遮罩等

人脸放到框内,自动拍照,保存base64,也快手动拍照

识别到人脸以后,大家可以自行发挥了,如,人脸对比等...

<script>

    //激活摄像头  
    navigator.getUserMedia  = navigator.getUserMedia ||  
      navigator.webkitGetUserMedia ||  
      navigator.mozGetUserMedia ||  
      navigator.msGetUserMedia;  
    navigator.getUserMedia({video:true}, gotStream, noStream);  

    function gotStream(stream) {  
      myVideo.src = URL.createObjectURL(stream);  
      myVideo.onerror = function () {  
        stream.stop();  
      };  
      stream.onended = noStream;  
      myVideo.onloadedmetadata = function () {  
        console.log('摄像头成功打开!');  
      };  
    }  

    function noStream(err){  
        console.log(err);  
    }  

    //激活摄像头end  
    var saveArray = {};  
    window.onload = function () {  
        var video = document.getElementById('video');  
        var canvas = document.getElementById('canvas');  
        var context = canvas.getContext('2d');  

        var tracker = new tracking.ObjectTracker('face');  
        tracker.setInitialScale(4);  
        tracker.setStepSize(2);  
        tracker.setEdgesDensity(0.1);  

        tracking.track('#video', tracker, {camera: true});  

        tracker.on('track', function (event) {  
            context.clearRect(0, 0, canvas.width, canvas.height);  

            event.data.forEach(function (rect) {  
                context.strokeStyle = '#fff';  
                context.strokeRect(rect.x, rect.y, rect.width, rect.height);  
                //context.font = '11px Helvetica';   
                context.fillStyle = "#fff";  

                   context.fillText('x: ' + rect.x + 'px', rect.x + rect.width + 5, rect.y + 11);  
                   context.fillText('y: ' + rect.y + 'px', rect.x + rect.width + 5, rect.y + 22);  

                saveArray.x = rect.x;  
                saveArray.y = rect.y;  
                saveArray.width = rect.width;  
                saveArray.height = rect.height;  

            });  
        });  
        setInterval(function () {    
            //console.log(saveArray);  
            if (saveArray.x > 80 &&  
                    saveArray.x + saveArray.width < 260 &&  
                    saveArray.y > 90 &&  
                    saveArray.y + saveArray.height < 260 &&  
                    saveArray.width < 150  
                    && saveArray.height < 150) {  
                console.log(saveArray);  
                getPhoto();  
                for (var key in saveArray) {  
                    delete saveArray[key];  
                }  
            }   
        }, 2000);  
        function getPhoto() {  

            context2.drawImage(video, 100, 120, 260, 380, 0, 0, 170, 255); //将video对象内指定的区域捕捉绘制到画布上指定的区域,实现拍照。  

        }  

        var btn = document.getElementById("btn");  
        btn.onclick= function () {  
            getPhoto();  
        }  

        var canvas1 = document.getElementById('canvas1');  
        var context1 = canvas1.getContext('2d');  
        var can = document.getElementById('shortCut');  
        var context2 = can.getContext('2d');  
        context1.strokeStyle = "#69fff1";  
          context1.moveTo(63, 66); //上线 x,y  
          context1.lineTo(257, 66); //右  
          context1.lineTo(257, 321); //下  
          context1.lineTo(63, 321);//左  
          context1.lineTo(63, 66);//左  
        context1.stroke();  

        var img = document.getElementById("img")  

        function convertCanvasToImage(canvas) {  
            var image = new Image();  
            image.src = canvas.toDataURL("image/png");  
            return image;  
        }  

        var keepImg = document.getElementById("keepImg");  
        keepImg.onclick = function () {  
            var photoImg = document.createElement("img");  
            photoImg.src = convertCanvasToImage(can).src;  
            img.appendChild(photoImg);  

            console.log(convertCanvasToImage(can).src);  
        }  

    };  

</script>  
收起阅读 »