uniapp开发企业微信应用中的定位问题记录

Posted /*梦里花落知多少*/

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uniapp开发企业微信应用中的定位问题记录相关的知识,希望对你有一定的参考价值。

开发工具为HBuilderX,框架为uniapp,开发移动端的Web应用,在企业微信中使用(自建应用),在获取用户定位中遇到的问题记录。

项目背景:开发工具为HBuilderX,框架为uniapp,开发移动端的Web应用,在企业微信中使用(自建应用),Web开发的应用,不是小程序。
需求点:获取用户当前的位置信息,技术流程包括以下几个环节:

  • 1、获取当前用户的经纬度位置信息,用的uniapp的uni.getLocation()接口。
  • 2、显示一个地图,标记用户的位置,用的百度地图SDK。
  • 3、地图可以拖动,拖动后标记点会跟着移动,让用户可以自行调整位置。
  • 4、获取标记点详细地址,采用百度地图的逆解析API,获得详细位置信息。

❓问题:但实际开发中定位老是不准,存在各种问题,最后通过升级HTTPS解决,记录一下处理过程。


01、百度地图

百度地图开放平台,注册一个开发者账号,百度地图需要申请一个KEY才能使用。可根据项目情况选择个人账号,还是企业账号。

类型 个人账号 企业开发者账号
应用场景 个人学习 企业商业使用
认证方式 开发者认证,个人实名认证(已完成) 企业名称、营业执照、法人、联系方式、对公帐号信息
认证时长 很快 几分钟-5个工作日,多种认证方式
收费 白嫖 商业授权,基础版5W/年
调用限额 JS API 定位:5,000次/日,并发10次/秒
JS API 逆地理编码:5,000次/日,并发30次/秒
JS API 定位:30W次/日,并发100次/秒
JS API 逆地理编码:300W次/日,并发100次/秒

方案

  • 如果使用次数较多,则需要考虑企业账号,或购买额度。
  • 一般小项目、公司内部使用,调用频次不多,可申请个人账号,或者多申请几个账号,轮训使用。

uniapp app和微信小程序使用腾讯地图定位

1. 首先 注册个腾讯地图定位的key 链接https://lbs.qq.com/dev/console/key/add2. 在官网下载好 sdk 保存到你项目里面

3.使用sdk

import QQMapWX from "./wxsdk/qqmap-wx-jssdk.min.js";
import  newModal  from './new-modal.js'
 let getLocation;
 
 // #ifdef MP-WEIXIN
getLocation = () => 
   return new Promise((resolve, reject) => 
     // 获取授权信息
     uni.getSetting(
       success: res => 
         if (res.authSetting && res.authSetting.hasOwnProperty("scope.userLocation")) 
           if (res.authSetting["scope.userLocation"]) 
             getCityInfo();
            else 
             uni.showModal(
               title: "提示",
               content: "请重新授权获取你的地理位置,否则部分功能将无法使用",
               success: (res) => 
                 if (res.confirm) 
                   uni.openSetting(
                     success: () => getCityInfo()
                   );
                  else 
                   reject("请授权获取你的地理位置,否则部分功能将无法使用!");
                 
               ,
             );
           
          else 
           getCityInfo();
         
       
     );
  
     // 获取地理位置信息
     const getCityInfo = () => 
       // 腾讯地图Api
 	  console.log("locaiton getting")
       const qqmapsdk = new QQMapWX( key: "你的key" );
       // 授权
       uni.authorize(
         scope: "scope.userLocation",
         success: () => 
           uni.getLocation(
             type: "gcj02", //  wgs84: 返回GPS坐标,gcj02: 返回国测局坐标
             success: res => 
               const latitude, longitude = res;
               const location = latitude, longitude;
 			  console.log(location)
               qqmapsdk.reverseGeocoder(
                 location,
                 success: res => resolve(res.result),
 				fail: err => 
 					console.log(err)
 				
               );
             
           );
         ,
         fail: () => reject("请授权获取你的位置,否则部分功能将无法使用!"),
       );
     ;
   );
 ;
 // #endif
 
 // #ifdef APP-PLUS
import gotoAppPermissionSetting, checkSystemEnableLocation from './permission.js'
getLocation = () => 
 	const qqmapsdk = new QQMapWX(
 		key: "你的key"
 	);
	return new Promise((resolve, reject) => 
		uni.getLocation(
			type: "gcj02", //  wgs84: 返回GPS坐标,gcj02: 返回国测局坐标
			success: res => 
				const 
					latitude,
					longitude
				 = res;
				const location = 
					latitude,
					longitude
				;
				qqmapsdk.reverseGeocoder(
					location,
					success: res => 
						resolve(res.result)
					,
					fail: err => 
						console.log(err)
					
				);
			,
			fail(err) 
				const res = checkSystemEnableLocation()
				if(!res) 
					newModal(
						title: "设备定位未开启",
						content: "是否去开启?",
						success(res) 
							if(res.confirm) 
								gotoAppPermissionSetting()
							
						
					)
				
			
		)
	)
 ;
 
 // #endif
 export default getLocation;

newModal 只是一个美化的 uni.showModal 可以以此代替

对这个感兴趣的  以下是它的封装

export const newModal = function(options) 
	let optionsObj = Object.assign(
		title: "提示",
		content: "自定义内容",
		align: "center", // 对齐方式 left/center/right
		cancelText: "取消", // 取消按钮的文字
		cancelColor: "#8F8F8F", // 取消按钮颜色
		confirmText: "确定", // 确认按钮文字
		confirmColor: "#26bc98", // 确认按钮颜色 
		showCancel: true, // 是否显示取消按钮,默认为 true
	, options);
	// 以下为计算菜单的nview绘制布局,为固定算法,使用者无关关心
	const screenWidth = plus.screen.resolutionWidth;
	const screenHeight = plus.screen.resolutionHeight;
	//弹窗容器宽度
	const popupViewWidth = screenWidth * 0.76;
	// 弹窗容器的Padding
	const viewContentPadding = 20;

	// 弹窗容器的宽度
	const viewContentWidth = parseInt(popupViewWidth - (viewContentPadding * 2));
	// 描述的列表
	const text = optionsObj.content;
	const maxWidth = viewContentWidth
	let textArr = text.split("");
	let len = textArr.length;
	// 上个节点
	let previousNode = 0;
	// 记录节点宽度
	let nodeWidth = 0;
	// 文本换行数组
	let rowText = [];
	// 如果是字母,侧保存长度
	let letterWidth = 0;
	// 汉字宽度
	let chineseWidth = 16;
	// otherFont宽度
	let otherWidth = 8;
	for (let i = 0; i < len; i++) 
		if (/[\\u4e00-\\u9fa5]|[\\uFE30-\\uFFA0]/g.test(textArr[i])) 
			if (letterWidth > 0) 
				if (nodeWidth + chineseWidth + letterWidth * otherWidth > maxWidth) 
					rowText.push(
						type: "text",
						content: text.substring(previousNode, i)
					);
					previousNode = i;
					nodeWidth = chineseWidth;
					letterWidth = 0;
				 else 
					nodeWidth += chineseWidth + letterWidth * otherWidth;
					letterWidth = 0;
				
			 else 
				if (nodeWidth + chineseWidth > maxWidth) 
					rowText.push(
						type: "text",
						content: text.substring(previousNode, i)
					);
					previousNode = i;
					nodeWidth = chineseWidth;
				 else 
					nodeWidth += chineseWidth;
				
			
		 else 
			if (/\\n/g.test(textArr[i])) 
				rowText.push(
					type: "break",
					content: text.substring(previousNode, i)
				);
				previousNode = i + 1;
				nodeWidth = 0;
				letterWidth = 0;
			 else if (textArr[i] == "\\\\" && textArr[i + 1] == "n") 
				rowText.push(
					type: "break",
					content: text.substring(previousNode, i)
				);
				previousNode = i + 2;
				nodeWidth = 0;
				letterWidth = 0;
			 else if (/[a-zA-Z0-9]/g.test(textArr[i])) 
				letterWidth += 1;
				if (nodeWidth + letterWidth * otherWidth > maxWidth) 
					rowText.push(
						type: "text",
						content: text.substring(previousNode, i + 1 - letterWidth)
					);
					previousNode = i + 1 - letterWidth;
					nodeWidth = letterWidth * otherWidth;
					letterWidth = 0;
				
			 else 
				if (nodeWidth + otherWidth > maxWidth) 
					rowText.push(
						type: "text",
						content: text.substring(previousNode, i)
					);
					previousNode = i;
					nodeWidth = otherWidth;
				 else 
					nodeWidth += otherWidth;
				
			
		
	
	if (previousNode < len) 
		rowText.push(
			type: "text",
			content: text.substring(previousNode, len)
		);
	
	const descriptionList = rowText;
	// 弹窗高度
	let popupViewHeight = 168;
	// 弹窗遮罩层
	let maskLayer = new plus.nativeObj.View("maskLayer",  //先创建遮罩层
		top: '0px',
		left: '0px',
		height: '100%',
		width: '100%',
		backgroundColor: 'rgba(0,0,0,0.5)'
	);
	let popupViewContentList = [
		tag: 'font',
		id: 'title',
		text: optionsObj.title,
		textStyles: 
			size: '18px',
			color: "#333",
			weight: "bold",
			whiteSpace: "normal"
		,
		position: 
			top: viewContentPadding + "px",
			left: viewContentPadding + "px",
			width: viewContentWidth + "px",
			height: "30px",
		
	];
	const textHeight = 22;
	let contentTop = 65;
	descriptionList.forEach((item, index) => 
		if (index > 0) 
			popupViewHeight += textHeight;
			contentTop += textHeight;
		
		popupViewContentList.push(
			tag: 'font',
			id: 'content' + index + 1,
			text: item.content,
			textStyles: 
				size: '14px',
				color: "#333",
				lineSpacing: "50%",
				align: optionsObj.align
			,
			position: 
				top: contentTop + "px",
				left: viewContentPadding + "px",
				width: viewContentWidth + "px",
				height: textHeight + "px",
			
		);
		if (item.type == "break") 
			contentTop += 10;
			popupViewHeight += 10;
		
	);
	popupViewContentList.push(
		tag: 'rect',
		id: 'lineTop',
		rectStyles: 
			color: "#f1f1f1",
		,
		position: 
			top: contentTop + 50 + "px",
			left: "0px",
			width: "100%",
			height: "1px",
		
	);
	if (optionsObj.showCancel) 
		popupViewContentList.push(
			tag: 'rect',
			id: 'line',
			rectStyles: 
				color: "#f1f1f1",
			,
			position: 
				top: contentTop + 50 + "px",
				left: popupViewWidth / 2 + "px",
				width: "1px",
				height: "50px",
			
		);
		popupViewContentList.push(
			tag: 'font',
			id: 'cancelText',
			text: optionsObj.cancelText,
			textStyles: 
				size: '15px',
				color: optionsObj.cancelColor,
			,
			position: 
				top: contentTop + 50 + "px",
				left: "0px",
				width: popupViewWidth / 2 + "px",
				height: "50px",
			
		);
		popupViewContentList.push(
			tag: 'font',
			id: 'confirmText',
			text: optionsObj.confirmText,
			textStyles: 
				size: '15px',
				color: optionsObj.confirmColor,
			,
			position: 
				top: contentTop + 50 + "px",
				left: popupViewWidth / 2 + "px",
				width: popupViewWidth / 2 + "px",
				height: "50px",
			
		);
	 else 
		popupViewContentList.push(
			tag: 'font',
			id: 'confirmText',
			text: optionsObj.confirmText,
			textStyles: 
				size: '16px',
				color: optionsObj.confirmColor,
			,
			position: 
				top: contentTop + 50 + "px",
				left: "0px",
				width: "100%",
				height: "50px",
			
		);
	
	// 弹窗内容
	let popupView = new plus.nativeObj.View("popupView",  //创建底部图标菜单
		tag: "rect",
		top: (screenHeight - popupViewHeight) / 2 + "px",
		left: '10%',
		height: popupViewHeight + "px",
		width: "80%"
	);
	// 绘制白色背景
	popupView.drawRect(
		color: "#FFFFFF",
		radius: "8px"
	, 
		top: "0px",
		height: popupViewHeight + "px",
	);
	popupView.draw(popupViewContentList);
	popupView.addEventListener("click", function(e) 
		if (optionsObj.showCancel) 
			if (e.clientY > popupViewHeight - 50 && e.clientX < popupViewWidth / 2) 
				// 取消
				maskLayer.close();
				popupView.close();
				options.success && options.success(
					confirm: false,
					cancel: true
				);
			 else if (e.clientY > popupViewHeight - 50 && e.clientX > popupViewWidth / 2) 
				// 确定
				maskLayer.close();
				popupView.close();
				options.success && options.success(
					confirm: true,
					cancel: false
				);
			
		 else 
			if (e.clientY > popupViewHeight - 50) 
				// 确定
				maskLayer.close();
				popupView.close();
				options.success && options.success(
					confirm: true,
					cancel: false
				);
			
		
	);
	// 显示弹窗
	maskLayer.show();
	popupView.show();
	options.complete && options.complete();
;

getLocation 使用

import getLocation from '../../../utils/getLocation.js'
getl() 
	const self = this
	getLocation().then(res => 
		self.address = res.address
	)

以上是关于uniapp开发企业微信应用中的定位问题记录的主要内容,如果未能解决你的问题,请参考以下文章

uniapp实战笔记微信小程序设置字体的开发踩坑记录

uniapp app和微信小程序使用腾讯地图定位

uniapp 实现企业微信网页授权登录

uni-k如何连接微信

uniapp小程序实战—— 使用腾讯地图获取定位

uniapp小程序实战—— 使用腾讯地图获取定位