0%

移动App开发笔记

jxstar移动App开发笔记!

添加功能入口

在主页(一般是index页面)添加功能(模块)入口。

开发平台 - 移动平台 - 移动功能注册 - 添加(功能入口)、移动角色注册 - 给角色添加权限(前边新增的功能入口)。

Java类接口相关

查询数据

使用query_data事件,查询数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//注意,要引入base64的依赖(公司提供的工具,对where_sql进行base64编码)
<script src="../../js/base64.min.js"></script>

//加载 列表
loadList() {
var where_sql = 'sp_outstore.outstore_state=?';//sql语句
var params = 'funid=queryevent&eventcode=query_data&query_funid=sp_outstore_confirm_2';
params += '&where_sql=' + where_sql;
params += '&where_type=string';//多个参数,用;隔开
params += '&where_value=1';//多个参数,用;隔开。使用like进行模糊查询时,要使用encodeURIComponent进行编码,例如:var e = encodeURIComponent; e(待编码字符);
//params += '&where_value=1;' + e('%' + search + '%') + ';' + e('%' + search + '%');
//分页:
params += '&start=' + this.currentPage * this.pageSize;//当前页面(页码,从0开始) * 页面大小
params += '&limit=' + this.pageSize;//页面大小
jxm.post(params, data => {
this.dataSource.push(...data.root); //追加在末尾
this.showData = JSON.parse(JSON.stringify(this.dataSource));
//加载完新数据后,关闭加载动画,true表示没有更多数据了。
mui('#refreshContainer').pullRefresh().endPullupToRefresh((this.currentPage + 1) * this.pageSize + 1 >= data.total);
});
}

修改数据

  • save,保存(更新)
  • save_eg,另存为。还需要添加fkValue字段(外键),见下边新增数据例子。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//保存 按钮
btnsave() {
this.dataDet.forEach(item => {
//保存 修改后的物资数量
var params = "funid=outstore_confirm_det_2"//功能ID(标识)
params += "&eventcode=save";//事件(在功能设计器中要有注册才行)
params += "&pagetype=editgrid";//选择表格编辑editgrid
params += "&keyid=" + item.sp_outstore_det__outstore_detid;//表 主键
params += "&sp_outstore_det.out_num=" + item.sp_outstore_det__out_num; //更新的数据:key=value。(带上表名)
params += "&dirtyfields=sp_outstore_det.out_num" //更新的字段,“;”隔开,带上表名
jxm.post(params, function(data) {
mui.toast('保存成功!');
});
})
}

新增数据

功能设计器中,新增“create”事件。

1
2
3
4
5
6
7
8
9
10
11
//params拼接成如下:

funid=equ_scan_det//功能标识
&eventcode=create//新建(事件)
&pagetype=editgrid//表格编辑(页面类型的填写,以功能设计器-事件注册页面表格中的为准)
&equ_scan_det.device_code=DL184004&equ_scan_det.device_name=盘盈设备&equ_scan_det.m_type=1&equ_scan_det.dept_name=&equ_scan_det.use_state=&equ_scan_det.dev_memo=&equ_scan_det.pda_type=1//插入的 数据字段
&fkValue=jxstar-477-352//外键。equ_scan_det为盘点明细表,此外键为equ_scan盘点单主键
&user_id=administrator

//1、参数名带上表名
//2、回调中会返回所创建(新增)的记录的主键

提交数据

调用audit事件,修改功能设计器中所设置的“记录状态列”。

1
2
3
4
5
6
7
8
9
10
11
//提交 按钮
btncommit() {
this.btnsave(); //先保存数据
var params = 'funid=sp_outstore_confirm_2&eventcode=audit&pagetype=form';
//sp_instore.instore_state 修改为 2 。2 - 已出库(根据规定,修改auditvalue的值。字段auditing一般修改为1)
params += '&auditvalue=2'+'&keyid='+this.data.sp_outstore__outstore_id;
//提交
jxm.post(params, function(data){
mui.alert('提交成功!', '提示');
});
}

自定义事件

通过自定义事件,绑定java类对数据进行复杂处理。

编写Java类

扩展:

java类中调用功能设计器中定义的其它事件(功能设计器 - 事件注册 - 事件)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public String commit(RequestContext req) {
String scanid = req.getRequestValue("scanid",""); //盘点单ID
String content = req.getRequestValue("content",""); //盘点信息
_log.showDebug("......scanid="+scanid);
_log.showDebug("......content="+content);
if(scanid.length()==0 || content.length()==0) {
setMessage("盘点信息为空,提交失败!");
return _returnFaild;
}

//创建服务控制器对象
ServiceController serviceController = (ServiceController) SystemFactory.createSystemObject("ServiceController");

//设置请求信息
req.setFunID("equ_scan");
req.setEventCode("commtask");
req.setRequestValue("scanid", scanid);
req.setRequestValue("content", content);
//先上传盘点信息
if (!serviceController.execute(req)) {
return _returnFaild;
}
...
}

配置

功能设计器中配置【事件与java类的映射】。

应用

前端代码中调用。

注意:使用jxm时要注意jxm/js/jxm.js中的SERVER_URL(服务器地址)是否正确。

扫码功能开发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//1、扫码按钮 触发该方法,打开扫码页面。(公司提供的扫码页面,扫码成功的回调函数为scanSucess)
clicked() {
jxm.open('../util/barcode_scan.html');//打开扫码页面
}

//2、定义 扫码成功 回调函数scanSucess
scanSucess(result) {
var item = this.dataDet.filter(data =>
data.sp_outstore_det__sp_code.toLowerCase().includes(result.toLowerCase())
);
if(item[0]) {
this.changeNum(item[0]); //修改物资数量
} else {
mui.alert("出库单中无该物资!", "提示");
}
}

//3.1、在vue中定义的函数,要抛出到window
mounted() {
mui.plusReady(() => {
window.scanSucess = this.scanSucess; //扫码成功回调
});
}
//3.2、或者在vue的外边,定义函数scanSucess
<script>
var vm = new Vue({...});
var scanSucess = vm.scanSucess;
</script>

扫码枪

案例:由扫码枪实体按键触发扫码动作,监听手持终端的扫码结果广播,获取扫码结果。

硬件设备:Honeywell 手持终端EDA51

设置:在“设置 - Honeywell设置 - Scanning - Internal Scanner - Default profile - Data Processing Settings - Data Intent”中启用Data Intent

广播地址:在上一步中勾选启用Data Intent后,点击进入Data Intent查看或更改广播地址(action)、扫码结果key名等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
created() {//vue的生命周期created函数
mui.plusReady(() => {
var _vue = this;
//监听扫码枪
var main = plus.android.runtimeMainActivity(); //获取activity
var context = plus.android.importClass('android.content.Context'); //上下文
//广播接收器
var receiver = plus.android.implements('io.dcloud.feature.internal.reflect.BroadcastReceiver', {
onReceive: doReceive //回调
});
var IntentFilter = plus.android.importClass('android.content.IntentFilter');
var Intent = plus.android.importClass('android.content.Intent');
var filter = new IntentFilter();
//添加过滤条件:扫码枪的广播
//手持终端EDA51,在“设置 - Honeywell设置 - Scanning - Internal Scanner - Default profile - Data Processing Settings - Data Intent”中查看默认广播地址(记得要启用Data Intent)
filter.addAction("com.honeywell.ezservice.uniqueaction");
main.registerReceiver(receiver, filter); //注册监听

function doReceive(context, intent) {
plus.android.importClass(intent); //通过intent实例引入intent类,方便以后的‘.’操作
//获取扫码结果。不同产品,key名可能不同。手持终端EDA51是data
var data = intent.getStringExtra("data");
//console.log(data);

//业务逻辑

//main.unregisterReceiver(receiver); //取消监听
}
})
}

更多:

https://max.book118.com/html/2019/0818/6034202014002055.shtm

https://ask.dcloud.net.cn/article/35044

MUI相关

教程:MUI教程

事件绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!--右上角弹出菜单-->
<div id="topPopover" class="mui-popover" style="width: 130px; height: 60px;">
<div class="mui-popover-arrow"></div>
<div class="mui-scroll-wrapper">
<div class="mui-scroll">
<ul class="mui-table-view">
<li id="re_scan" class="mui-table-view-cell"><a>重新盘点</a>
</ul>
</div>
</div>
</div>


//右上角事件
mui("#topPopover").on("tap","#topPopover ul li",function(e){
var btnType = this.id;

//重新盘点
if(btnType == "re_scan"){//“按钮”上的id
if(cur_status == '3'){
mui.alert("当前盘点任务已完成,不能再执行该操作了!");
return;
}
jxm.confirm("是否清除所有已盘点数据,并重新盘点?", function(){
DeviceScanUtil.reScan(scan_id);
});
}
});

使用e.stoppropagation();来阻止冒泡事件。放在function(e){}的最后即可。

页面跳转传值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//跳转
mui.openWindow({
url: 'outstore_det.html',//页面地址(相对地址)
extras: {
now_item: 'item数据'
}
});

//获取值
mui.plusReady(()=>{
var item = plus.webview.currentWebview().now_item;
})

//返回上一级:
mui.back();

扩展:页面之间跳转,并指定执行目标页面的函数,使用自定义事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
//1.准备:
//在初次打开页面store_check.html时,openWindow中添加id
mui.openWindow({
id: 'store_check.html',
url: 'app/store_check/store_check.html'
});


//2.页面跳转
//2.1跳转到目标页面store_check.html
//2.2调用(执行)目标页面中的函数refreshData()
//2.3携带的参数为isRefresh:true(页面间传值)
//2.4openWindow中使用id
mui.alert('提交成功!', '提示', '确认', () => {
//返回 盘点任务 页面,并更新数据
var Page = plus.webview.getWebviewById('store_check.html');
mui.fire(Page, 'refreshData', {
isRefresh: true
});
mui.openWindow({
id: 'store_check.html'
});
});

//3.目标页面
//添加 refreshData自定义事件监听 更新盘点任务(提交盘点后重新进入该页面)
window.addEventListener('refreshData', function(event) {
//获得事件参数
var isRefresh = event.detail.isRefresh;
if(isRefresh) {
//清空数据
vm.dataSource = [];
//重置当前页、页面大小
vm.currentPage = 0;
vm.pageSize = 10;
//加载数据
vm.loadList();
}
});

转圈圈动画

1
2
3
4
//启动
//if(window.plus) var wa=plus.nativeUI.showWaiting();
//关闭
//if(window.plus)wa.close();

退出程序

1
2
3
if(confirm("确认退出?")){
plus.runtime.quit();
}

对话框设置

1
2
3
4
5
6
7
8
9
10
//输入对话框mui.prompt

//设置 默认值
document.querySelector('.mui-popup-input input').value = item.sp_outstore_det__out_num; //输入框默认值
//设置 键盘类型
document.querySelector('input').type = 'number'; //数字键盘
document.querySelector('input').pattern = '\d*'; //数字 九宫格键盘
//设置 焦点
document.querySelector('input').focus(); //获取焦点
document.querySelector('input').blur();//失去焦点(隐藏键盘)

上拉刷新

1
2
//上拉刷新。加载动画的隐藏,使用下边的方式:
mui('#refreshContainer').pullRefresh().endPullupToRefresh((this.currentPage + 1) * this.pageSize + 1 >= data.total);

click事件失效

vue的click事件失效。

在移动端,应该使用tap事件代替click事件。

返回顶部

列表过长时,提供返回顶部按钮。

配合上边的上拉刷新。

1
2
3
4
5
6
7
8
<button type="button" class="mui-btn" style="position: fixed;right: 20px;bottom: 20px;z-index: 100;border-radius: 50%;" @click="clicked">
<i class="mui-icon mui-icon-arrowup" style="font-size: 35px;"></i>
</button>


clicked() {
mui('#refreshContainer').pullRefresh().scrollTo(0, 0, 100); // 滚动到顶部
}

问题记录

注意:jxstar项目文件不要直接覆盖(残留文件会导致类/文件找不到的情况)

登录问题

1.提示软件失效

错误提示如下:

1
2
jxstar load license 2021-12-02
软件失效代码为204,请联系软件开发商!

需要更新本地tomcat中的许可文件license.dat。文件存放路径为:

1
2
3
tomcat\apache-tomcat-7.0.94\webapps\jxstar\WEB-INF\classes\license.dat

WEB-INF\classes\license.dat

一般是通用的,可以在客户系统的测试系统中拷贝下来替换掉本地的旧的许可文件。

2.无法登录

登录时报错,有可能是已过“用户许可试用日期”。

需要更新sys_var表的变量license.user.endtime,将var_value改成大于当前日期。

1
update sys_var set var_value = '3E333B463333333B3933' where var_code = 'license.user.endtime'

3.无法加载文件

问题:转圈圈,提示无法加载系统文件。

解决方法:若tomcat版本为8可尝试降为6

4.无法访问

提示“not key [index.dbnostart] text!”,无法访问。

可能是mysql版本不对,若是8.x版本可尝试切换到5.x版本。

5.提示未登录

情况一:打开新建的html文件,提示未登录。可访问“wx_nologin.html”实现免登录访问。

1
http://127.0.0.1:8848/jxwx/wx_nologin.html?usercode=admin

情况二:移动app,登录进入功能列表后还提示“用户没有登录”,有可能是账号未激活。可以尝试在PC端激活用户(系统设置 - 权限设置 - 用户注册 - “更多”菜单中选择激活)

记录查询出错

登录系统后,提示“记录查询出错”。tomcat控制台提示root用户无权限(mysql问题)

wheresql

where_sql不可用。

高版本的jxstar,使用where_sql时需在“开发平台-功能管理-where注册”中进行注册。使用时where_sql后边的值填写注册所设置的标识。

若图片不能正常显示,请在浏览器中打开

欢迎关注我的其它发布渠道