uni-app项目开发实践h5端总括
# 企业微信/粤政易端
# 初始化
# 引入库方式
iOS特殊处理部分
<script>
let ran = navigator.userAgent
let isIOS = !!ran.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)
if (!isIOS) {
let script = document.createElement('script');
script.src = 'https://res.wx.qq.com/open/js/jweixin-1.2.0.js';
script.async = false;
script.referrerPolicy = 'origin';
document.head.appendChild(script);
script.onload = () => {
console.info('完成手动加载 js-sdk 重写覆盖掉 uni 自带的 window.wx')
}
}
</script>
<script src="https://open.work.weixin.qq.com/wwopen/js/jwxwork-1.0.0.js" type="text/javascript" referrerpolicy="origin"></script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 签名使用时
注意:isH5Ios ? wx : window.jWeixin
不做全局处理;要动态获取
import wx from 'wecomjsdk';
const jsApiList = () => {
const baseApi = [
"invoke",
"getLocation",
"startAutoLBS",
"stopAutoLBS",
"onLocationChange",
"onHistoryBack",
"previewImage",
]
if (isYzy) baseApi.push('openUrl')
return baseApi
}
export const signature = () => {
return new Promise((resolve, reject) => {
const url = location.href.split("#")[0];
const pms = isYzy ? signatureWxyzy({ url: url }) : signatureWxqy({ url: url })
return pms.then(res => {
if (res.code != 0) {
showToast('接口API签名失败!')
reject('error')
return
}
let wxConfig
if(isYzy){
wxConfig = res.data
}else if(isYss){
wxConfig = JSON.parse(res.data)
wxConfig.appId = wxConfig.appid
wxConfig.nonceStr = wxConfig.noncestr
}
const envWx = isH5Ios ? wx : window.jWeixin
console.info('====wxwork==envWx====', envWx)
envWx.config({
debug: false,
beta: true,
appId: wxConfig.appId,
nonceStr: wxConfig.nonceStr,
timestamp: Number(wxConfig.timestamp),
signature: wxConfig.signature,
jsApiList: jsApiList(),
success: (res2: any) => {
console.info('======init===success=====', res2)
},
});
envWx.ready((res2: any) => {
console.info('======ready===success=====', res2)
resolve(res2)
})
envWx.error((error: any) => {
console.error("====signature===config===error===", error)
reject(error)
})
}).catch((error: any) => {
console.error("====signature==catch===error===", error)
})
})
}
}
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# 定位功能
export const getLocation = async (isNeedSign: boolean = false) => {
if (isNeedSign) await signature()
const envWx = isH5Ios ? wx : window.jWeixin
return new Promise((resolve, reject) => {
envWx.getLocation({
type: locationType,
success: function (res: { type: string; longitude: any; latitude: any; }) {
console.info('---wxwork---getLocation---success----', res);
if (isH5Ios) {
const iosLocation = wgs84togcj02(res.longitude, res.latitude)
res.longitude = iosLocation[0]
res.latitude = iosLocation[1]
res.type = locationType
}
resolve(res)
},
fail: function (res: any) {
console.error("应用定位error", res)
reject(res)
},
complete: function (res: any) {
if (res.errMsg === 'getLocation:cancel') {
console.error("应用定位取消", res);
if (isYzy) {
showToast('在设置-应用-粤政易-权限中开启位置权限,以正常使用定位功能', 'none', 5000)
} else if (isYss) {
showToast('在设置-应用-企业微信-权限中开启位置权限,以正常使用定位功能', 'none', 5000)
}
// showToast('应用定位失败,请给应用授权定位权限后,再打开应用使用!', 'none', 5000)
}
},
});
})
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
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
封装引用处理
store
actions: {
GET_CURRENT_LOCATION: ({commit}: ActionContext<RootState, RootState>) => {
return getLocationCoords().then(res => {
const location = {
...DEFAULT_LOCATION,
latitude: res.latitude,
longitude: res.longitude,
}
return coordsToAddress(location).then((res2) => {
location.address = res2.address
location.code = res2.code
commit(GET_CURRENT_LOCATION, location)
})
})
},
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
utils
export const getLocationCoords = () => {
return getLocation().then(Res => {
console.log('当前位置的经纬度:', Res)
const res = JSON.parse(JSON.stringify(Res))
const coords = {
longitude: res.longitude,
latitude: res.latitude,
}
if (res.type == COORDS_TYPE.WGS && (res.latitude + '').split('.')[1].length <= 6 && (res.longitude + '').split('.')[1].length <= 6) {
const location = wgs84togcj02(res.longitude, res.latitude) // 便于后面的天地图转换使用
coords.longitude = location[0]
coords.latitude = location[1]
}
console.log('当前位置的经纬度优化后:', coords.longitude, coords.latitude)
return coords
})
}
export const coordsToAddress = (locationInfo: LocationInfo, codeType: number = 2): Promise<{address: string, code: string}> => {
const locationExt ={
address: DEFAULT_LOCATION.address,
code :DEFAULT_LOCATION.code
}
return new Promise((resolve, reject) => {
uni.request({
url: `${tiandituApi}?postStr={"lon":${locationInfo.longitude},"lat":${locationInfo.latitude},"ver":1}&type=geocode&tk=${tiandituKey}`,
success: (res) => {
console.log('---coordsToAddress---res--', codeType, res)
if (res.statusCode === 200 && res.data) {
let code = locationExt.code
//@ts-ignore //formatted_address county+address
locationExt.address = res.data?.result?.addressComponent.address
switch (codeType) {
case 1:
//@ts-ignore
code = res.data?.result?.addressComponent.province_code
break;
case 2:
//@ts-ignore
code = res.data?.result?.addressComponent.city_code
break;
case 3:
//@ts-ignore
code = res.data?.result?.addressComponent.county_code
break;
}
locationExt.code = code.replace('156', '')
console.log('获取中文街道地理位置成功', locationExt)
resolve(locationExt)
} else {
console.error('获取信息失败,请重试!')
resolve(locationExt)
}
},
fail: (err: any) => {
console.error('获取信息失败,',err)
reject(err)
}
})
})
}
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
使用
mounted() {
this.$store.dispatch('GET_CURRENT_LOCATION')
}
const location = this.$store.state.location
const locationArr = [location.latitude, location.longitude]
1
2
3
4
5
6
2
3
4
5
6
# 导航功能
export const openMapLoaction = (locationInfo: LocationInfo) => {
uni.showActionSheet({
titile:'选择地图应用',
itemList: ['百度地图', '高德地图', ],
success: function (res: any) {
const selectIndex = res.tapIndex + 1
const address = locationInfo.address
// 接口数据默认的是大地坐标系
const [longitude, latitude] = selectIndex == 1 ? wgs84tobd09(locationInfo.longitude, locationInfo.latitude) : wgs84togcj02(locationInfo.longitude, locationInfo.latitude)
let mapUrl = ""
if (selectIndex == 1) {
mapUrl = `http://api.map.baidu.com/marker?location=${latitude},${longitude}&title=${address}&content=''&output=html&src=webapp.baidu.openAPIdemo`
if(isAndroid){
const hasBaiduMap = plus.runtime.isApplicationExist({ pname: 'com.baidu.BaiduMap', action: 'baidumap://' });
if (hasBaiduMap) {
mapUrl = `baidumap://map/marker?location=${latitude},${longitude}&title=${address}&coord_type=bd09ll&src=andr.baidu.openAPIdemo`
}else{
plus.nativeUI.alert("检测到暂未安装本地图应用,请安装后再使用,导航体验效果会更好!");
}
}
}else if(selectIndex == 2){
mapUrl = `http://uri.amap.com/marker?position=${longitude},${latitude}&name=${address}&coordinate=gaode&callnative=1`
if (isAndroid) {
const hasAmap = plus.runtime.isApplicationExist({ pname: 'com.autonavi.minimap', action: 'androidamap://' });
if (hasAmap) {
mapUrl = `androidamap://viewMap?sourceApplication=appname&poiname=${address}&lat=${latitude}&lon=${longitude}&dev=0`
}else{
plus.nativeUI.alert("检测到暂未安装本地图应用,请安装后再使用,导航体验效果会更好!");
}
}
}
mapUrl = encodeURI(mapUrl)
if(isAndroid){
plus.runtime.openURL(mapUrl,(error)=> console.error(error));
}else {
wxwork.openUrl(false, mapUrl)
}
},
fail: function (res: any) {
console.error(res.errMsg);
}
});
}
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
40
41
42
43
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
40
41
42
43
使用
openLoaction(item) {
let locationInfo = {
latitude: item.resCenLat,
longitude: item.resCenLong,
address: item.resName,
};
openMapLoaction(locationInfo)
},
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 缓存处理【重点】
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="Cache-Control" content="no-cache, must-revalidate">
<meta http-equiv="expires" content="0">
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="Cache-Control" content="no-cache, must-revalidate">
<meta http-equiv="expires" content="0">
<title>
<%= htmlWebpackPlugin.options.title %>
</title>
<script>
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || CSS.supports('top: constant(a)'))
document.write('<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + (coverSupport ? ', viewport-fit=cover' : '') + '" />')
</script>
<link rel="stylesheet" href="<%= BASE_URL %>static/index.<%= VUE_APP_INDEX_CSS_HASH %>.css" />
</head>
<body>
<noscript>
<strong>Please enable JavaScript to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
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
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
# 调试处理
# vConsole暗门
引入预留
if (getStorageSync(LOCAL_STORAGE.VCONSOLE)) {
const VConsole = require('vconsole');
new VConsole();
}
1
2
3
4
2
3
4
使用开启
<view class="info-box" @click="addClickNum()">
<view class="name-box">
<text class="user-name">{{ user.name }}</text>
<span v-if="!isPro" style="color: red; font-size: 20px;">【开发模式】</span>
</view>
<text class="user-duty">{{ user.phone | hidePhone }}</text>
</view>
methods: {
addClickNum() {
this.clickNum++;
if(this.clickNum == 10) {
this.clickNum = 0
uni.showModal({
title: '系统配置',
content: `isPro:${isPro}\n baseUrl:${baseUrl}\n`,
success: (res) => {
if (res.confirm) this.showConsole()
}
});
}
},
showConsole() {
if(!getStorageSync(LOCAL_STORAGE.VCONSOLE) || getStorageSync(LOCAL_STORAGE.VCONSOLE) == false) {
setStorageSync(LOCAL_STORAGE.VCONSOLE,true)
}else {
removeStorageSync(LOCAL_STORAGE.VCONSOLE)
}
setTimeout(()=>{
location.reload()
},1000)
},
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
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
# 初始化获取参数
onLaunch() {
console.log('App Launch')
// 根据当前本地缓存判断是否登录
const userInfo = uni.getStorageSync('userInfo')
// 用于刷新后更新store
if(!userInfo){
this.$store.commit('user/SET_USERINFO')
this.$isResolve() // 执行resolve跳出promise
}
// 获取系统栏高度
uni.getSystemInfo({
success: (res) => {
const statusBarHeight = res.statusBarHeight
const versionInfo = {
osVersion: `${res?.model}(${res?.system})`,
platformVersion: '',
}
//@ts-ignore
const ua = `${res?.ua}`
let platformVersion = ''
if (ua) {
if (isYzy&& ua.match(/wxworklocal/i)) {
//@ts-ignore
platformVersion = `wxyzy(${ua.match(/wxworklocal\/([\d.]+)/)[1] || ''})`
}else if(isYss && ua.match(/wxwork/i)) {
//@ts-ignore
platformVersion = `wxqy(${ua.match(/wxwork\/([\d.]+)/)[1] || ''})`
}
}
versionInfo.platformVersion = platformVersion;
this.$store.commit('SET_SYS_INFO', versionInfo)
this.$store.commit('SET_STATUSBAR_HEIGHT', statusBarHeight)
}
})
},
const defaultstate = {
sysInfo:{
proVersion: `${proTag}(${proVersion})`,
osVersion:'',
platformVersion:'',
},
statusBarHeight: 0,
location:{...DEFAULT_LOCATION},
}
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
40
41
42
43
44
45
46
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
40
41
42
43
44
45
46
# 显示调试
<view class="versionInfo">
<view class="tip">
应用版本信息
</view>
<view class="info">
<span>PRO:{{ this.$store.state.sysInfo.proVersion }} </span>
<span class="ml-1">OS:{{ this.$store.state.sysInfo.osVersion }}</span>
<span v-if="isH5" class="ml-1">PLAT:{{ this.$store.state.sysInfo.platformVersion }}</span>
</view>
</view>
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
上次更新: 2023/11/17, 05:08:20