开发中遇到的一些问题、功能点
- 1. 前端
- 2. vuex与localStorage持久化
- 3. JSON.parse(), JSON.stringify()与空数据
- 4. el-select不回显,vue2
- 5. el-table换页勾选
- 6. el-upload批量上传
- 7. el-upload上传到数组里面指定index,如何处理
- 8. 平台管理按钮权限配置(指令式)
- 9. 店铺装修首页功能
- 10. 金额计算,decimal.js
- 11. 时间处理,moment
- 12. 标签页面通信
- 13. uniapp界面跳转的数据更新(用户体验需要使用局部刷新处理)
- 14. 小程序支付,分享,复制url,微信客服消息,订阅消息,定位
- 15. HBuilder X打包运行鸿蒙应用(vue2 -> vue3)
- 16. 元素拖拽,vuedraggable组件使用
- 17. 微信第三方平台/微信开放平台,小程序分发功能
- 18. element数组元素的表单校验
- 19. uniapp列表文本显示3行,超过显示更多
- 20. uniapp movable-area、movable-view组件对图片列表进行长按拖拽排序
- 21. uniapp安卓nfc读写功能
- 22. uniapp安卓微信小程序nfc读取卡号功能
- 23. element, uview上传视频进度条功能
- 24. uniapp APP打开地图使用plus方式
1. 前端
html, css, javascript, ajax, BootStrap
vue, vuex, axios, vue-router
minxin
Lodash
vue3, TypeScript, pinia
react hooks, umijs
微信小程序, uni-app
前端框架:vant, iView
后台框架:ElementUI, and design, LayUI
打包:webpack, Rollup, vite, vue-Cli
css: tailwindcss, Animate.css, PostCSS, less, sass
canvas
包管理:npm, yarn, npx
图表:echarts, AntV
长连接:WebSocket
代码管理:git
接口测试工具:postman
模拟数据:mock.js
服务端:node.js, express, koa, nginx
Jenkins
桌面应用:electron
Web3D可视化:three.js
Taro
微前端:qiankun
SEO网站性能优化:Next.js(React), Nuxt.js(Vue)
开发工具:vscode, WebStorm, HBuilder X, Sublime Text, 微信开发者工具
2. vuex与localStorage持久化
3. JSON.parse(), JSON.stringify()与空数据
JSON.parse解析空数据会报异常,所以可以使用try…catch
try {
return JSON.parse(str);
} catch (e) {
return {};
}
4. el-select不回显,vue2
vue2数据双向绑定的问题
恶心地方:有时本地运行不会出现,但buil放到测试服务器上也不会产生,发到生产就会有这个问题
this.$set(this.obj, 'key', value)
// 终极解决方案
// this.$forceUpdate()
5. el-table换页勾选
必须要设置row-key,逻辑选中时需要校验选择列表是否存在,不然会出现重复勾选
<el-table
ref="multipleTable"
row-key="productId"
:data="tableData"
border
:header-cell-style="{ background: '#EEF3FF', color: '#333333' }"
tooltip-effect="dark"
style="width: 100%"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" reserve-selection />
</el-table>
// 查看商品
seeProduct() {
this.getAll()
this.$nextTick(() => {
if (this.params.productIds && this.params.productIds.length) {
(this.params.productIds || []).forEach(productId => {
if (this.multipleSelection.findIndex(item => item.productId.toString() === productId.toString()) !== -1) return
this.$refs.multipleTable.toggleRowSelection({
productId: productId,
}, true)
})
}
})
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
6. el-upload批量上传
发现文章写过了,就贴个地址吧
el-upload批量上传
7. el-upload上传到数组里面指定index,如何处理
handleSuccess(data, file, fileList, index) {
if (!data.result || !data.data.url) return this.$message.error('上传失败,请稍后重试')
this.params.list[index].file = file
this.params.list[index].value = data.data.url
this.$forceUpdate()
},
createSuccessHandler(index) {
return (response, file, fileList) => {
this.handleSuccess(response, file, fileList, index);
};
}
8. 平台管理按钮权限配置(指令式)
/**
* @Description: permissionDirect.js
* @Description: 定义一些和按钮权限有关的 Vue指令
*/
/**
* 必须包含列出的所有权限,元素才显示
* @type {{install(*): void}}
*/
export const hasPermission = {
install(Vue) {
Vue.directive('hasPermission', {
inserted(el, binding, vnode) {
const permissions = vnode.context.$store.getters.buttonPermissions || [];
const value = binding.value;
let flag = true;
if (Array.isArray(value)) {
for (const v of value) {
if (!permissions.includes(v)) {
flag = false
}
}
} else {
if (!permissions.includes(value)) {
flag = false
}
}
if (!flag) {
if (!el.parentNode) {
el.style.display = 'none'
} else {
el.parentNode.removeChild(el)
}
}
}
})
}
};
/**
* 当不包含列出的权限时,渲染该元素
* @type {{install(*): void}}
*/
export const hasNoPermission = {
install(Vue) {
Vue.directive('hasNoPermission', {
inserted(el, binding, vnode) {
const permissions = vnode.context.$store.getters.buttonPermissions || [];
const value = binding.value;
let flag = true;
if (Array.isArray(value)) {
for (const v of value) {
if (permissions.includes(v)) {
flag = false
}
}
} else {
if (permissions.includes(value)) {
flag = false
}
}
if (!flag) {
if (!el.parentNode) {
el.style.display = 'none'
} else {
el.parentNode.removeChild(el)
}
}
}
})
}
};
/**
* 只要包含列出的任意一个权限,元素就会显示
* @type {{install(*): void}}
*/
export const hasAnyPermission = {
install(Vue) {
Vue.directive('hasAnyPermission', {
inserted(el, binding, vnode) {
const permissions = vnode.context.$store.getters.buttonPermissions || [];
const value = binding.value;
let flag = false;
if (Array.isArray(value)) {
for (const v of value) {
if (permissions.includes(v)) {
flag = true
}
}
} else {
if (permissions.includes(value)) {
flag = true
}
}
if (!flag) {
if (!el.parentNode) {
el.style.display = 'none'
} else {
el.parentNode.removeChild(el)
}
}
}
})
}
};
/**
* 必须包含列出的所有角色,元素才显示
* @type {{install(*): void}}
*/
export const hasRole = {
install(Vue) {
Vue.directive('hasRole', {
inserted(el, binding, vnode) {
const permissions = vnode.context.$store.state.account.roles || [];
const value = binding.value;
let flag = true;
if (Array.isArray(value)) {
for (const v of value) {
if (!permissions.includes(v)) {
flag = false
}
}
} else {
if (!permissions.includes(value)) {
flag = false
}
}
if (!flag) {
if (!el.parentNode) {
el.style.display = 'none'
} else {
el.parentNode.removeChild(el)
}
}
}
})
}
};
/**
* 只要包含列出的任意一个角色,元素就会显示
* @type {{install(*): void}}
*/
export const hasAnyRole = {
install(Vue) {
Vue.directive('hasAnyRole', {
inserted(el, binding, vnode) {
const permissions = vnode.context.$store.state.account.roles || [];
const value = binding.value;
let flag = false;
if (Array.isArray(value)) {
for (const v of value) {
if (permissions.includes(v)) {
flag = true
}
}
} else {
if (permissions.includes(value)) {
flag = true
}
}
if (!flag) {
if (!el.parentNode) {
el.style.display = 'none'
} else {
el.parentNode.removeChild(el)
}
}
}
})
}
};
/**
* @Description: install.js
*/
import Vue from 'vue'
import { hasPermission, hasNoPermission, hasAnyPermission, hasRole, hasAnyRole } from './permissionDirect'
const Plugins = [
hasPermission,
hasNoPermission,
hasAnyPermission,
hasRole,
hasAnyRole
]
Plugins.map((plugin) => {
Vue.use(plugin)
})
export default Vue
/**
* @Description: main.js
*/
import '@/utils/install' // button permission control
9. 店铺装修首页功能
10. 金额计算,decimal.js
常用几个自定义方法
// npm install decimal.js
import Decimal from 'decimal.js'
// 乘法
mul (...param) {
let decimal = new Decimal(1);
param.forEach((item) => {
decimal = decimal.mul((item || 0).toString());
});
return decimal.toNumber();
},
// 加法
add (...param) {
let decimal = new Decimal(0);
param.filter(item => item).forEach((item) => {
decimal = decimal.add((item || 0).toString());
});
return decimal.toNumber();
},
// 减法
sub (diff = 0, ...param) {
let decimal = new Decimal(diff || 0);
param.filter(item => item).forEach((item) => {
decimal = decimal.sub((item || 0).toString());
});
return decimal.toNumber();
},
// 除法
div (diff = 0, ...param) {
let decimal = new Decimal(diff || 0);
param.filter(item => item).forEach((item) => {
decimal = decimal.div((item || 0).toString());
});
return decimal.toNumber();
}
11. 时间处理,moment
常用两个过滤器
// npm install moment -save-dev
Vue.filter('timeFormat', (time) => {
if (!time) return null
return moment(time).format('YYYY-MM-DD HH:mm:ss')
})
Vue.filter('timeFormatYYYYMMDD', (time) => {
if (!time) return null
return moment(time).format('YYYY-MM-DD')
})
12. 标签页面通信
直接监听就完了
watch: {
'shopId': {
handler(newVal, oldVal) {
if (newVal) {
this.canvasGet()
}
}
}
},
// 监听用户更换账号登录,重新获取画布信息
window.addEventListener('storage', (e) => {
if (e.key === 'BusinessShopId') {
this.shopId = e.newValue
}
});
13. uniapp界面跳转的数据更新(用户体验需要使用局部刷新处理)
地址界面编辑信息,直接修改列表数据,不进行全局刷新
let pages = getCurrentPages();
if (pages && pages.length > 1) {
let pre = pages[pages.length - 2];
if (pre.route === "地址列表界面") {
let index = pre.$vm.list.findIndex((item) => item.id=== this.id);
if (index !== -1) {
pre.$vm.list[index]["name"] = name
...
}
}
}
14. 小程序支付,分享,复制url,微信客服消息,订阅消息,定位
以后再贴代码
15. HBuilder X打包运行鸿蒙应用(vue2 -> vue3)
文档内容太长,已新增文章HBuilder X打包运行鸿蒙应用(vue2 -> vue3)
16. 元素拖拽,vuedraggable组件使用
17. 微信第三方平台/微信开放平台,小程序分发功能
管理界面基于element UI开发的,代码文章地址,需要VIP哦点这里
1). 商户授权
2). 模板列表(删除功能),草稿箱列表(添加到模板库功能)
3). 小程序基本信息查看,小程序授权信息查看
4). 上传永久素材,获取永久素材,上传临时素材
5). 服务类目列表,添加服务类目,上传资质凭证,修改资质凭证,删除服务类目
6). 服务器域名查看,修改
7). 业务域名查看,修改
8). 提交/上传代码功能
9). 体验成员列表,绑定,解绑
10). 小程序版本信息
线上版本
版本号:
发布时间:
版本描述:
小程序码: (获取小程序码接口)
操作:回退小程序列表,回退小程序
审核版本
版本号:
审核ID:
提交时间:
版本描述:
审核状态:审核中2、通过0、不通过1、已撤回3、延后4
审核不通过的原因:
审核不通过的截图示例:
操作:撤回审核,发布小程序,再次提审(被拒绝重新驳回功能)
体验版本
版本号:
提交时间:
版本描述:
体验码: (获取小程序体验码接口)
操作:提交审核,加急审核
18. element数组元素的表单校验
<el-form ref="ruleForm" :model="params" :rules="formRules">
<template v-for="(item, index) in xxx" :key="index">
<el-form-item label="xxx" :prop="'list.' + index" :rules="formRules.list">
</el-form-item>
</template>
</el-form>
formRules: {
list: [
{ validator: (rule, value, callback) => {
if (!value.key) {
callback(new Error("xxx"));
} else {
callback();
}
}, required: true, trigger: ["blur", 'change'] },
],
},
19. uniapp列表文本显示3行,超过显示更多
watch: {
'list.*.text': {
handler() {
this.list.forEach(item => {
this.updateShouldShowMoreButton(item);
});
},
deep: true,
},
},
updateShouldShowMoreButton(item) {
this.$nextTick(() => {
let id = `text-${item.zpgPromotionCircle.id}`
// 使用 createSelectorQuery 获取元素的高度
const query = uni.createSelectorQuery().in(this);
query.select(`#${id}`).boundingClientRect().exec(res => {
if (res && res[0]) {
const {height} = res[0];
item.shouldShowMoreButton = Math.floor(height) > 53;
}
});
})
},
20. uniapp movable-area、movable-view组件对图片列表进行长按拖拽排序
uniapp movable-area、movable-view组件对图片列表进行长按拖拽排序
21. uniapp安卓nfc读写功能
const package_NdefRecord = 'android.nfc.NdefRecord';
const package_NdefMessage = 'android.nfc.NdefMessage';
const package_TECH_DISCOVERED = 'android.nfc.action.TECH_DISCOVERED';
const package_TAG_DISCOVERED = 'android.nfc.action.TAG_DISCOVERED';
const package_Intent = 'android.content.Intent';
const package_Activity = 'android.app.Activity';
const package_PendingIntent = 'android.app.PendingIntent';
const package_IntentFilter = 'android.content.IntentFilter';
const package_NfcAdapter = 'android.nfc.NfcAdapter';
const package_Ndef = 'android.nfc.tech.Ndef';
const package_NdefFormatable = 'android.nfc.tech.NdefFormatable';
const package_Parcelable = 'android.os.Parcelable';
const package_String = 'java.lang.String';
let NfcAdapter;
let nfc;
let nfcCallback;
let NdefRecord;
let NdefMessage;
let nfcType = 'cardNo'
let nfcwriteText = ''
let readyWriteData = false;
let readyRead = false;
let noNFC = false;
let techListsArray = [
['android.nfc.tech.IsoDep'],
['android.nfc.tech.NfcA'],
['android.nfc.tech.NfcB'],
['android.nfc.tech.NfcF'],
['android.nfc.tech.Nfcf'],
['android.nfc.tech.NfcV'],
['android.nfc.tech.NdefFormatable'],
['android.nfc.tech.MifareClassic'],
['android.nfc.tech.MifareUltralight']
];
export function initNFC(callback) {
if (getApp().globalData.systemInfo.platform.toLowerCase() === 'android') {
nfcCallback = callback;
init();
}
}
export function closeNFC() {
nfcCallback = null;
if (getApp().globalData.systemInfo.platform.toLowerCase() === 'android') {
close();
}
}
export function setNfcType(e) {
if (!['cardNo', 'write', 'read'].includes(e)) {
showToast('类型不正确')
return
}
nfcType = e
}
export function setNfcText(e) {
nfcwriteText = e
}
function init() {
try {
let main = plus.android.runtimeMainActivity();
let Intent = plus.android.importClass(package_Intent);
let Activity = plus.android.importClass(package_Activity);
let PendingIntent = plus.android.importClass(package_PendingIntent);
let IntentFilter = plus.android.importClass(package_IntentFilter);
NfcAdapter = plus.android.importClass(package_NfcAdapter);
nfc = NfcAdapter.getDefaultAdapter(main);
if (nfc == null) {
showToast('设备不支持NFC!')
return;
}
if (!nfc.isEnabled()) {
showToast('请在系统设置中先启用NFC功能!')
return;
}
let intent = new Intent(main, main.getClass());
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
let pendingIntent = PendingIntent.getActivity(main, 0, intent, 0);
let ndef = new IntentFilter(package_TECH_DISCOVERED);
let tag = new IntentFilter(package_TAG_DISCOVERED);
ndef.addDataType("*/*");
let intentFiltersArray = [ndef, tag];
plus.globalEvent.addEventListener("newintent", () => {
readCardNo();
}, false);
plus.globalEvent.addEventListener("pause", (e) => {
if (nfc) {
nfc.disableForegroundDispatch(main);
}
}, false);
plus.globalEvent.addEventListener("resume", (e) => {
if (nfc) {
nfc.enableForegroundDispatch(main, pendingIntent, intentFiltersArray, techListsArray);
}
}, false);
nfc.enableForegroundDispatch(main, pendingIntent, intentFiltersArray, techListsArray);
} catch (e) {
console.error(e);
}
}
/**
* 监听
*/
function readCardNo() {
NdefRecord = plus.android.importClass("android.nfc.NdefRecord");
NdefMessage = plus.android.importClass("android.nfc.NdefMessage");
let main = plus.android.runtimeMainActivity();
let intent = main.getIntent();
if ("android.nfc.action.TECH_DISCOVERED" == intent.getAction()) {
if (nfcType === 'cardNo') {
__read_no(intent)
} else if (nfcType === 'write') {
__write(intent);
} else {
__read(intent);
}
}
}
/**
* 写入内容
*/
function __write(intent) {
if (!nfcwriteText) {
showToast('写入内容不能为空')
return
}
let text = nfcwriteText
let textBytes = plus.android.invoke(text, "getBytes");
let textRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA,
plus.android.invoke("text/plain", "getBytes"), plus.android.invoke("", "getBytes"), textBytes);
let message = new NdefMessage([textRecord]);
let Ndef = plus.android.importClass('android.nfc.tech.Ndef');
let NdefFormatable = plus.android.importClass('android.nfc.tech.NdefFormatable');
let tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
let ndef = Ndef.get(tag);
if (ndef != null) {
var size = message.toByteArray().length;
console.log("size=" + size);
ndef.connect();
if (!ndef.isWritable()) {
showToast("tag不允许写入");
return;
}
if (ndef.getMaxSize() < size) {
showToast("文件大小超出容量");
return;
}
ndef.writeNdefMessage(message);
showToast("写入数据成功.");
return;
} else {
let format = NdefFormatable.get(tag);
if (format != null) {
try {
format.connect();
format.format(message);
showToast("格式化tag并且写入message");
return;
} catch (e) {
showToast("格式化tag失败.");
return;
}
} else {
showToast("Tag不支持NDEF");
return;
}
}
}
/**
* 读取内容
*/
function __read(intent) {
let Parcelable = plus.android.importClass("android.os.Parcelable");
let rawmsgs = intent.getParcelableArrayExtra("android.nfc.extra.NDEF_MESSAGES");
if (rawmsgs) {
const records = rawmsgs[0].getRecords();
var result = records[0].getPayload();
var s = plus.android.newObject("java.lang.String", result);
if (typeof s === 'string') {
showToast("数据内容:" + s);
} else {
console.log(s)
showToast('数据为空')
}
} else {
showToast('数据为空')
}
}
/**
* 读取卡号
*/
function __read_no(intent) {
try {
let content = "";
let tag = plus.android.importClass("android.nfc.Tag");
tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
let bytesId = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID);
let cardNobytes = tag.getId()
let cardNoHex16 = bytesToHexString(bytesId);
let reverseTagId = reverseTwo(bytesToHexString(tag.getId()));
let reverseTagHex10 = parseInt(reverseTagId, 16)
content += "卡片字节数组ID:" + cardNobytes + "<br/>";
content += "卡片16进制ID:" + cardNoHex16 + "<br/>";
content += "卡片16进制翻转ID:" + reverseTagId + "<br/>";
content += "卡片10进制卡号:" + reverseTagHex10 + "<br/>";
if (nfcCallback) {
nfcCallback(cardNoHex16);
}
} catch (e) {
if (nfcCallback) {
nfcCallback(null);
}
}
}
function bytesToHexString(inarray) {
let i, j, x;
let hex = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A",
"B", "C", "D", "E", "F"
];
let out = "";
for (j = 0; j < inarray.length; ++j) {
x = parseInt(inarray[j]) & 0xff;
i = (x >> 4) & 0x0f;
out += hex[i];
i = x & 0x0f;
out += hex[i];
}
return out;
}
function reverseTwo(str) {
let str1 = "";
for (var i = 1; i <= str.length; i++) {
str1 += str[i - 1];
if (i % 2 == 0) {
if (i == str.length) {
break;
}
str1 += ":";
}
}
let str2 = "";
for (let i = str1.split(":").length - 1; i >= 0; i--) {
str2 += str1.split(":")[i];
}
return str2;
}
function close() {
if (nfc) {
let main = plus.android.runtimeMainActivity();
nfc.disableForegroundDispatch(main);
}
}
function showToast(msg) {
uni.showToast({
title: msg,
icon: 'none'
})
}
index.vue使用
// #ifdef APP-PLUS
import { initNFC, closeNFC } from '@/utils/nfc.js'
// #endif
// #ifdef MP-WEIXIN
import { initWxNFC, closeWxNFC } from '@/utils/wxNfc.js'
// #endif
export default {
name: "index",
data() {
cardNo: '',
},
onLoad(option) {
if (uni.getSystemInfoSync().platform.toLowerCase() === 'android') {
// #ifdef APP-PLUS
initNFC((cardNo) => {
this.cardNo= cardNo || ''
});
// #endif
// #ifdef MP-WEIXIN
initWxNFC((cardNo) => {
this.cardNo = cardNo || ''
if (this.cardNo) {
this.search()
}
});
// #endif
}
},
onUnload() {
// #ifdef APP-PLUS
closeNFC()
// #endif
// #ifdef MP-WEIXIN
closeWxNFC()
// #endif
},
}
22. uniapp安卓微信小程序nfc读取卡号功能
let NfcAdapter;
let nfcCallback;
let nfcType = 'cardNo'
export function initWxNFC(callback) {
if (getApp().globalData.systemInfo.platform.toLowerCase() === 'android') {
nfcCallback = callback;
init();
}
}
export function closeWxNFC() {
nfcCallback = null;
if (getApp().globalData.systemInfo.platform.toLowerCase() === 'android') {
close();
}
}
export function setNfcType(e) {
if (!['cardNo', 'write', 'read'].includes(e)) {
showToast('类型不正确')
return
}
nfcType = e
}
function init() {
try {
NfcAdapter = wx.getNFCAdapter();
// 检查是否支持NFC
if (!NfcAdapter) {
showToast('当前设备不支持NFC!')
return;
}
NfcAdapter.startDiscovery({
success: function (res) {
console.log('开启NFC适配器成功。');
},
fail: function (res) {
if (res.errCode === 13000) {
//当前设备不支持NFC
showToast('设备不支持NFC!')
} else if (res.errCode === 13001) {
//系统NFC开关未打开
showToast('请在系统设置中先启用NFC功能!')
} else {
//未知错误
}
}
});
//注册发现芯片后处理事件
NfcAdapter.onDiscovered(discoverHandlerAuthAndReadM1);
} catch (e) {
console.error(e);
}
}
//认证并读取M1卡指定分区处理事件
const discoverHandlerAuthAndReadM1 = function(res) {
let techs = res.techs || []
if (techs.includes('Ndef')) {
handleNdef(res.messages);
} else if (techs.includes('ISO Dep')) {
handleIsoDep(res.id);
} else if (techs.includes('MIFARE Classic')) {
handleMifareClassic(res.id);
} else if (techs.includes('NFC-A')) {
handleNfcA(res.id)
} else {
// 芯片协议不匹配
}
}
function handleMifareClassic(id) {
if (nfcType === 'cardNo') {
readCardNumber(id)
}
}
// 读取卡号
function readCardNumber(id) {
let hex16 = ab2hex(id).toUpperCase()
// let aid = parseInt(ab2hex(id), 16);
if (nfcCallback) {
nfcCallback(hex16);
}
}
/**
* 格式化得到aid值
* @param {Object} buffer
*/
const ab2hex = function(buffer) {
let hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function(bit) {
return ('00' + bit.toString(16)).slice(-2);
}
);
return hexArr.join('');
};
function close() {
if (NfcAdapter) {
// 关闭nfc监听事件
NfcAdapter.offDiscovered(discoverHandlerAuthAndReadM1);
NfcAdapter.stopDiscovery();
}
}
function showToast(msg) {
uni.showToast({
title: msg,
icon: 'none'
})
}
23. element, uview上传视频进度条功能
24. uniapp APP打开地图使用plus方式
/**
* 地址数据
* @param {Object} data
* @param {String} data.latitude 纬度,范围为-90~90,负数表示南纬。使用 gcj02 国测局坐标系
* @param {String} data.longitude 经度,范围为-180~180,负数表示西经。使用 gcj02 国测局坐标系
* @param {Number} data.scale 缩放比例,范围5~18
* @param {String} data.name 位置名
* @param {String} data.address 地址的详细说明
*/
export const openAppMap = (data) => {
let source = 'appname'
let appid = 'com.xxx.cn'
let name = data.name
let address = data.address
let hasBaiduMap = plus.runtime.isApplicationExist({pname: 'com.baidu.BaiduMap', action: 'baidumap://'});
let hasAMap = plus.runtime.isApplicationExist({pname: 'com.autonavi.minimap', action: 'androidamap://'});
let hasQQMap = plus.runtime.isApplicationExist({pname: 'com.tencent.map', action: 'qqmap://'});
let urlBaiduMap = `baidumap://map/marker?location=${data.latitude},${data.longitude}&title=${name}&content=${address}&src=${appid}&coord_type=gcj02`;
let urlAMap = `androidamap://viewMap?sourceApplication=${source}&poiname=${name}&lat=${data.latitude}&lon=${data.longitude}&dev=0`
// &referer=OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77
let urlQQMap = `qqmap://map/marker?marker=coord:${data.latitude},${data.longitude};title:${name};addr:${address}`
// ios,特殊单独的
let hasIosAMap = plus.runtime.isApplicationExist({pname: 'com.autonavi.minimap', action: 'iosamap://'});
let appleMap = `http://maps.apple.com/?q=${name}&address=${address}&ll=${data.latitude},${data.longitude}&spn=0.008766,0.019441`
let iosAMap = `iosamap://viewMap?sourceApplication=${source}&poiname=${name}&lat=${data.latitude}&lon=${data.longitude}&dev=0`
const maps = {
'urlBaiduMap': urlBaiduMap,
'urlAMap': urlAMap,
'urlQQMap': urlQQMap,
'appleMap': appleMap,
'iosAMap': iosAMap
}
const buttons = []
if (hasBaiduMap) {
buttons.push({title: '百度地图', key: 'urlBaiduMap'})
}
if (hasQQMap) {
buttons.push({title: '腾讯地图', key: 'urlQQMap'})
}
if (getApp().globalData.isAndroid) {
if (hasAMap) {
buttons.push({title: '高德地图', key: 'urlAMap'})
}
if (buttons.length === 0) {
uni.showToast({
title: '未安装地图应用',
icon: 'none'
})
return
}
plus.nativeUI.actionSheet({
title: "选择地图应用",
cancel: "取消",
buttons: buttons
}, function (e) {
if (e.index !== -1) {
let obj = buttons[e.index - 1]
console.log(e.index, maps[obj.key])
plus.runtime.openURL(maps[obj.key], (res) => {
console.log("=============", res)
});
}
})
} else {
if (hasIosAMap) {
buttons.push({title: '高德地图', key: 'iosAMap'})
}
buttons.unshift({title: "Apple地图", key: 'appleMap'})
// iOS上获取本机是否安装了百度高德地图,需要在manifest里配置,在manifest.json文件app-plus->distribute->apple->urlschemewhitelist节点下添加(如urlschemewhitelist:["iosamap","baidumap"])
plus.nativeUI.actionSheet({
title: "选择地图应用",
cancel: "取消",
buttons: buttons
}, function (e) {
if (e.index !== -1) {
let obj = buttons[e.index - 1]
console.log(e.index, maps[obj.key])
plus.runtime.openURL(maps[obj.key], (res) => {
console.log(res)
});
}
})
}
}