HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

友盟统计事件埋点分享

统计 友盟

因业务需要,我们的app需要继承友盟并且进行事件埋点,涉及电商场景的埋点。
首先,需要在manifest.json文件中勾选统计选项

然后在源码视图中配置从友盟那边申请的appkey,并且输入渠道标识

                    "umeng" : {  
                        "idfa" : true,  
                        "appkey_ios" : "ios的appkey",  
                        "channelid_ios" : "ios的标识",  
                        "appkey_android" : "安卓的appkey",  
                        "channelid_android" : "安卓的标识,可任意输入,用于区分打出来的包,建议用英文"  
                    }

经过测试,plus.statistic.eventTrig可以埋自定义事件的点,但对于电商事件的埋点(友盟规定的事件ID,如:register、finish_payment等)似乎无效。
所以选择用NJS的方式定义了一个函数去调用,使用方式: eventTrig( String类型的事件ID,Object类型的data ) , 以下NJS的代码:


function eventTrig( eventId , data ){  
    // #ifdef APP-PLUS  
        let isios = uni.getSystemInfoSync().platform == 'ios'  
        if( isios ) plus.ios.invoke('MobClick','event:attributes:',eventId,data)  
        else{  
            let HashMap = plus.android.importClass('java.util.HashMap')  
            let hashData = new HashMap()  
            for(let key in data ){  
                hashData.put( String(key),String(data[key]) )  
            }  
            let main = plus.android.runtimeMainActivity()  
            let MobclickAgent = plus.android.importClass('com.umeng.analytics.MobclickAgent')  
            MobclickAgent.onEvent(main,String(eventId),hashData)  
        }  
    // #endif  
    // #ifndef APP-PLUS  
    console.log(...arguments)  
    // #endif  
}  

经过不严谨的测试,目前使用起来是没有发现问题的,有其他需要或是有发现bug的小伙伴可自行改造哈。

继续阅读 »

因业务需要,我们的app需要继承友盟并且进行事件埋点,涉及电商场景的埋点。
首先,需要在manifest.json文件中勾选统计选项

然后在源码视图中配置从友盟那边申请的appkey,并且输入渠道标识

                    "umeng" : {  
                        "idfa" : true,  
                        "appkey_ios" : "ios的appkey",  
                        "channelid_ios" : "ios的标识",  
                        "appkey_android" : "安卓的appkey",  
                        "channelid_android" : "安卓的标识,可任意输入,用于区分打出来的包,建议用英文"  
                    }

经过测试,plus.statistic.eventTrig可以埋自定义事件的点,但对于电商事件的埋点(友盟规定的事件ID,如:register、finish_payment等)似乎无效。
所以选择用NJS的方式定义了一个函数去调用,使用方式: eventTrig( String类型的事件ID,Object类型的data ) , 以下NJS的代码:


function eventTrig( eventId , data ){  
    // #ifdef APP-PLUS  
        let isios = uni.getSystemInfoSync().platform == 'ios'  
        if( isios ) plus.ios.invoke('MobClick','event:attributes:',eventId,data)  
        else{  
            let HashMap = plus.android.importClass('java.util.HashMap')  
            let hashData = new HashMap()  
            for(let key in data ){  
                hashData.put( String(key),String(data[key]) )  
            }  
            let main = plus.android.runtimeMainActivity()  
            let MobclickAgent = plus.android.importClass('com.umeng.analytics.MobclickAgent')  
            MobclickAgent.onEvent(main,String(eventId),hashData)  
        }  
    // #endif  
    // #ifndef APP-PLUS  
    console.log(...arguments)  
    // #endif  
}  

经过不严谨的测试,目前使用起来是没有发现问题的,有其他需要或是有发现bug的小伙伴可自行改造哈。

收起阅读 »

高颜值、高品质组件库——FirstUI,快来体验一把!

自定义组件 全局组件 小程序组件 ui组件

1、产品特征:

FirstUI(https://www.firstui.cn/)

  • 多端支持。一套代码,多端适用,支持iOS(vue和Nvue)、Android(vue和Nvue)、微信小程序、支付宝小程序、QQ小程序、百度小程序、字节跳动小程序、H5平台
  • 完善的组件。目前共规划118款,已上线70款,涵盖基础组件、表单组件、导航组件、布局组件、常用布局、扩展组件、操作反馈、数据组件、JS、图表、画布。
  • 丰富实用的布局、模板。基于FirstUI提供的组件,针对常用场景、行业,提供丰富实用的布局和模板。
  • 专属社区。我们用flarum(ps:这个大家也可以试下,设计与功能方面好用,感觉用来做社区非常棒)打造了FirstU专属社区(https://forum.firstui.cn/),用户可以在社区交流分享FirstUI的使用经验、提问。有其他组件、模板需求,也可以在社区中反馈。

2、源码及文档:

3、扫码体验:

大部分组件是操作性的,大家扫码操作可以有更真切的感受。目前发布了6个平台版本,大家可以扫码体验下。考虑快速预览,所以暂未上架App应用,后续待功能完善再进行上架。

已上线功能清单:

  • 框架
    • FirstUI组件库(uni-app版)
  • 模板
    • 登录(A)模板
    • 登录(B)模板
    • 登录(C)模板
    • 登录(D)模板
    • 门户模板
  • 组件
    • 基础组件
    • Color 色彩
    • Icon 图标
    • Button 按钮
    • Footer 页脚
    • Animation 动画
    • 导航组件
    • NavBar 导航栏
    • Pagination 分页器
    • SegmentedControl 分段器
    • Tabbar 标签栏
    • Tabs 标签页
    • IndexList 索引列表
    • NoticeBar 通告栏
    • Sticky 吸顶容器
    • Steps 步骤条
    • Fab 浮动按钮
    • Drawer 抽屉
    • BottomPopup 底部弹出层
    • TopPopup 顶部弹出层
    • TimeAxis 时间轴
    • 布局组件
    • Layout 栅格布局
    • Panel 面板
    • Preview 表单预览
    • List 列表
    • Card 卡片
    • 扩展组件
    • ShareSheet 分享面板
    • Result 结果页
    • FilterBar 筛选栏
    • DigitalRoller 数字滚轮
    • DigitalKeyboard 数字键盘
    • CountdownVerify 验证码倒计时
    • SwiperDot 轮播图指示点
    • LicensePlate 车牌号键盘
    • SingleInput 单输入框
    • 操作反馈
    • ActionSheet 上拉菜单
    • Toast 轻提示
    • BackDrop 遮罩层
    • Dialog 对话框
    • DropdownMenu 下拉菜单
    • Modal 模态框
    • Landscape 压屏窗
    • Loading 加载
    • Message 消息提示
    • SwipeAction 滑动菜单
    • DropdownList 下拉菜单
    • LoadAni 加载动画
    • 数据组件
    • Badge 徽章
    • Alert 警告框
    • Avatar 头像
    • Tag 标签
    • Progress 进度条
    • Collapse 折叠面板
    • Divider 分割线
    • LoadMore 加载更多
    • Empty 暂无数据
    • 画布
    • Poster 绘制分享海报
    • 表单组件
    • Picker 选择器
    • DatePicker 日期时间选择器
    • Form 表单校验
    • Input 输入框
    • InputNumber 数字输入框
    • Radio 单选框
    • Checkbox 复选框
    • Switch 开关
    • Textarea 多行输入框
    • SearchBar 搜索栏
    • JS
    • Clipboard 复制文本
    • Request 网络请求
    • Utils 工具类
    • Validator 表单验证
继续阅读 »

1、产品特征:

FirstUI(https://www.firstui.cn/)

  • 多端支持。一套代码,多端适用,支持iOS(vue和Nvue)、Android(vue和Nvue)、微信小程序、支付宝小程序、QQ小程序、百度小程序、字节跳动小程序、H5平台
  • 完善的组件。目前共规划118款,已上线70款,涵盖基础组件、表单组件、导航组件、布局组件、常用布局、扩展组件、操作反馈、数据组件、JS、图表、画布。
  • 丰富实用的布局、模板。基于FirstUI提供的组件,针对常用场景、行业,提供丰富实用的布局和模板。
  • 专属社区。我们用flarum(ps:这个大家也可以试下,设计与功能方面好用,感觉用来做社区非常棒)打造了FirstU专属社区(https://forum.firstui.cn/),用户可以在社区交流分享FirstUI的使用经验、提问。有其他组件、模板需求,也可以在社区中反馈。

2、源码及文档:

3、扫码体验:

大部分组件是操作性的,大家扫码操作可以有更真切的感受。目前发布了6个平台版本,大家可以扫码体验下。考虑快速预览,所以暂未上架App应用,后续待功能完善再进行上架。

已上线功能清单:

  • 框架
    • FirstUI组件库(uni-app版)
  • 模板
    • 登录(A)模板
    • 登录(B)模板
    • 登录(C)模板
    • 登录(D)模板
    • 门户模板
  • 组件
    • 基础组件
    • Color 色彩
    • Icon 图标
    • Button 按钮
    • Footer 页脚
    • Animation 动画
    • 导航组件
    • NavBar 导航栏
    • Pagination 分页器
    • SegmentedControl 分段器
    • Tabbar 标签栏
    • Tabs 标签页
    • IndexList 索引列表
    • NoticeBar 通告栏
    • Sticky 吸顶容器
    • Steps 步骤条
    • Fab 浮动按钮
    • Drawer 抽屉
    • BottomPopup 底部弹出层
    • TopPopup 顶部弹出层
    • TimeAxis 时间轴
    • 布局组件
    • Layout 栅格布局
    • Panel 面板
    • Preview 表单预览
    • List 列表
    • Card 卡片
    • 扩展组件
    • ShareSheet 分享面板
    • Result 结果页
    • FilterBar 筛选栏
    • DigitalRoller 数字滚轮
    • DigitalKeyboard 数字键盘
    • CountdownVerify 验证码倒计时
    • SwiperDot 轮播图指示点
    • LicensePlate 车牌号键盘
    • SingleInput 单输入框
    • 操作反馈
    • ActionSheet 上拉菜单
    • Toast 轻提示
    • BackDrop 遮罩层
    • Dialog 对话框
    • DropdownMenu 下拉菜单
    • Modal 模态框
    • Landscape 压屏窗
    • Loading 加载
    • Message 消息提示
    • SwipeAction 滑动菜单
    • DropdownList 下拉菜单
    • LoadAni 加载动画
    • 数据组件
    • Badge 徽章
    • Alert 警告框
    • Avatar 头像
    • Tag 标签
    • Progress 进度条
    • Collapse 折叠面板
    • Divider 分割线
    • LoadMore 加载更多
    • Empty 暂无数据
    • 画布
    • Poster 绘制分享海报
    • 表单组件
    • Picker 选择器
    • DatePicker 日期时间选择器
    • Form 表单校验
    • Input 输入框
    • InputNumber 数字输入框
    • Radio 单选框
    • Checkbox 复选框
    • Switch 开关
    • Textarea 多行输入框
    • SearchBar 搜索栏
    • JS
    • Clipboard 复制文本
    • Request 网络请求
    • Utils 工具类
    • Validator 表单验证
收起阅读 »

uniapp引入arcgis for js

map 地图

uniapp引入arcgis for js

​ 在前段时间,我刚开始接触uniapp,并接到了在uniapp项目中使用arcgis for js的任务。搜遍了所有的经验帖子也没有一个具体的方法步骤,只有几位大佬分享了可行的结果截图。所以今天写一个小白教程,如有错误,欢迎大家指出。

​ 首先在一个空项目中,引入esri-loader。

npm install--save esri-loader

​ 成功后,在页面中通过renderjs引入esri-loader,注意地图部分需要给出具体高度。

<template>  
    <view >  
        <view id="myMapView" style=" height: 623px " />  
    </view>  
</template>  

<script module="myMapViews" lang="renderjs">  
    //renderjs部分  
    import {  
        loadModules  
    } from 'esri-loader'  
    export default {  
        name: 'myMapView',  
        data() {  
            return {};  
        },  
        mounted() {  
            this.createMapView()  
        },  
        methods: {  
            createMapView() {  
                const options = {  
                    url: 'https://js.arcgis.com/4.14/init.js',  
                    css: 'https://js.arcgis.com/4.14/esri/themes/light/main.css'  
                };  
                loadModules([  
                    "esri/Map",  
                    "esri/views/MapView"  
                ], options).then(([Map, MapView]) => {  
                    var map = new Map({  
                        basemap: "topo-vector"  
                    });  
                    var view = new MapView({  
                        container: "myMapView",  
                        map: map,  
                        center: [-118.80500, 34.02700], // longitude, latitude  
                        zoom: 13  
                    });  
                })  
            }  
        }  
    }  
</script>  

<scrip>  
// service 层  
</scrip>  

<style>  
</style>

效果图如下:

​ 同时,在renderjs的script中,是无法获取到service层的数据的,也无法使用uni的相关接口(注意:H5是可以正常使用的,但是APP端就会报错,比如uni.request等),所以要通过一定的方式从service层去传输。

​ 如果要进行网络请求目前有两种思路:

​ 1.自己写一个原生ajax请求,在renderjs部分使用。

​ 2.在service层给后台发请求后,将数据传回renderjs部分

    下面简单给出个renderjs和service层通讯例子:  
<template>  
    <view>  
        <!-- service层mapdata改变就会调用renderjs部分的mapDataChanged方法 -->  
        <view id="myMapView" :change:mapData="myMapViews.mapDataChanged" :mapData="mapData" style=" height: 500px " />  
        <view>  
            <uni-button @click="changeMapData">service点击</uni-button>  
        </view>  
    </view>  

</template>  

<script module="myMapViews" lang="renderjs">  
    //renderjs部分  
    import {  
        loadModules  
    } from 'esri-loader'  
    export default {  
        name: 'myMapView',  
        data() {  
            return {};  
        },  
        mounted() {  
            this.createMapView()  
        },  
        methods: {  
            createMapView() {  
                const options = {  
                    url: 'https://js.arcgis.com/4.14/init.js',  
                    css: 'https://js.arcgis.com/4.14/esri/themes/light/main.css'  
                };  
                loadModules([  
                    "esri/Map",  
                    "esri/views/MapView"  
                ], options).then(([Map, MapView]) => {  
                    var map = new Map({  
                        basemap: "topo-vector"  
                    });  
                    var view = new MapView({  
                        container: "myMapView",  
                        map: map,  
                        center: [-118.80500, 34.02700], // longitude, latitude  
                        zoom: 13  
                    });  
                })  
            },  
            mapDataChanged(newValue, oldValue, ownerVm, vm) {  
                //mapData改变触发  
                console.log("newValue:", newValue)  
                console.log("oldValue:", oldValue)  
                //调用service层的getFromRenderJs方法,并传值  
                ownerVm.callMethod('getFromRenderJs', {  
                    type: 'polyline'  
                })  
                //这种方法也可以主动调用service层方法  
                /*UniViewJSBridge.publishHandler('onWxsInvokeCallMethod', {  
                    cid: this._$id,  
                    method: 'loadingClose',  
                    args: {  

                    }  
                })*/  
            }  

        }  
    }  

</script>  

<script>  
    //service层  
    export default {  
        data() {  
            return {  
                mapData: {}  
            }  
        },  
        mounted() {},  
        methods: {  
            changeMapData() {  
                //click事件触发的service层方法  
                this.mapData = {  
                    type: 'point'  
                }  
            },  
            getFromRenderJs(params) {  
                //renderjs调用的service层方法  
                console.log('getFromRenderJs:', params)  
            }  

        },  

    }  

</script>  

<style>  
</style>

结果如下:

继续阅读 »

uniapp引入arcgis for js

​ 在前段时间,我刚开始接触uniapp,并接到了在uniapp项目中使用arcgis for js的任务。搜遍了所有的经验帖子也没有一个具体的方法步骤,只有几位大佬分享了可行的结果截图。所以今天写一个小白教程,如有错误,欢迎大家指出。

​ 首先在一个空项目中,引入esri-loader。

npm install--save esri-loader

​ 成功后,在页面中通过renderjs引入esri-loader,注意地图部分需要给出具体高度。

<template>  
    <view >  
        <view id="myMapView" style=" height: 623px " />  
    </view>  
</template>  

<script module="myMapViews" lang="renderjs">  
    //renderjs部分  
    import {  
        loadModules  
    } from 'esri-loader'  
    export default {  
        name: 'myMapView',  
        data() {  
            return {};  
        },  
        mounted() {  
            this.createMapView()  
        },  
        methods: {  
            createMapView() {  
                const options = {  
                    url: 'https://js.arcgis.com/4.14/init.js',  
                    css: 'https://js.arcgis.com/4.14/esri/themes/light/main.css'  
                };  
                loadModules([  
                    "esri/Map",  
                    "esri/views/MapView"  
                ], options).then(([Map, MapView]) => {  
                    var map = new Map({  
                        basemap: "topo-vector"  
                    });  
                    var view = new MapView({  
                        container: "myMapView",  
                        map: map,  
                        center: [-118.80500, 34.02700], // longitude, latitude  
                        zoom: 13  
                    });  
                })  
            }  
        }  
    }  
</script>  

<scrip>  
// service 层  
</scrip>  

<style>  
</style>

效果图如下:

​ 同时,在renderjs的script中,是无法获取到service层的数据的,也无法使用uni的相关接口(注意:H5是可以正常使用的,但是APP端就会报错,比如uni.request等),所以要通过一定的方式从service层去传输。

​ 如果要进行网络请求目前有两种思路:

​ 1.自己写一个原生ajax请求,在renderjs部分使用。

​ 2.在service层给后台发请求后,将数据传回renderjs部分

    下面简单给出个renderjs和service层通讯例子:  
<template>  
    <view>  
        <!-- service层mapdata改变就会调用renderjs部分的mapDataChanged方法 -->  
        <view id="myMapView" :change:mapData="myMapViews.mapDataChanged" :mapData="mapData" style=" height: 500px " />  
        <view>  
            <uni-button @click="changeMapData">service点击</uni-button>  
        </view>  
    </view>  

</template>  

<script module="myMapViews" lang="renderjs">  
    //renderjs部分  
    import {  
        loadModules  
    } from 'esri-loader'  
    export default {  
        name: 'myMapView',  
        data() {  
            return {};  
        },  
        mounted() {  
            this.createMapView()  
        },  
        methods: {  
            createMapView() {  
                const options = {  
                    url: 'https://js.arcgis.com/4.14/init.js',  
                    css: 'https://js.arcgis.com/4.14/esri/themes/light/main.css'  
                };  
                loadModules([  
                    "esri/Map",  
                    "esri/views/MapView"  
                ], options).then(([Map, MapView]) => {  
                    var map = new Map({  
                        basemap: "topo-vector"  
                    });  
                    var view = new MapView({  
                        container: "myMapView",  
                        map: map,  
                        center: [-118.80500, 34.02700], // longitude, latitude  
                        zoom: 13  
                    });  
                })  
            },  
            mapDataChanged(newValue, oldValue, ownerVm, vm) {  
                //mapData改变触发  
                console.log("newValue:", newValue)  
                console.log("oldValue:", oldValue)  
                //调用service层的getFromRenderJs方法,并传值  
                ownerVm.callMethod('getFromRenderJs', {  
                    type: 'polyline'  
                })  
                //这种方法也可以主动调用service层方法  
                /*UniViewJSBridge.publishHandler('onWxsInvokeCallMethod', {  
                    cid: this._$id,  
                    method: 'loadingClose',  
                    args: {  

                    }  
                })*/  
            }  

        }  
    }  

</script>  

<script>  
    //service层  
    export default {  
        data() {  
            return {  
                mapData: {}  
            }  
        },  
        mounted() {},  
        methods: {  
            changeMapData() {  
                //click事件触发的service层方法  
                this.mapData = {  
                    type: 'point'  
                }  
            },  
            getFromRenderJs(params) {  
                //renderjs调用的service层方法  
                console.log('getFromRenderJs:', params)  
            }  

        },  

    }  

</script>  

<style>  
</style>

结果如下:

收起阅读 »

为啥发了一下这个就被踢了呢?


笑死,为啥被踢了呢?


笑死,为啥被踢了呢?

启动图制作:Android Studio制作.9图亲测详细流程之每步图解

详细内容直接打开我的博客进行查看:https://blog.csdn.net/qq_42961150/article/details/121417954?spm=1001.2014.3001.5502

原生安卓开发APP的启动图、 uniapp开发安卓app自定义启动图。制作.9图 的方式也有多种,Android Studio是其中比较常见的一种方式。该方式制作.9图也是我在做uniapp打包app项目过程中亲测完成。。。

继续阅读 »

详细内容直接打开我的博客进行查看:https://blog.csdn.net/qq_42961150/article/details/121417954?spm=1001.2014.3001.5502

原生安卓开发APP的启动图、 uniapp开发安卓app自定义启动图。制作.9图 的方式也有多种,Android Studio是其中比较常见的一种方式。该方式制作.9图也是我在做uniapp打包app项目过程中亲测完成。。。

收起阅读 »

太相信Object.assign了,花了2天时间找到问题。

以下代码,想象一下结果。

    const val = {  
        sex: 0,  
        age: {  
            x: 10  
        }  
    }  
    let a = {};  
    let b = {};  
    let aa = Object.assign(a, val);  
    let bb = Object.assign(b, val);  
    a.sex = 1;  
    a.age.x = 20;  
    console.log(a.sex, b.sex, aa.sex, bb.sex)  
    console.log(a.age.x, b.age.x, aa.age.x, bb.age.x)  

或许是我太low了,之前还从没太在意过这个问题。

改用JSON.parse(JSON.stringify(defaultOrder))

继续阅读 »

以下代码,想象一下结果。

    const val = {  
        sex: 0,  
        age: {  
            x: 10  
        }  
    }  
    let a = {};  
    let b = {};  
    let aa = Object.assign(a, val);  
    let bb = Object.assign(b, val);  
    a.sex = 1;  
    a.age.x = 20;  
    console.log(a.sex, b.sex, aa.sex, bb.sex)  
    console.log(a.age.x, b.age.x, aa.age.x, bb.age.x)  

或许是我太low了,之前还从没太在意过这个问题。

改用JSON.parse(JSON.stringify(defaultOrder))

收起阅读 »

关于解决【HBuilderX 内置浏览器空白】无法调试的问题

HBuilderX技巧 Mac版

> 记录Mac系统中HBuilderX问题

当内置的浏览器空白 无法调适时试试下面这个重启工具的命令吧

lsof -i:9777 | awk '{print $2}' | tail -n +2 | xargs kill -9

> 记录Mac系统中HBuilderX问题

当内置的浏览器空白 无法调适时试试下面这个重启工具的命令吧

lsof -i:9777 | awk '{print $2}' | tail -n +2 | xargs kill -9

完整好用的uniapp 录音调用百度语音转文字代码

经历三天时间各种遇到困难 之后终于实现了这个功能,参照网上了许多文章 才找到一个能正常实现的方法,网上能找到的例子都不起作用,相信很多人困惑在这,为了避免别人出现这种情况,我分享我的代码,绝对可用,包括 uniapp前端使用了recorderManager和java端调用百度语音转文字,我相信很多人都很需要我写的东西
我只试验了安卓手机
plus.speech这个方式就不要用了,不好用调用百度的语音识别时在百度的管理控制台会看到dev_id这个参数没传的错误也没找到添加这个参数的地方
所以在hbuildx里面当前项目的app模块配置这个地方不需要选

1.非常重要的一个步骤 manifest.json里面添加android.permission.RECORD_AUDIO这个权限,无论是想真机调试,由其是使用了自定义基座一定要在线打个包,让基座包含这个权限然后在手机系统 里面应用管理当前这个app的权限管理里面必须要看到有录音权限这一项。

  1. 为了能够在使用recorderManager在进入要使用录音功能的页面会询问是否允许录音这样的权限,必须要使用recorderManager之前要调用一次硬件权限申请。这个在插件市场里面有一个https://ext.dcloud.net.cn/plugin?id=594 这个地址 App权限判断和提示这样的js,用于判断或申请某个硬件权限使用的是native.js的功能。这个插件引入项目之后会在当前项目目录的js_sdk这样一个文件夹。在里面会出现wa-permission文件 夹下面会有一个permission.js,附件中会把上传前后端代码

3.相关代码
uniapp端代码


  <view class="popup-content" >  
                    <view>{{msg}}</view>  
                    <view>你在说{{voicetext}}</view>  
                    <button class="uni-btn"  type="warn" @touchstart="startvoice" @touchend="endvoice">按说语话松开停止</button>  
                    <button class="uni-btn"  type="warn" @tap="playvoice" >播放录音</button>  
    </view>  
<script>  
import permision from "@/js_sdk/wa-permission/permission.js"  
    const recorderManager = uni.getRecorderManager();  
    const innerAudioContext = uni.createInnerAudioContext();  
export default {  
     data() {  
    return {  
            voicetext:"",  
        msg:"",  
        voicepath:""  
       }  
   },  
  onLoad() {  
      this.initaudio()  

   },  
methods: {  
   async initaudio(){  
                           //注意此处必须为 await 因为会触发异步事件,手机上会弹出权限申请对话框处理完才能走下一步录音  
                 let recordauth =  await permision.requestAndroidPermission("android.permission.RECORD_AUDIO")  
                 console.log("判断有没有录音权限>>>>>>"+recordauth)  
                  if(recordauth==1){  
                               recorderManager.onStart((res)=>{  
                                        console.log("开始 录音>>>>>>>>>...")  
                                    });  
                               recorderManager.onStop((res)=>{  
                                    console.log("recorderstop....res.tempFilePath>>>"+res.tempFilePath)  
                                    this.voicepath = res.tempFilePath  
                                    this.uploadvoicefile()  
                                    // 使用uni.uploadFile上传到服务器上,此时是mp3格式  
                                });  

                                recorderManager.onError( (res)=> {  

                                 console.log('onError'+JSON.stringify(res));  
                                });  
                  }   
            }, //initaudio 方法结束  
          startvoice(){  
                console.log("开始录音")  
                recorderManager.start({  
                    format:"mp3",  
                    sampleRate: 16000 // 必须设置是后台设置的参数,不然百度语音识别不了  
                });  
         },  
        endvoice(){  

              console.log("结束录音")  
              //注意为了避免说话时间太短导致这个api出现bug要加一些延时  
             setTimeout(()=>{  
                recorderManager.stop()  
             },1000)  

            },  
            playvoice(){  
                console.log("点击playvoice")  
                if (this.voicepath) {  
                    console.log("播放声音")  
                    innerAudioContext.src = this.voicepath;  
                    innerAudioContext.play();  
                }  
            },  
            uploadvoicefile(){  
                // this.msg = "调用java端服务文件路径"+this.voicepath  
                 uni.uploadFile({  
                url: 'http://ip:端口/uploadFile(java端接收文件接口名)',   
                filePath: this.voicepath,//录音结束后返回的临时路径,  
                name: 'file',  
                formData: {  
                   dev_id:1537 //中文带标点  
                 },  
                success: (uploadFileRes) => {  
                    let word = uploadFileRes.data  
                    console.log("上传音频成功"+word);  
                },  
                fail: (res) => {  

                    console.log("上传音频失败"+JSON.stringify(res));  
                }  
                });  
            }  
    }  
}  
</script> ```   
 //注意uploadFile 的url属性 这个地方ip不能是localhost或127,如果自已电脑启动java服务必须 是本机的真实ip如192.xxx这种,或者域名什么的,并且java端接口一定要支持跨域,很多人卡到这个ip上,我也是网上很难找到解决问题的贴子  
注意filePath这个路径就是recorderManager的onStop事件就得到的_doc这种开头的路径,不需要加什么file:不是像网上某些人说的加这种东西  

java端  
pom里面需要引用两个包  

            <dependency>  
            <groupId>com.baidu.aip</groupId>  
            <artifactId>java-sdk</artifactId>  
            <version>4.16.3</version>  
        </dependency>  

        <dependency>  
            <groupId>com.googlecode.soundlibs</groupId>  
            <artifactId>mp3spi</artifactId>  
            <version>1.9.5.4</version>  
        </dependency>  

 ``` import com.baidu.aip.speech.AipSpeech;  
import javazoom.spi.mpeg.sampled.file.MpegAudioFileReader;  
import org.apache.commons.io.IOUtils;  
import org.json.JSONArray;  
import org.json.JSONObject;  

import org.springframework.web.bind.annotation.*;  
import org.springframework.web.multipart.MultipartFile;  

import javax.sound.sampled.AudioFormat;  
import javax.sound.sampled.AudioInputStream;  
import javax.sound.sampled.AudioSystem;  
import java.io.IOException;  
import java.io.InputStream;  
import java.util.HashMap;  

@RestController  
@CrossOrigin(origins = "*")  
public class BaiduSpeech {  
    //设置APPID/AK/SK  
    public static final String APP_ID = ""; //去百度语音服务申请  
    public static final String API_KEY = "";//去百度语音服务申请  
    public static final String SECRET_KEY = "";//去百度语音服务申请  

    @RequestMapping(value = "/uploadFile")  
    public String uploadFile( @RequestParam("dev_id") int dev_id, @RequestParam("file") MultipartFile file) throws Exception {  
        byte[] pcmbytedata = mp3Convert2pcm(file.getInputStream());  
        HashMap<String,Object> options = new HashMap<String,Object>();  
        options.put("dev_pid",dev_id);//  
        JSONObject jsonfrombaidu =  basicBydata(pcmbytedata,"pcm",options);  
        JSONArray jsonArray =  jsonfrombaidu.getJSONArray("result");  
        String result =  jsonArray.getString(0);  
        System.out.println(result); //解析完的结果   
        return result;  
    }  
    // 获取AipSpeech对象,建议单例使用  
    public static AipSpeech getClient() {  
        AipSpeech client = new AipSpeech(APP_ID, API_KEY, SECRET_KEY);  
        // 可选:设置网络连接参数  
        client.setConnectionTimeoutInMillis(2000);  
        client.setSocketTimeoutInMillis(60000);  
        return client;  
    }  

    // 语音识别(来自文件)  
    public static JSONObject basicBydata(byte[] voicedata, String fileType,HashMap<String,Object> options) {  
        AipSpeech client = getClient();  

        return client.asr(voicedata, fileType, 16000, options);  
    }  
    /**  
     * MP3转换PCM  
     * @param inputStream MP3输入流  
     * @throws Exception  
     */  
    public static byte[] mp3Convert2pcm(InputStream inputStream) throws Exception {  
        //转换PCM audioInputStream 数据  
        AudioInputStream audioInputStream = getPcmAudioInputStream(inputStream);  
        byte[] pcmBytes = IOUtils.toByteArray(audioInputStream);  
        return pcmBytes;  
    }  

    /**  
     * 获取PCM AudioInputStream 数据  
     * @param inputStream MP3输入流  
     * @return AudioInputStream PCM输入流  
     */  
    private static AudioInputStream getPcmAudioInputStream(InputStream inputStream) {  
        AudioInputStream audioInputStream = null;  
        AudioFormat targetFormat = null;  
        try {  
            AudioInputStream in = null;  
            MpegAudioFileReader mp = new MpegAudioFileReader();  
            in = mp.getAudioInputStream(inputStream);  
            AudioFormat baseFormat = in.getFormat();  
            targetFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, baseFormat.getSampleRate(), 16,  
                    baseFormat.getChannels(), baseFormat.getChannels() * 2, baseFormat.getSampleRate(), false);  
            audioInputStream = AudioSystem.getAudioInputStream(targetFormat, in);  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        return audioInputStream;  
    }  

} ``` 
继续阅读 »

经历三天时间各种遇到困难 之后终于实现了这个功能,参照网上了许多文章 才找到一个能正常实现的方法,网上能找到的例子都不起作用,相信很多人困惑在这,为了避免别人出现这种情况,我分享我的代码,绝对可用,包括 uniapp前端使用了recorderManager和java端调用百度语音转文字,我相信很多人都很需要我写的东西
我只试验了安卓手机
plus.speech这个方式就不要用了,不好用调用百度的语音识别时在百度的管理控制台会看到dev_id这个参数没传的错误也没找到添加这个参数的地方
所以在hbuildx里面当前项目的app模块配置这个地方不需要选

1.非常重要的一个步骤 manifest.json里面添加android.permission.RECORD_AUDIO这个权限,无论是想真机调试,由其是使用了自定义基座一定要在线打个包,让基座包含这个权限然后在手机系统 里面应用管理当前这个app的权限管理里面必须要看到有录音权限这一项。

  1. 为了能够在使用recorderManager在进入要使用录音功能的页面会询问是否允许录音这样的权限,必须要使用recorderManager之前要调用一次硬件权限申请。这个在插件市场里面有一个https://ext.dcloud.net.cn/plugin?id=594 这个地址 App权限判断和提示这样的js,用于判断或申请某个硬件权限使用的是native.js的功能。这个插件引入项目之后会在当前项目目录的js_sdk这样一个文件夹。在里面会出现wa-permission文件 夹下面会有一个permission.js,附件中会把上传前后端代码

3.相关代码
uniapp端代码


  <view class="popup-content" >  
                    <view>{{msg}}</view>  
                    <view>你在说{{voicetext}}</view>  
                    <button class="uni-btn"  type="warn" @touchstart="startvoice" @touchend="endvoice">按说语话松开停止</button>  
                    <button class="uni-btn"  type="warn" @tap="playvoice" >播放录音</button>  
    </view>  
<script>  
import permision from "@/js_sdk/wa-permission/permission.js"  
    const recorderManager = uni.getRecorderManager();  
    const innerAudioContext = uni.createInnerAudioContext();  
export default {  
     data() {  
    return {  
            voicetext:"",  
        msg:"",  
        voicepath:""  
       }  
   },  
  onLoad() {  
      this.initaudio()  

   },  
methods: {  
   async initaudio(){  
                           //注意此处必须为 await 因为会触发异步事件,手机上会弹出权限申请对话框处理完才能走下一步录音  
                 let recordauth =  await permision.requestAndroidPermission("android.permission.RECORD_AUDIO")  
                 console.log("判断有没有录音权限>>>>>>"+recordauth)  
                  if(recordauth==1){  
                               recorderManager.onStart((res)=>{  
                                        console.log("开始 录音>>>>>>>>>...")  
                                    });  
                               recorderManager.onStop((res)=>{  
                                    console.log("recorderstop....res.tempFilePath>>>"+res.tempFilePath)  
                                    this.voicepath = res.tempFilePath  
                                    this.uploadvoicefile()  
                                    // 使用uni.uploadFile上传到服务器上,此时是mp3格式  
                                });  

                                recorderManager.onError( (res)=> {  

                                 console.log('onError'+JSON.stringify(res));  
                                });  
                  }   
            }, //initaudio 方法结束  
          startvoice(){  
                console.log("开始录音")  
                recorderManager.start({  
                    format:"mp3",  
                    sampleRate: 16000 // 必须设置是后台设置的参数,不然百度语音识别不了  
                });  
         },  
        endvoice(){  

              console.log("结束录音")  
              //注意为了避免说话时间太短导致这个api出现bug要加一些延时  
             setTimeout(()=>{  
                recorderManager.stop()  
             },1000)  

            },  
            playvoice(){  
                console.log("点击playvoice")  
                if (this.voicepath) {  
                    console.log("播放声音")  
                    innerAudioContext.src = this.voicepath;  
                    innerAudioContext.play();  
                }  
            },  
            uploadvoicefile(){  
                // this.msg = "调用java端服务文件路径"+this.voicepath  
                 uni.uploadFile({  
                url: 'http://ip:端口/uploadFile(java端接收文件接口名)',   
                filePath: this.voicepath,//录音结束后返回的临时路径,  
                name: 'file',  
                formData: {  
                   dev_id:1537 //中文带标点  
                 },  
                success: (uploadFileRes) => {  
                    let word = uploadFileRes.data  
                    console.log("上传音频成功"+word);  
                },  
                fail: (res) => {  

                    console.log("上传音频失败"+JSON.stringify(res));  
                }  
                });  
            }  
    }  
}  
</script> ```   
 //注意uploadFile 的url属性 这个地方ip不能是localhost或127,如果自已电脑启动java服务必须 是本机的真实ip如192.xxx这种,或者域名什么的,并且java端接口一定要支持跨域,很多人卡到这个ip上,我也是网上很难找到解决问题的贴子  
注意filePath这个路径就是recorderManager的onStop事件就得到的_doc这种开头的路径,不需要加什么file:不是像网上某些人说的加这种东西  

java端  
pom里面需要引用两个包  

            <dependency>  
            <groupId>com.baidu.aip</groupId>  
            <artifactId>java-sdk</artifactId>  
            <version>4.16.3</version>  
        </dependency>  

        <dependency>  
            <groupId>com.googlecode.soundlibs</groupId>  
            <artifactId>mp3spi</artifactId>  
            <version>1.9.5.4</version>  
        </dependency>  

 ``` import com.baidu.aip.speech.AipSpeech;  
import javazoom.spi.mpeg.sampled.file.MpegAudioFileReader;  
import org.apache.commons.io.IOUtils;  
import org.json.JSONArray;  
import org.json.JSONObject;  

import org.springframework.web.bind.annotation.*;  
import org.springframework.web.multipart.MultipartFile;  

import javax.sound.sampled.AudioFormat;  
import javax.sound.sampled.AudioInputStream;  
import javax.sound.sampled.AudioSystem;  
import java.io.IOException;  
import java.io.InputStream;  
import java.util.HashMap;  

@RestController  
@CrossOrigin(origins = "*")  
public class BaiduSpeech {  
    //设置APPID/AK/SK  
    public static final String APP_ID = ""; //去百度语音服务申请  
    public static final String API_KEY = "";//去百度语音服务申请  
    public static final String SECRET_KEY = "";//去百度语音服务申请  

    @RequestMapping(value = "/uploadFile")  
    public String uploadFile( @RequestParam("dev_id") int dev_id, @RequestParam("file") MultipartFile file) throws Exception {  
        byte[] pcmbytedata = mp3Convert2pcm(file.getInputStream());  
        HashMap<String,Object> options = new HashMap<String,Object>();  
        options.put("dev_pid",dev_id);//  
        JSONObject jsonfrombaidu =  basicBydata(pcmbytedata,"pcm",options);  
        JSONArray jsonArray =  jsonfrombaidu.getJSONArray("result");  
        String result =  jsonArray.getString(0);  
        System.out.println(result); //解析完的结果   
        return result;  
    }  
    // 获取AipSpeech对象,建议单例使用  
    public static AipSpeech getClient() {  
        AipSpeech client = new AipSpeech(APP_ID, API_KEY, SECRET_KEY);  
        // 可选:设置网络连接参数  
        client.setConnectionTimeoutInMillis(2000);  
        client.setSocketTimeoutInMillis(60000);  
        return client;  
    }  

    // 语音识别(来自文件)  
    public static JSONObject basicBydata(byte[] voicedata, String fileType,HashMap<String,Object> options) {  
        AipSpeech client = getClient();  

        return client.asr(voicedata, fileType, 16000, options);  
    }  
    /**  
     * MP3转换PCM  
     * @param inputStream MP3输入流  
     * @throws Exception  
     */  
    public static byte[] mp3Convert2pcm(InputStream inputStream) throws Exception {  
        //转换PCM audioInputStream 数据  
        AudioInputStream audioInputStream = getPcmAudioInputStream(inputStream);  
        byte[] pcmBytes = IOUtils.toByteArray(audioInputStream);  
        return pcmBytes;  
    }  

    /**  
     * 获取PCM AudioInputStream 数据  
     * @param inputStream MP3输入流  
     * @return AudioInputStream PCM输入流  
     */  
    private static AudioInputStream getPcmAudioInputStream(InputStream inputStream) {  
        AudioInputStream audioInputStream = null;  
        AudioFormat targetFormat = null;  
        try {  
            AudioInputStream in = null;  
            MpegAudioFileReader mp = new MpegAudioFileReader();  
            in = mp.getAudioInputStream(inputStream);  
            AudioFormat baseFormat = in.getFormat();  
            targetFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, baseFormat.getSampleRate(), 16,  
                    baseFormat.getChannels(), baseFormat.getChannels() * 2, baseFormat.getSampleRate(), false);  
            audioInputStream = AudioSystem.getAudioInputStream(targetFormat, in);  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        return audioInputStream;  
    }  

} ``` 
收起阅读 »

php curl 请求https接口证书问题

php 在windows下面使用curl请求一个https需要配置证书,具体请看代码:

php.ini配置

证书下载

http://curl.haxx.se/ca/cacert.pem

php 在windows下面使用curl请求一个https需要配置证书,具体请看代码:

php.ini配置

证书下载

http://curl.haxx.se/ca/cacert.pem

基于uni-admin的模糊查询和筛选查询(针对用户查询自己商品/产品使用)

admin uni_app项目 云开发

说明

1.程序基于uni-admin管理系统(用户)的模糊查询和筛选查询
2.程序由schema2code自动生成,添加几行代码即可
3.如果内容对各位有帮助请关注一下,创作不易

模糊查询

    let newWheres =this.getWhere();  
    let newWhere=newWheres.length>0?'('+newWheres+') && u_id == $cloudEnv_uid':'u_id == $cloudEnv_uid'

筛选查询

    newWhere.u_id=db.getCloudEnv('$cloudEnv_uid')

示例

    const dbOrderBy = 'create_date desc' // 排序字段,asc(升序)、desc(降序)  
    const dbSearchFields = ["title","description","reject_description"] // 模糊搜索字段,支持模糊搜索的字段列表。联表查询格式: 主表字段名.副表字段名,例如用户表关联角色表 role.role_name  
    export default {  
        methods: {  
            // 模糊查询  
            search() {  
                let newWheres =this.getWhere();  
                let newWhere=newWheres.length>0?'('+newWheres+') && u_id == $cloudEnv_uid':'u_id == $cloudEnv_uid'  
                this.where = newWhere  
                this.$nextTick(() => {  
                    this.loadData()  
                })  
            },  
            // 筛选查询  
            filterChange(e, name) {  
                this._filter[name] = {  
                type: e.filterType,  
                    value: e.filter  
                }  
                let newWhere = filterToWhere(this._filter, db.command)   
                newWhere.u_id=db.getCloudEnv('$cloudEnv_uid')  
                if (Object.keys(newWhere).length) {  
                    this.where = newWhere  
                } else {  
                    this.where = ''  
                }  
                this.$nextTick(() => {  
                    this.$refs.udb.loadData()  
                })  
            }  
        }  
    }
继续阅读 »

说明

1.程序基于uni-admin管理系统(用户)的模糊查询和筛选查询
2.程序由schema2code自动生成,添加几行代码即可
3.如果内容对各位有帮助请关注一下,创作不易

模糊查询

    let newWheres =this.getWhere();  
    let newWhere=newWheres.length>0?'('+newWheres+') && u_id == $cloudEnv_uid':'u_id == $cloudEnv_uid'

筛选查询

    newWhere.u_id=db.getCloudEnv('$cloudEnv_uid')

示例

    const dbOrderBy = 'create_date desc' // 排序字段,asc(升序)、desc(降序)  
    const dbSearchFields = ["title","description","reject_description"] // 模糊搜索字段,支持模糊搜索的字段列表。联表查询格式: 主表字段名.副表字段名,例如用户表关联角色表 role.role_name  
    export default {  
        methods: {  
            // 模糊查询  
            search() {  
                let newWheres =this.getWhere();  
                let newWhere=newWheres.length>0?'('+newWheres+') && u_id == $cloudEnv_uid':'u_id == $cloudEnv_uid'  
                this.where = newWhere  
                this.$nextTick(() => {  
                    this.loadData()  
                })  
            },  
            // 筛选查询  
            filterChange(e, name) {  
                this._filter[name] = {  
                type: e.filterType,  
                    value: e.filter  
                }  
                let newWhere = filterToWhere(this._filter, db.command)   
                newWhere.u_id=db.getCloudEnv('$cloudEnv_uid')  
                if (Object.keys(newWhere).length) {  
                    this.where = newWhere  
                } else {  
                    this.where = ''  
                }  
                this.$nextTick(() => {  
                    this.$refs.udb.loadData()  
                })  
            }  
        }  
    }
收起阅读 »

getBluetoothAdapterState api "discovering": false, 无法搜索到蓝牙设备

蓝牙打印

uni.getBluetoothAdapterState 无法搜索蓝牙连接打印机
安卓版本 6.0,定位权限 与蓝牙权限开启后,还是无法搜索到蓝牙
数据返回

{  
    "discovering": false,  
    "available": true,  
    "errMsg": "getBluetoothAdapterState:ok"  
}

经过检查 ,原因是 手机 定位没有开启,开启手机定位后 能够正常运行

继续阅读 »

uni.getBluetoothAdapterState 无法搜索蓝牙连接打印机
安卓版本 6.0,定位权限 与蓝牙权限开启后,还是无法搜索到蓝牙
数据返回

{  
    "discovering": false,  
    "available": true,  
    "errMsg": "getBluetoothAdapterState:ok"  
}

经过检查 ,原因是 手机 定位没有开启,开启手机定位后 能够正常运行

收起阅读 »

Mac OS HBuilderX 更换Dock栏图标

HBuidlerX 在Mac OS Dock栏图标太大,显的很不协调。
修改前


修改后

修改方法

解压 :hx_icon@2x.icns.zip
右键 -> 显示简介 -> 拖动 hx_icon@2x.icns 到上图位置

继续阅读 »

HBuidlerX 在Mac OS Dock栏图标太大,显的很不协调。
修改前


修改后

修改方法

解压 :hx_icon@2x.icns.zip
右键 -> 显示简介 -> 拖动 hx_icon@2x.icns 到上图位置

收起阅读 »