开发中遇到的一些问题、功能点

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)
                });
            }
        })
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值