1. 概述
1.1 版本
报表服务器版本 | App版本 |
---|---|
11.0 | V11.0 |
1.2 应用场景
用户希望一键获取当前地理位置,或把当前地理位置实时展示在地图上便于信息确认。
1.3 功能简介
本文介绍如何获取当前地理位置。
注:以下示例仅演示如何获取地理位置,如需进行填报,需要自行设置模板填报属性,详细步骤可参考:设置填报属性 。
示例 | 实现思路 |
---|---|
示例一:普通报表获取经纬度 | 在普通报表中添加按钮,给按钮添加 JS 事件。 在 JS 中使用 FR.location 方法,直接获取当前位置的经纬度 |
示例二:决策报表获取经纬度 | 在决策报表中添加文本控件,给控件添加 JS 事件。 在 JS 中使用 FR.location 方法,直接获取当前位置的经纬度 |
示例三:FVS 获取经纬度及地理位置名称 | 在 FVS 中添加标题组件,给组件添加 JS 事件。 在 JS 中实现以下步骤: 1)使用 FR.location 方法获取当前位置的经纬度。 2)由于 ios 端和Android端返回的经纬度坐标系不同,调用高德的坐标转换 API 接口,根据设备类型,将经纬度统一转换成火星坐标系。 3)调用高德逆地理编码 API 接口将经纬度转换成实际的地理位置名称。 |
示例四:普通报表获取经纬度、地理位置名称及刷新地图 | 在普通报表中添加按钮,给按钮添加 JS 事件。 在 JS 中实现以下步骤: 1)使用 FR.location 方法获取当前位置的经纬度。 2)由于 ios 端和Android端返回的经纬度坐标系不同,调用高德的坐标转换 API 接口,根据设备类型,将经纬度统一转换成火星坐标系。 3)调用高德逆地理编码 API 接口将经纬度转换成实际的地理位置名称。 4)点地图绑定经纬度,使用图表刷新接口刷新地图,快速定位到准确位置。 |
2. 示例一:普通报表获取经纬度
本节示例:制作一张签到模板,点击「地理位置」按钮获取当前位置的经纬度,并填入下方对应的单元格中。如下图所示:
2.1 准备模板
1)设置主体内容
打开设计器,新建一张普通报表,模板样式如下图所示。
2)添加控件
设置 E2 单元格为按钮控件,控件名称为「地理位置」。
设置 C5 单元格为下拉框控件,E5 单元格为时间控件。如下图所示:
2.2 JS 获取经纬度
选中 E2 单元格,在右侧属性面板中点击「控件设置>事件」,给按钮控件添加一个点击事件。
在 JavaScript 脚本中,通过 FR.location 方法获取地理位置的经纬度,如果 status 值为 success,则表示获取地理位置成功,否则定位失败。
如果定位成功,则将返回的地理位置信息通过 setCellValue 赋值给 C4 单元格。如下图所示:
注:该方法只适用于移动端,如果在 Web 点击该按钮事件获取地理位置,则直接提示定位失败。
JavaScript 代码如下所示:
FR.location(function(status, message){ //获取地理位置
if(status=="success") {
//定位成功,message返回经纬度值
FR.Msg.alert("当前位置是" + message);
contentPane.setCellValue(2, 3, message);
} else {
//定位失败,message返回对应的错误信息
FR.Msg.alert(message); //定位失败
}
});
2.3 JS 获取当前时间
选中 E2 单元格,在右侧属性面板中点击「控件设置>事件」,给按钮控件再添加一个点击事件。
在 JavaScript 脚本中, 将获取到的当前签到时间赋值给 E4 单元格。如下图所示:
JavaScript 代码如下:
var myDate = new Date();
var mytime=myDate.getFullYear()+"-"+(myDate.getMonth()+1)+"-"+myDate.getDate()+" "+myDate.getHours()+":"+myDate.getMinutes()+":"+myDate.getSeconds(); //获取当前时间
contentPane.setCellValue(4, 3, mytime);
2.4 效果查看
App 直接扫码填报预览或将制作完成的模板挂载至数据决策系统,类型选择「填报」,即在 App 目录中查看,详细挂载步骤请查看 添加模板,如下图所示:
App 预览效果如下图所示:
3. 示例二:决策报表获取经纬度
本节示例:制作一张决策报表,预览时自动获取当前位置的经纬度。
3.1 准备模板
新建一张决策报表,在表单内添加 2 个「文本控件」,控件名称分别为 jingdu、weidu 。如下图所示:
3.2 添加事件
选中一个文本控件,如 jingdu ,为其添加一个「初始化后事件」。如下图所示:
JavaScript 代码如下:
var self = this;
FR.location(function(status, message){
if(status=="success") {
var jingwei=message.split(",") ;
self.options.form.getWidgetByName("jingdu").setValue(jingwei[1]);
self.options.form.getWidgetByName("weidu").setValue(jingwei[0]); }
});
3.3 效果预览
App 直接扫码预览或将制作完成的模板挂载至数据决策系统,即可在 App 目录中查看,详细挂载步骤请查看 添加模板 。
App 预览效果如下图所示:
4. 示例三:FVS 获取经纬度及地理位置名称
本节示例:制作一张 FVS 模板,点击「点我获取经纬度及地理位置名称」获取当前位置的经纬度及地理位置名称。
4.1 环境准备
本节方案需要使用到高德的坐标转换 API 接口和逆地理编码 API 接口,在使用接口前需前往高德开放平台申请 Web 服务 API 类型 Key 。
示例代码中使用的高德 KEY 仅用于方案展示,不可在正式环境中使用。
注1:如需在正式环境中使用该方案,需自行前往高德官网申请免费/付费 key,请前往:高德开放平台 。
注2:如只需获取经纬度,不需获取地理位置名称,则不需要进行此节环境准备操作。
4.2 准备模板
1)打开 FineReport 设计器,点击菜单栏「文件>新建可视化看板」。
2)点击「创建看板」,如下图所示:
3)点击左侧组件列表栏的「文字」组件,将「标题」拖入画布中,如下图所示:
4)选中「标题」组件,在右侧配置栏「内容」中设置标题内容为「点我获取经纬度及地理位置名称」,如下图所示:
4.3 添加事件
1)选中「标题」组件,点击右侧配置栏「交互>点击事件>添加点击事件>JavaScript」。
2)设置事件名称为「获取经纬度及地理位置名称」,输入 JavaScript 代码,点击「确定」,如下图所示:
JavaScript 代码如下:
duchamp.location(function(status, message, coordinate) { //三个参数,status是状态(success,fail),message是经纬度(如31.590668,120.457507),coordinate是坐标系信息(ios返回WGS84,Android返回GCJ02)。
if (status == "success") { //获取经纬度成功时执行此函数
var aa = message.split(','); //message是一个,分割的字符串,转换成数组
weidu = aa[0]; //获取数据分析app、企业微信、钉钉返回的纬度
jingdu = aa[1]; //获取数据分析app、企业微信、钉钉返回的经度
if (coordinate == "WGS84") { //根据坐标系判断当前设备是Android还是ios,Android返回GCJ02,ios返回WGS84,当手机是ios时执行以下代码
var url1 = "https://restapi.amap.com/v3/assistant/coordinate/convert?locations=" + jingdu + "," + weidu + "&coordsys=gps&output=json&key=4eff2ee8c07f35b8702722abc8f35bf2"; //调用高德API将ios返回的地球坐标系经纬度转换为火星坐标系
duchamp.ajax({
url: url1,
type: "get", //高德api要求使用get方式请求
dataType: "jsonp", //跨域使用jsonp方式
success: function(data) { //请求成功时调用此函数
if (data.status == "1") { //高德api接口返回的状态码是1(请求成功)
jingdu = data.locations.split(',')[0]; //获取转换后的经度
weidu = data.locations.split(',')[1]; //获取转换后的纬度
var url2 = "https://restapi.amap.com/v3/geocode/regeo?output=json&location=" + jingdu + "," + weidu + "&key=4eff2ee8c07f35b8702722abc8f35bf2&radius=10&extensions=all"; //调用高德API根据经纬度进行逆地理编码
duchamp.ajax({
url: url2,
type: "get", //高德api要求使用get方式请求
dataType: "jsonp", //跨域使用jsonp方式
success: function(msg) { //请求成功时调用此函数
if (msg.status == "1") { //高德api接口返回的状态码是1(请求成功)
var address = msg.regeocode.formatted_address; //从高德API返回的结果中,取出结构化地址,即地理位置名称
if (address != null && address != "" && address != "null") { //判断地址是否为空
duchamp.Msg.alert({title:"当前经纬度和地址:",message:jingdu+","+weidu+","+address});//地址不为空,则弹出当前经纬度和地址
} else {
duchamp.Msg.alert({title:"警告:",message:"无法获取当前地址"});//地址为空,则弹出警告
}
};
if (msg.status == "0") { //高德api接口返回的状态码是0(请求失败)
duchamp.Msg.alert({title:"警告:",message:"经纬度转换地址出错:错误信息是" + msg.info + ",错误码是:" + msg.infocode + ",详情请访问:https://lbs.amap.com/api/webservice/guide/tools/info/"}); //如果出错,弹出高德api返回的报错
}
},
error: function(info) { //请求失败时调用此函数
duchamp.Msg.alert({title:"警告:",message:"请求失败,请联系管理员。"});
},
complete: function(XMLHttpRequest, status) { //请求完成后最终执行回调函数
if (status == 'timeout') { //超时,status还有success,error等值的情况
duchamp.Msg.alert({title:"警告:",message:"请求超时,请检查网络。"});
}
},
timeout: 3000, //超时时间为3S
async: "false" //同步请求,和上面的ajax请求不是异步的,需要顺序执行
});
};
if (data.status == "0") { //高德api接口返回的状态码是0(请求失败)
duchamp.Msg.alert({title:"警告:",message:"经纬度转换坐标系出错:错误信息是" + data.info + ",错误码是:" + data.infocode + ",详情请访问:https://lbs.amap.com/api/webservice/guide/tools/info/"}); //如果出错,弹出高德api返回的报错
}
},
error: function(info) { //请求失败时调用此函数
duchamp.Msg.alert({title:"警告:",message:"请求失败,请联系管理员。"});
},
complete: function(XMLHttpRequest, status) { //请求完成后最终执行回调函数
if (status == 'timeout') { //判断是否超时,status还有success,error等值的情况
duchamp.Msg.alert({title:"警告:",message:"请求超时"});
}
},
timeout: 3000, //超时时间为3s
async: "false" //同步请求,和下面的ajax请求不是异步的,需要顺序执行
});
} else { //当手机是Android时,执行以下代码
var url3 = "https://restapi.amap.com/v3/geocode/regeo?output=json&location=" + jingdu + "," + weidu + "&key=4eff2ee8c07f35b8702722abc8f35bf2&radius=10&extensions=all"; //调用高德API根据经纬度进行逆地理编码
duchamp.ajax({
url: url3,
type: "get", //高德api要求使用get方式请求
dataType: "jsonp", //跨域使用jsonp方式
success: function(msg) { //请求成功时调用此函数
if (msg.status == "1") { //高德api接口返回的状态码是1(请求成功)
var address = msg.regeocode.formatted_address; //从高德API返回的结果中,取出结构化地址,即地理位置名称
if (address != null && address != "" && address != "null") { //判断地址是否为空
duchamp.Msg.alert({title:"当前经纬度和地址:", message:jingdu+","+weidu+","+address});//地址不为空,则弹出当前经纬度和地址
} else {
duchamp.Msg.alert({title:"警告:",message:"无法获取当前地址"});//地址为空,则弹出警告
}
};
if (msg.status == "0") { //高德api接口返回的状态码是0(请求失败)
duchamp.Msg.alert({title:"警告:",message:"经纬度转换地址出错:错误信息是" + msg.info + ",错误码是:" + msg.infocode + ",详情请访问:https://lbs.amap.com/api/webservice/guide/tools/info/"}); //如果出错,弹出高德api返回的报错
}
},
error: function(info) { //请求失败时调用此函数
duchamp.Msg.alert({title:"警告:",message:"请求失败,请联系管理员。"});
},
complete: function(XMLHttpRequest, status) { //请求完成后最终执行回调函数
if (status == 'timeout') { //超时,status还有success,error等值的情况
duchamp.Msg.alert({title:"警告:",message:"请求超时,请检查网络。"});
}
},
timeout: 3000, //超时时间为3S
async: "false" //同步请求,和上面的ajax请求不是异步的,需要顺序执行
});
}
} else { //获取经纬度失败时执行此函数
duchamp.Msg.alert({title:"警告:",message:"错误:请检查手机网络和定位服务开关及权限,或联系管理员。" + "\n" + "状态码:" + status + "\n" + "错误信息:" + JSON.stringify(message)}); //数据分析app、企业微信、钉钉获取经纬度失败时返回报错信息
}
});
4.4 效果预览
App 直接扫码预览或将制作完成的模板挂载至数据决策系统,即可在 App 目录中查看,详细挂载步骤请查看 添加模板 。
App 预览效果如下图所示:
5. 示例四:普通报表获取经纬度、地理位置名称及刷新地图
示例:制作一张普通报表,点击「地理位置」按钮获取当前位置信息,并填入相应的单元格中,同时自动刷新地图,把当前地理位置展示在地图上方便用户确认。
注:该方案支持移动端app、企业微信集成、钉钉集成。
5.1 环境准备
本节方案需要使用到高德的坐标转换 API 接口和逆地理编码 API 接口,在使用接口前需前往高德开放平台申请 Web 服务 API 类型 Key 。
示例代码中使用的高德 KEY 仅用于方案展示,不可在正式环境中使用。
注:如需在正式环境中使用该方案,需自行前往高德官网申请免费/付费 key,请前往:高德开放平台 。
注2:如只需获取经纬度,不需获取地理位置名称,则不需要进行此节环境准备操作。
5.2 准备模板
1)设置主体内容
打开设计器,新建一张普通报表,模板样式如下图所示。
注:需确保经度、纬度、地名存放在固定的单元格中,便于后续点地图绑定单元格数据。
2)设计地图
合并 B1~H21 单元格区域,选中单元格,点击工具栏 插入图表,选择「地图>点地图」。如下图所示:
选中地图所在单元格,点击右侧属性面板「单元格元素」,选择「类型」, 地图点选择「中国」,GIS 图层选择「高德地图」。
选择「数据」, 数据集来源为「单元格数据」,使用「经纬度定位」,绑定单元格内的经纬度和位置信息。具体设置如下图所示:
3)添加控件
合并 J3~L3单元格,设置 J3 单元格为按钮控件,如下图所示:
5.3 添加事件
选中 J3 单元格,在右侧属性面板中点击「控件设置>事件」,给按钮控件添加一个「点击」事件,事件需要设置一个地图位置参数。如下图所示:
JavaScript 代码如下:
FR.location(function(status, message, coordinate) { //三个参数,status是状态(success,fail),message是经纬度(如31.590668,120.457507),coordinate是坐标系信息(ios返回WGS84,Android返回GCJ02)。
if (status == "success") { //获取经纬度成功时执行此函数
var aa = message.split(','); //message是一个,分割的字符串,转换成数组
weidu = aa[0]; //获取数据分析app、企业微信、钉钉返回的纬度
jingdu = aa[1]; //获取数据分析app、企业微信、钉钉返回的经度
if (coordinate == "WGS84") { //根据坐标系判断当前设备是Android还是ios,Android返回GCJ02,ios返回WGS84,当手机是ios时执行以下代码
var url1 = "https://restapi.amap.com/v3/assistant/coordinate/convert?locations=" + jingdu + "," + weidu + "&coordsys=gps&output=json&key=47b4db70b1259b4722957d991202f66d"; //调用高德API将ios返回的地球坐标系经纬度转换为火星坐标系
FR.ajax({
url: url1,
type: "get", //高德api要求使用get方式请求
dataType: "jsonp", //跨域使用jsonp方式
success: function(data) { //请求成功时调用此函数
if (data.status == "1") { //高德api接口返回的状态码是1(请求成功)
jingdu = data.locations.split(',')[0]; //获取转换后的经度
weidu = data.locations.split(',')[1]; //获取转换后的纬度
var url2 = "https://restapi.amap.com/v3/geocode/regeo?output=json&location=" + jingdu + "," + weidu + "&key=47b4db70b1259b4722957d991202f66d&radius=10&extensions=all"; //调用高德API根据经纬度进行逆地理编码
FR.ajax({
url: url2,
type: "get", //高德api要求使用get方式请求
dataType: "jsonp", //跨域使用jsonp方式
success: function(msg) { //请求成功时调用此函数
if (msg.status == "1") { //高德api接口返回的状态码是1(请求成功)
var address = msg.regeocode.formatted_address; //从高德API返回的结果中,取出结构化地址,即地理位置名称
if (address != null && address != "" && address != "null") { //判断地址是否为空
contentPane.setCellValue(9, 1, jingdu);
contentPane.setCellValue(10, 1, weidu);
contentPane.setCellValue(11, 1, address); //给地图绑定的三个单元格赋值
setTimeout(function() {
FR.Chart.WebUtils.getChart(b).dataRefresh(); //刷新地图
}, 1000);
FR.Msg.alert("当前地址是:" + address);
} else {
FR.Msg.alert("无法获取当前地址");
}
};
if (msg.status == "0") { //高德api接口返回的状态码是0(请求失败)
FR.Msg.alert("经纬度转换地址出错:错误信息是" + msg.info + ",错误码是:" + msg.infocode + ",详情请访问:https://lbs.amap.com/api/webservice/guide/tools/info/"); //如果出错,弹出高德api返回的报错
}
},
error: function(info) { //请求失败时调用此函数
FR.Msg.alert("请求失败,请联系管理员。");
},
complete: function(XMLHttpRequest, status) { //请求完成后最终执行回调函数
if (status == 'timeout') { //超时,status还有success,error等值的情况
FR.Msg.alert("请求超时,请检查网络。");
}
},
timeout: 3000, //超时时间为3S
async: "false" //同步请求,和上面的ajax请求不是异步的,需要顺序执行
});
};
if (data.status == "0") { //高德api接口返回的状态码是0(请求失败)
FR.Msg.alert("经纬度转换坐标系出错:错误信息是" + data.info + ",错误码是:" + data.infocode + ",详情请访问:https://lbs.amap.com/api/webservice/guide/tools/info/"); //如果出错,弹出高德api返回的报错
}
},
error: function(info) { //请求失败时调用此函数
FR.Msg.alert("请求失败,请联系管理员。");
},
complete: function(XMLHttpRequest, status) { //请求完成后最终执行回调函数
if (status == 'timeout') { //判断是否超时,status还有success,error等值的情况
FR.Msg.alert("请求超时");
}
},
timeout: 3000, //超时时间为3s
async: "false" //同步请求,和下面的ajax请求不是异步的,需要顺序执行
});
} else { //当手机是Android时,执行以下代码
var url3 = "https://restapi.amap.com/v3/geocode/regeo?output=json&location=" + jingdu + "," + weidu + "&key=47b4db70b1259b4722957d991202f66d&radius=10&extensions=all"; //调用高德API根据经纬度进行逆地理编码
FR.ajax({
url: url3,
type: "get", //高德api要求使用get方式请求
dataType: "jsonp", //跨域使用jsonp方式
success: function(msg) { //请求成功时调用此函数
if (msg.status == "1") { //高德api接口返回的状态码是1(请求成功)
var address = msg.regeocode.formatted_address; //从高德API返回的结果中,取出结构化地址,即地理位置名称
if (address != null && address != "" && address != "null") { //判断地址是否为空
contentPane.setCellValue(9, 1, jingdu);
contentPane.setCellValue(10, 1, weidu);
contentPane.setCellValue(11, 1, address); //给地图绑定的三个单元格赋值
setTimeout(function() {
FR.Chart.WebUtils.getChart(b).dataRefresh(); //刷新地图
}, 1000);
FR.Msg.alert("当前地址是:" + address);
} else {
FR.Msg.alert("无法获取当前地址");
}
};
if (msg.status == "0") { //高德api接口返回的状态码是0(请求失败)
FR.Msg.alert("经纬度转换地址出错:错误信息是" + msg.info + ",错误码是:" + msg.infocode + ",详情请访问:https://lbs.amap.com/api/webservice/guide/tools/info/"); //如果出错,弹出高德api返回的报错
}
},
error: function(info) { //请求失败时调用此函数
FR.Msg.alert("请求失败,请联系管理员。");
},
complete: function(XMLHttpRequest, status) { //请求完成后最终执行回调函数
if (status == 'timeout') { //超时,status还有success,error等值的情况
FR.Msg.alert("请求超时,请检查网络。");
}
},
timeout: 3000, //超时时间为3S
async: "false" //同步请求,和上面的ajax请求不是异步的,需要顺序执行
});
}
} else { //获取经纬度失败时执行此函数
FR.Msg.alert("错误:请检查手机网络和定位服务开关及权限,或联系管理员。" + "\n" + "状态码:" + status + "\n" + "错误信息:" + JSON.stringify(message)); //数据分析app、企业微信、钉钉获取经纬度失败时返回报错信息
}
});
5.4 效果预览
App 直接扫码查看或将制作完成的模板挂载至数据决策系统,类型选择「填报」,即可在 App 目录中查看,详细挂载步骤请查看 添加模板,如下图所示:
移动端预览效果如下图所示:
6. 注意事项
问题描述:
制作决策报表时,想调节控件大小,出现如下图的提示:
解决方案:
在「控件设置」里面将「body」的布局方式改为「绝对布局」,就能够自定义控件大小了。
7. 模板下载
1)示例一已完成模板:普通报表获取经纬度.cpt
2)示例二已完成模板:决策报表获取经纬度.frm
3)示例三已完成模板:FVS获取经纬度及地理位置名称.fvs
4)示例四已完成模板:普通报表获取经纬度、地理位置名称及刷新地图.cpt