管理员 发布的文章

解决Hbuilder打包的apk文件按手机返回键直接退出软件
问题描述:Hbuilder打包的app如果点击手机返回键,app会直接退出,返回不了上一页。

写在公共js文件中,每个页面均引入该js,代码如下:

document.addEventListener('plusready', function() {

var webview = plus.webview.currentWebview();
plus.key.addEventListener('backbutton', function() {
    webview.canBack(function(e) {
        if(e.canBack) {
            webview.back();
        } else {
            webview.close(); //hide,quit按手机返回键直接退出APP
            //plus.runtime.quit();
        }
    })
});

});

上面的一段代码即可实现按手机返回键时返回上一页,当返回到首页,再按手机返回键即可退出APP,下面的代码可以不要

点击手机返回键两次提示退出程序,代码如下:

注: 在hbuilder中新建移动App时,选择模板-mui项目,在页面中引入mui.js以及mui.min.js,点击两次退出程序效果才会实现
mui.plusReady(function() {

            //首页返回键处理
            //处理逻辑:1秒内,连续两次按返回键,则退出应用;
            var first = null;
            plus.key.addEventListener('backbutton', function() {
                //首次按键,提示‘再按一次退出应用’
                if (!first) {
                    first = new Date().getTime();
                    mui.toast('再按一次退出应用');
                    setTimeout(function() {
                        first = null;
                    }, 1000);
                } else {
                    if (new Date().getTime() - first < 1000) {
                        plus.runtime.quit();
                    }
                }
            }, false);
        });

按手机返回键返回上一页 + 点击手机返回键两次提示退出程序效果,完整js代码:

注:此段代码当在首页,按手机返回键时无效果,不会退出APP,要点击两次才行

<script>
document.addEventListener('plusready', function() {

    var webview = plus.webview.currentWebview();
    plus.key.addEventListener('backbutton', function() {
        webview.canBack(function(e) {
            if(e.canBack) {
                webview.back();             
            } else {
                //webview.close(); //hide,quit
                //plus.runtime.quit();
                mui.plusReady(function() {
                    //首页返回键处理
                    //处理逻辑:1秒内,连续两次按返回键,则退出应用;
                    var first = null;
                    plus.key.addEventListener('backbutton', function() {
                        //首次按键,提示‘再按一次退出应用’
                        if (!first) {
                            first = new Date().getTime();
                            mui.toast('再按一次退出应用');
                            setTimeout(function() {
                                first = null;
                            }, 1000);
                        } else {
                            if (new Date().getTime() - first < 1500) {
                                plus.runtime.quit();
                            }
                        }
                    }, false);
                });
            }
        })
    });
});

</script>

js后台返回给前端数据处理成树形结构数据
后台返回给前端数据:

[{

"id": "1",    //唯一标识id
"name": "女装/男装/内衣",
"parentId": "0"    //父级id

}, {

"id": "2",
"name": "女装",
"parentId": "1"

}, {

"id": "3",
"name": "男装",
"parentId": "1"

}, {

"id": "4",
"name": "童装",
"parentId": "1"

}, {

"id": "5",
"name": "内衣",
"parentId": "1"

}, {

"id": "6",
"name": "连衣裙",
"parentId": "2"

}, {

"id": "7",
"name": "毛呢外套",
"parentId": "2"

}, {

"id": "8",
"name": "休闲裤",
"parentId": "2"

}, {

"id": "9",
"name": "牛仔外套",
"parentId": "2"

}, {

"id": "10",
"name": "鞋靴/箱包/配件",
"parentId": "0"

}]

前端处理数据

let data1 = res.data;//后台初始数据

        function setTreeData(arr) {
            // 删除所有的children,以防止多次调用
            arr.forEach(function(item) {
                delete item.children;
            });
            let map = {}; //构建map
            arr.forEach(i => {
                map[i.id] = i; //构建以id为键 当前数据为值
            });
            let treeData = [];
            arr.forEach(child => {
                const mapItem = map[child.parentId]; //判断当前数据的parentId是否存在map中
                if (mapItem) {
                    //存在则表示当前数据不是最顶层的数据
                    //注意: 这里的map中的数据是引用了arr的它的指向还是arr,当mapItem改变时arr也会改变,踩坑点
                    (mapItem.children || (mapItem.children = [])).push(child); //这里判断mapItem中是否存在child
                } else {
                    //不存在则是顶层数据
                    treeData.push(child);
                }
            });
            return treeData;
        }
        console.log(setTreeData(data1))

处理结果:

[{

"id": "1",
"name": "女装/男装/内衣",
"parentId": "0",
"children": [{
    "id": "2",
    "name": "女装",
    "parentId": "1",
    "children": [{
        "id": "6",
        "name": "连衣裙",
        "parentId": "2"
    }, {
        "id": "7",
        "name": "毛呢外套",
        "parentId": "2"
    }, {
        "id": "8",
        "name": "休闲裤",
        "parentId": "2"
    }, {
        "id": "9",
        "name": "牛仔外套",
        "parentId": "2"
    }]
}, {
    "id": "3",
    "name": "男装",
    "parentId": "1"
}, {
    "id": "4",
    "name": "童装",
    "parentId": "1"
}, {
    "id": "5",
    "name": "内衣",
    "parentId": "1"
}]

}, {

"id": "10",
"name": "鞋靴/箱包/配件",
"parentId": "0"

}]

表名 功能
ims_ewei_shop_adv 广告表
ims_ewei_shop_alipaym_log *支付宝直接充值日志表
ims_ewei_shop_article 营销文章
ims_ewei_shop_article_category 营销表单分类
ims_ewei_shop_article_log 点赞/阅读记录
ims_ewei_shop_article_report 用户举报记录
ims_ewei_shop_article_share 用户分享数据
ims_ewei_shop_article_sys 文章设置
ims_ewei_shop_carrier 自提点表
ims_ewei_shop_category 商品分类表
ims_ewei_shop_commission_apply 提现申请表
ims_ewei_shop_commission_clickcount 点击记数表
ims_ewei_shop_commission_level 分销分级表
ims_ewei_shop_commission_log 分销日志表
ims_ewei_shop_commission_shop 店中店表
ims_ewei_shop_coupon 优惠券表
ims_ewei_shop_coupon_category 优惠券分类表
ims_ewei_shop_coupon_data 优惠券领取记录表
ims_ewei_shop_coupon_guess 优惠券口令玩法日志表
ims_ewei_shop_coupon_log 优惠券日志表
ims_ewei_shop_creditshop_adv 积分商城广告表
ims_ewei_shop_creditshop_category 积分商城分类表
ims_ewei_shop_creditshop_goods 积分商城商品表
ims_ewei_shop_creditshop_log 积分商城日志表表
ims_ewei_shop_designer 店铺装修插件表
ims_ewei_shop_designer_menu 店铺装修菜单表
ims_ewei_shop_dispatch 配送表
ims_ewei_shop_diyform_category 自定义表单分类表
ims_ewei_shop_diyform_data 自定义表单数据表
ims_ewei_shop_diyform_temp 自定义表单临时表
ims_ewei_shop_diyform_type 自定义表单类型
*ims_ewei_shop_erp_area ERP插件地区表
*ims_ewei_shop_erp_product ERP插件产品表
ims_ewei_shop_exhelper_express 快递助手打印模板表
ims_ewei_shop_exhelper_senduser 快递助手发货人信息表
ims_ewei_shop_exhelper_sys 快递助手打印机配置表
ims_ewei_shop_express 物流表
ims_ewei_shop_feedback 反馈表
ims_ewei_shop_goods 商品表 ERP 全球购 *甩手掌柜
ims_ewei_shop_goods_comment 商品评论表
ims_ewei_shop_goods_option 商品规格表 *ERP
ims_ewei_shop_goods_param 商品参数表
ims_ewei_shop_goods_spec 商品规格表
ims_ewei_shop_goods_spec_item 商品规格项目表
ims_ewei_shop_member 用户表 注册表单 启动画面 关注、佣金排行榜
ims_ewei_shop_member_address 用户地址表
ims_ewei_shop_member_cart 用户购物车表
ims_ewei_shop_member_favorite 用户收藏表
ims_ewei_shop_member_group 用户组表
ims_ewei_shop_member_history 用户浏览足迹表
ims_ewei_shop_member_level 用户分级表
ims_ewei_shop_member_log 用户充值记录表
ims_ewei_shop_member_message_template 模板消息表
ims_ewei_shop_notice 提醒表
ims_ewei_shop_order 订单表 *ERP
ims_ewei_shop_order_comment 订单评论表
ims_ewei_shop_order_goods 订单商品表
ims_ewei_shop_order_refund 订单退货表
ims_ewei_shop_perm_log 权限日志
ims_ewei_shop_perm_plugin 插件权限
ims_ewei_shop_perm_role 权限规则
ims_ewei_shop_perm_user 用户权限
ims_ewei_shop_plugin 插件表
ims_ewei_shop_postera 活动海报表
ims_ewei_shop_postera_log 活动海报日志表
ims_ewei_shop_postera_qr 活动海报二维码表
ims_ewei_shop_poster 超级海报表
ims_ewei_shop_poster_log 超级海报日志表
ims_ewei_shop_poster_qr 超级海报二维码表
ims_ewei_shop_poster_scan 超级海报扫描表
*ims_ewei_shop_regform 注册表单审核表
ims_ewei_shop_refund_address 退货地址表
ims_ewei_shop_saler 核销人员表
ims_ewei_shop_store 商店表
ims_ewei_shop_sysset 系统设置
ims_ewei_shop_system_copyright 版权设置
ims_ewei_shop_virtual_category 虚拟商品分类
ims_ewei_shop_virtual_data 虚拟商品数据
ims_ewei_shop_virtual_type 虚拟商品类型

本帖转自章鱼大大 原文链接https://bbs.125.la/forum.php?mod=viewthread&tid=14132061

新建project等常规操作我就不细讲了 一层楼发不完 未看到完结不要插楼 插楼的麻烦论坛管理直接删除
首先.强烈建议从此之后的所有支持库均由VS2015开发.最后使用2015编译器链接 至少5年内 可以不用换支持库
至于5年后.走一步看一步
VC6其实我也不推荐.虽然不会出MSVR的版本问题.因为编译之后可能会出现符号冲突
而且这玩意是1998年的 比论坛一些人年纪都大
这篇教程小白看会看不懂
新手C++会比较吃力
有问题可以进群问727137285(日后CGLIBFE的群) 或者 547525064(ELIB开发群) 我的ID是:MOV RAX 214D
(顺便打个电线杆小广告 接单接单 116 0320 547 价格美丽 基于windows一般都没问题)

我只说说一些重点 我重新创建了一个项目 Test_For_E
开发环境VS2015+win10 1607
测试环境易语言5.2+WIN7 SP1+上面帖子中提到的修复后的VS2015编译链接器
创建项目.选择win32,然后选DLL
1.png
创建之后.dllmain.cpp不管他 暂时不要动
打开文件夹.复制elib过去.或者手动添加文件夹位置到C/C++属性页
2.png
易语言支持库的开发必须有elib的头文件.里面基本上只是定义数据类型
elib文件版本不一样 也稍微有不同,至少我本人拿到的2个版本都有BUG 并且我其中一份还有其他人修改过的痕迹.帖子最后我会上传修正的elib.
你也可以不用 在esdkcppelib中也有 不过可能需要自己改改BUG 其实也不能算是BUG 那个编译环境太老了 会出很多问题
然后新建E_Head.h头文件
在该头文件中.第一步先导入易语言数据类型 如果你用的是我给出的elib.那么只需要

include "elib/fnshare.hpp"

否则的话看官方文档 各头文件用处不一样

这个头文件的作用就是用来定义各种易语言支持类型的
实际上 易语言动态库fne就是一个DLL.很逗吧?

在编译之后.直接把DLL改名为fne放到易语言lib里面都可以.但是反之不行 原因我之后会讲

然后加入动态库信息
3.png
GUID可以随便填.推荐使用VS->TOOLS里面的createguid
或者在这里找 https://www.uuidgenerator.net/
版本号 支持库名称等
关于命令符分类 我也没搞明白 这种写法真的太Low了 有兴趣可以查查官方文档
新建实现文件 Test.cc
4.png
所有函数必须使用extern "C"申明 除非你用的纯C开发并且使用C方式编译
所有函数返回值必须使用void 参数类型也不能变
PMDATA_INF pRetData, INT nArgCount, PMDATA_INF pArgInf
这里大概讲解一下 我说完后你们再看看官方文档就懂了
PMDATA_INF是易语言自定义数据类型.内部使用了一个联合体,也就是说任意时刻只有一个类型是有效的
pRetData是返回值.也就是易语言调用之后的参数返回值
5.png
也就是在动态库中进行规则约定,如果我的返回值是int类型.那么我就使用pRetData->m_int 同时在另一处规定返回值
这里我们让他返回整数型1.
nArgCount是参数个数
这也就是为什么易语言可以实现不限制参数个数的原因 这也是为什么易语言可以使用通用类型.但是通用类型却只能是易语言基本类型的原因
pArgInf这个才是易语言真正传进来的参数 数组结构 其实易语言返回值也可以做成多个返回值.不知道为什么没有弄
pArgInf的使用基本和pRetData是一样的
比如使用第一个参数 是pArgInf[0].m_int
那么第二个 就是pArgInf[1].m_int
后面的类型自选
test我设置了3个参数.分别是整数型 文本型 和子程序指针
然后全部转const char* 最后吧内容弹出来
OK 在写一个test2
test只设置一个参数.返回值为文本型
接下来开始设置一些函数信息.我们现在只是定义声明了函数,易语言那边需要特殊操作才能正常获取
之前我们说到了在动态库中约定规则 参数 返回值等现在就是要告诉易语言的时候.编译动态库之后.易语言会获取到这部分信息.静态编译也需要这部分信息的支持
6.png
数组名自定义即可每一个数组都是一条参数信息
名称和描述不用讲.最后会显示到易语言里面去
图像这两个我也没用过 有兴趣的可以试试
接下来是返回值类型.参考一楼那张图
第一个参数是整数 所以使用SDT_INT 这个也是易语言自定义类型 所以我们第一个参数使用了pArgInf[0].m_int
函数的参数搞定了.接下来是函数的信息 返回值 参数个数等约定
7.png
关于ExecuteCommand和CommandNames 照抄就行了 至于为什么看官方文档 把所有函数名称写进去就行了
这两个数组中的每个函数 位置必须一一对应.他并不是用英文名称去查找函数.而是用位置索引!
Commands用于定义函数帮助信息 这些都需要用逗号隔开
只讲几个重要的 名称描述啥的一看就知道是干嘛的了
参数个数 也就是该函数需要的参数个数.这里一定要填对.填错了我也不知道会发生啥
然后是参数类型的具体定义 也就是上一楼中我们定义的数组
关于__E_STATIC_LIB
官方文档中提到的宏而已可以删除 不影响正常编译
在编译静态库的时候 并不需要参数信息参数个数等信息
易语言通过查找fne内的信息 去匹配static lib 这点其实有点蠢 一旦两个版本不一致 会发生未知后果 而且没有任何警告
8.png
照抄这个函数 函数名自定义就可以了
前两个一般不用动
最后一个需要注意
NL_GET_DEPENDENT_LIBS 这个是静态库依赖的Lib列表
在动态库写入之后.静态编译的时候 会添加到命令行中(我目测.猜的)
当然也可以不管他.直接在link.ini中写入.
9.png
这里一般照抄就行
唯一要改的就是下面的函数
改成上面那个就OK
怕你们看不见 特意补图
10.png
接下来申明导出函数
11.png
之前那个帖子中说需要.def 其实不需要 只需要申明导出就行
回到最初的那个问题
为什么易语言编译出来的DLL不行?原因就在这里了
在整个fne编译之后 只有一个导出函数
getnewinf会把你定义的所有信息全部返回.包括什么支持库名字啊 描述啊 函数啊 参数啊 返回值 都在里面
其实还是蛮神奇的 只需要导出这么一个函数即可如果易语言同样导出这个函数 并且导出信息 其实易语言编译个DLL出来 改下名也能用!
放入lib之后 添加支持库的时候 易语言会去遍历每一个fne的PE函数导出表 看看有没有叫做getnewinf的函数 有就获取信息 显示出来
OK 到这一步.整个支持库编写就完成了 接下来是配置
首先 修改字符集 是debug版本 我这里吧debug当做fne release当做lib用
12.png
VS默认是Unicode 改过来就行 编译平台什么的其实无所谓 VC6能不能用未知
但是你要是想支持XP3下运行 就在编译器选择XP
配置类型.dll 目标文件名可以改成.fne 或者编译后手动改 随便你的
13.png
这里默认就行 如果全程序优化打开了 就关闭它.否则会造成编译出错
14.png
代码生成一般debug默认MDd 这里我改成mtd 因为MD是动态编译 需要安装VS运行库 如果你需要发布fne 别人又没有装运行库 那么就无法使用 所以我选择MT静态编译
fne的设置就这么多 编译拿过去试一下

15.png
编译通过
16.png
拿过去试试.DLL改下名字 改fne 丢到e/lib中
17.png
OJ8K 读出来了
18.png
试试调用
19.png
很完美
20.png

这是使用C++11标准的std::thread库 C++11标准由C++委员会制定 从boost中选取 windows平台上编译器由微软实现
现在知道我之前的那个帖子有多么凶残了吧?
OK 接下来 静态库

配置我直接选的release
21.png
修改配置类型为静态库
目标文件名加上_static 只有这样易语言才识别
也可以不加 编译后手动改
改一下字符集
22.png
一定要关闭全程序优化!
23.png
一定要选择MT静态编译 否则你的静态库没有任何意义!
然后编译生成 其他一般都默认就可以
24.png
放入estatic_lib中
然后开始静态编译
25.png

    不好意思 我是盗版狗...

很完美
其次是关于上一贴的补充说明
编译显示krnel.lib符号未找到的一定要修改这里
26.png
OK 教程到此结束

本帖最后由 章鱼大大 于 2018-3-3 23:49 编辑

此楼作为补充楼层
有任何修改 错误.或者补充 都会在这层中编辑觉得牛逼的话点一下关注(听众) 后续我会开源很多支持库出来 第一个就是线程库 从此告别模块和官方支持库渣渣封装

15年我就搜过易语言支持库开发教程 没有 这可能是除了官方文档的唯一一个支持库开发教程了

补充1:关于写窗口的问题
我修改过后的elib还能不能写窗口我不太清楚 导入的头文件不太一样 我没兴趣搞那个

推荐各位别造那种轮子...

整个项目打包包括fne lib 还有elib都在这里了
https://pan.baidu.com/s/1d29T4y
本帖转自章鱼大大 原文链接https://bbs.125.la/forum.php?mod=viewthread&tid=14132061

1.宝贝亮点:

1.1液晶可显示输入输出电压,输出电流输出功率;

1.2.输入端防反接保护,反接不会烧毁;

1.3.可升压,可降压,输出电压0.5-30V任意调节,限制电流0-4A任意调节;

1.4.输出端防倒灌,给电池充电时不用另外加防倒灌二极管;

1.5.按键控制输出端ON/OFF状态,并且可以设置上电默认为ON或OFF;

1.6.采用升降压芯片作为主要控制器,外置60V 75A MOS管作为开关管,双60V 5A SS56肖特基做整流,60V耐压值,优于市面上的XL6009/LM2577不成熟方案(很多器件耐压值不足,MOS 管和肖特基二极管耐压值必须大于输入加输入电压值);

1.7.输出纹波小,有LC滤波;

1.8.含散热片,送模块支撑隔离柱。

2.产品参数:

输入电压:5.5-30V(输入电压5V时,也可以实现升降压,但是电压电流测量不准确;低于4.7V时,欠压保护)

输出电压:0.5-30V

输出电流:能长期稳定工作在3A ,加强散热下可达到4A

输出功率:自然散热35W,加强散热50W

电压显示分辨率:0.05V

电流显示分辨率:0.005A

转换效率:88%左右

软启动:有(很大功率带负载模块启动时有可能失效)

输入反接保护:有

输出端防倒灌:有

短路保护:有

工作频率:180KHZ

尺寸:长高 664821mm

安装孔:直径4mm

重量:46g

3.功能说明:

3.1.模块有IN/OUT,ON/OFF两个按键:IN/OUT按键切换输入电压与输出电压显示,长按可以切换输出电流输出功率显示;ON/OFF按键控制输出ON或OFF,长按可以设置下次上电默认输出状态是ON或者OFF。

3.2.CC为电流设置电位器,顺时针旋转,可增大设定电流,当负载电流达到设定电流时,进入恒流状态,CC恒流指示灯(红色)亮起;右边CV为电压设置电位器,顺时针旋转,可增大输出电压。ON指示灯是输出状态指示灯,当输出端有电压时亮,否则灭。

4.使用方法:

4.1.作为具有过流保护能力的普通升降压模块使用

(1)调节CV恒压电位器,使输出电压达到您想要的电压值。

(2)用万用表10A电流档测量输出短路电流(直接把两只表笔接到输出端即可),同时调节CC恒流电位器使输出电流达到预定的过流保护值。(比如万用表显示的电流值是2A,那么您使用模块时最大电流只能到2A,电流到2A时红色恒压恒流指示灯亮,否则该指示灯灭)

注意:在此状态下使用时,由于输出端有电流采样电阻,接上负载后会有0~0.2V的压降,同时大电流的时候,输入导线和输出导线会有一定的线上压降,此为正常现象!

4.2.作为电池充电器使用

不带恒流功能的模块是不能用来给电池充电的,由于耗完电的电池与充电器的压差很大,导致充电电流过大,造成电池损坏,所以开始的时候要对电池使用恒流充电,当充电到一定程度的时候自动切换回恒压充电。

(1)确定您需要充电电池的浮充电压和充电电流;(假如锂电池参数为3.7V/2200mAh,那么浮充电压为4.2V,最大充电电流1C,即2200mA)

(2)空载条件下,万用表测量输出电压,调节恒压电位器使输出电压达到浮充电压;(假如给3.7V锂电池充电,把输出电压调为4.2V即可)

(3)用万用表10A电流档测量输出短路电流(直接把两只表笔接到输出端即可),同时调节恒流电位器使输出电流达到预定的充电电流值;

(4)接上电池,充电。

(步骤1、2、3为:输入端接电源,输出端空载不接电池)

4.3.作为大功率LED恒流驱动模块使用

(1)确定您需要驱动LED的工作电流和最高工作电压;

(2)空载条件下,万用表测量输出电压,调节恒压电位器使输出电压达到LED最高工作电压;

(3)用万用表10A电流档测量输出短路电流,同时调节恒流电位器使输出电流达到预定的LED工作电流;

(4)接上LED,试机。

(步骤1、2、3为:输入接电源,输出空载不接LED灯。)

注意:本模块在超过3A、35W使用时,请加强散热!!!

5.注意事项:

5.1.模块输入IN-禁止与输出OUT-短接,否则恒流功能失效。

5.2.请确保供电电源的功率时刻大于输出负载所需功率!

5.3.模块若想满载输出,输入电压要8V以上,当输入电压为5V时,输出功率约为15W,电压电流表失效。模块电流值最大4A,前提受限于最大输出功率,比如输出17V,电流应不大于2A。

5.4.模块带输出短路保护,短路保护后模块自动关闭输出,给模块重新上电即可恢复,如果您的供电电源无输出限流保护,建议在模块输入前端串接保险丝,提高安全系数。

5.5.模块有输入欠压保护功能,默认是4.7V左右,低于这个值后,会自动断开输出,给模块重新上电即可恢复(注意是模块端口处的电压,当输入电流比较大时,不要忽略输入导线上的分压)。