HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

自动生成UniApp代码

源码

http://wtm.plus

可以在线拖拽制作页面,能在线预览,自动生成带数据库的前后台代码,并且可以下载完整的uniapp项目代码,可以直接用hbuilder打开运行。

http://wtm.plus

可以在线拖拽制作页面,能在线预览,自动生成带数据库的前后台代码,并且可以下载完整的uniapp项目代码,可以直接用hbuilder打开运行。

分享拦截路由,权限判断

let list = ["navigateTo", "redirectTo", "reLaunch", "switchTab"];  
    list.forEach(item => { //用遍历的方式分别为,uni.navigateTo,uni.redirectTo,uni.reLaunch,uni.switchTab这4个路由方法添加拦截器  
        uni.addInterceptor(item, {  
            invoke(e) { // 调用前拦截  
                const {  
                    role,  
                    permission  
                } = uniCloud.getCurrentUserInfo()  
                if (!role.includes('admin') && !permission.includes(e.hasPermission)) {  
                    return uni.showToast({  
                        title: '没有权限!请联系管理员!',  
                        icon: 'none',  
                        position:'center'  
                    })  
                }  
                return e  
            },  
            fail(err) { // 失败回调拦截   
                console.log(err);  

            }  
        })  
    })
uni.navigateTo({  
    url: 'job',  
    hasPermission: 'MenDianYuYuanGong_EDIT'  
});
继续阅读 »
let list = ["navigateTo", "redirectTo", "reLaunch", "switchTab"];  
    list.forEach(item => { //用遍历的方式分别为,uni.navigateTo,uni.redirectTo,uni.reLaunch,uni.switchTab这4个路由方法添加拦截器  
        uni.addInterceptor(item, {  
            invoke(e) { // 调用前拦截  
                const {  
                    role,  
                    permission  
                } = uniCloud.getCurrentUserInfo()  
                if (!role.includes('admin') && !permission.includes(e.hasPermission)) {  
                    return uni.showToast({  
                        title: '没有权限!请联系管理员!',  
                        icon: 'none',  
                        position:'center'  
                    })  
                }  
                return e  
            },  
            fail(err) { // 失败回调拦截   
                console.log(err);  

            }  
        })  
    })
uni.navigateTo({  
    url: 'job',  
    hasPermission: 'MenDianYuYuanGong_EDIT'  
});
收起阅读 »

招聘前端 15K - 20K(14薪)

招聘

佳和健康(厦门)
薪资:15K - 20K(14薪)

工作职责:

  1. 负责互联网产品前端代码的编写,按照设计效果图、需求实现功能和用户体验;兼具移动端开发经验的优先;
  2. 与设计师、开发工程师紧密工作在一起,负责产出高质量的产品前端层,确保产品具有优质的用户使用体验和高性能;
  3. 能向产品和设计人员表达对产品的好的建议,提前提示技术风险;
  4. 跟前端架构师团队一起搭建公司产品前端架构,规范前端代码,跟踪前端技术发展方向,研究和掌握最新前端开发技术;
  5. 持续的优化前端体验和页面响应速度,优化代码并保持良好兼容性,提升web界面的友好性和易用性;
  6. 主导开发核心组件,封装适应于PC和Mobile的js交互控件。

任职资格:
1、 本科及以上学历计算机相关专业,6年以上互联网前端开发经验;
2、 精通HTML、CSS、JavaScript、Ajax、响应式设计等核心前端开发技术,有精益求精的编码习惯和对问题的钻研精神;
3、 熟悉React或Vue等现代框架,熟悉SASS, LESS, Require JS, grunt, gulp 等工具;
4、 熟练掌握nodejs,熟悉ES6语法规则,熟悉webpack和git/github;
5、 熟练使用各种脚本调试器、DOM查看器等定位问题,熟练使用各种工具检测web服务的性能和定位瓶颈;
5、 熟悉移动端开发(如:微信小程序、Android或iOS)有加分;
6、 有责任心,良好的跨团队(与产品、后端、设计团队)沟通表达能力和团队协作能力;
7、 有激情,希望加入创业团队,发挥主动精神,创新精神,实现个人技艺和职业快速成长;
8、有互联网医疗开发经验者优先。

简历投递邮箱:lixueting@jiahehealth.com

轻松的工作氛围,优厚的福利待遇,全额社保公积金,员工住宿

我们是谁
由央企背景光大集团孵化、依托于上市公司嘉事堂的互联网医疗公司,提供专业的患者管理服务致力于打造[硬件 服务 AI 平台]四位一体的诊后管理云平台,一支充满无限可能的年轻队伍,有来自于平安、微医、万达、知名三甲医院的优秀小伙伴,我们心怀超凡渴望,追求成功,期望与你一起发光发热,我们是佳和健康!

继续阅读 »

佳和健康(厦门)
薪资:15K - 20K(14薪)

工作职责:

  1. 负责互联网产品前端代码的编写,按照设计效果图、需求实现功能和用户体验;兼具移动端开发经验的优先;
  2. 与设计师、开发工程师紧密工作在一起,负责产出高质量的产品前端层,确保产品具有优质的用户使用体验和高性能;
  3. 能向产品和设计人员表达对产品的好的建议,提前提示技术风险;
  4. 跟前端架构师团队一起搭建公司产品前端架构,规范前端代码,跟踪前端技术发展方向,研究和掌握最新前端开发技术;
  5. 持续的优化前端体验和页面响应速度,优化代码并保持良好兼容性,提升web界面的友好性和易用性;
  6. 主导开发核心组件,封装适应于PC和Mobile的js交互控件。

任职资格:
1、 本科及以上学历计算机相关专业,6年以上互联网前端开发经验;
2、 精通HTML、CSS、JavaScript、Ajax、响应式设计等核心前端开发技术,有精益求精的编码习惯和对问题的钻研精神;
3、 熟悉React或Vue等现代框架,熟悉SASS, LESS, Require JS, grunt, gulp 等工具;
4、 熟练掌握nodejs,熟悉ES6语法规则,熟悉webpack和git/github;
5、 熟练使用各种脚本调试器、DOM查看器等定位问题,熟练使用各种工具检测web服务的性能和定位瓶颈;
5、 熟悉移动端开发(如:微信小程序、Android或iOS)有加分;
6、 有责任心,良好的跨团队(与产品、后端、设计团队)沟通表达能力和团队协作能力;
7、 有激情,希望加入创业团队,发挥主动精神,创新精神,实现个人技艺和职业快速成长;
8、有互联网医疗开发经验者优先。

简历投递邮箱:lixueting@jiahehealth.com

轻松的工作氛围,优厚的福利待遇,全额社保公积金,员工住宿

我们是谁
由央企背景光大集团孵化、依托于上市公司嘉事堂的互联网医疗公司,提供专业的患者管理服务致力于打造[硬件 服务 AI 平台]四位一体的诊后管理云平台,一支充满无限可能的年轻队伍,有来自于平安、微医、万达、知名三甲医院的优秀小伙伴,我们心怀超凡渴望,追求成功,期望与你一起发光发热,我们是佳和健康!

收起阅读 »

这次更新的HBuilder3.4.6还是不错的。有更好的ts的支持,能提示常用函数。

HBuilderX

语言服务由Java调整为Node。想问问可以用ts写uniCloud云函数吗

语言服务由Java调整为Node。想问问可以用ts写uniCloud云函数吗

有没有拼团学习的

学习

https://ke.qq.com/course/3455428?group_id=1742204#term_id=103593307

https://ke.qq.com/course/3455428?group_id=1742204#term_id=103593307

APP使用MathJax解析数学公式

MathJAX

近期有个需求,将之前后台录入的MathJax公式解析展示到APP中,研究了一下论坛里的代码,最终实现了需求,将代码和遇到的问题整理一下发出来,分享一下经验。

实现的效果图在下面附件中,目前只测试过安卓APP,H5和苹果APP未测试

核心代码如下:
因为目前只有一个页面使用数学公式,所以未封装,多个页面需要的话可以自行封装一个JS。
将代码完整的复制到vue页面里即可使用

<script module="MathJax" lang="renderjs">  
    export default {  
        mounted() {  
            let that = this;  
            if (typeof window.MathJax === 'object') {  
                that.initMathJax()  
            } else {  
                const script = document.createElement('script')  
                                //MathJax地址,为保持稳定可以下载到自己的服务器上引用,注意config参数不可忽略  
                script.src = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js?config=TeX-MML-AM_CHTML'  
                script.onload = that.initMathJax.bind(that);  
                document.head.appendChild(script)  
            }  
        },  
        methods: {  
            initMathJax() {  
                MathJax.Hub.Config({  
                    showProcessingMessages: false, //关闭js加载过程信息  
                    messageStyle: "none", //不显示信息  
                    jax: ["input/TeX", "output/HTML-CSS"],  
                    tex2jax: {  
                        inlineMath: [  
                            ["$", "$"],  
                            ["\\(", "\\)"]  
                        ], //行内公式选择符  
                        displayMath: [   
                            ["$$", "$$"],  
                            ["\\[", "\\]"]  
                        ], //段内公式选择符  
                        skipTags: ["script", "noscript", "style", "textarea", "pre", "code", "a"] //避开某些标签  
                    },  
                    "HTML-CSS": {  
                        availableFonts: ["STIX", "TeX"], //可选字体  
                        showMathMenu: false //关闭右击菜单显示  
                    }  
                });  
                this.MathQueue();  
            },  
            MathQueue: function() {  
                if (!window.MathJax) {  
                    return;  
                }  
                                //container 是当前页面DOM的ID,可以自定义  
                window.MathJax.Hub.Queue(["Typeset", window.MathJax.Hub, document.getElementById('container')]);  
            }  
        }  
    }  
</script>  

HTML代码:

<view class="problem-content-title" v-html="execQuestionContent(item.questionDto.question.question)"> </view>

此时可以不用v-html,我用v-html是因为公式中还含有html元素,execQuestionContent方法的作用是处理斜杠,如果公式正确可以不用,方法代码在下方图中,有需要的可以参考

遇到的问题:
1、执行后公式没有变化
排查原因:
1、排查公式是否符合inlineMath、displayMath选择符匹配标准,例如\\( 对应公式里的 \(, \\\\(对应\\(,此处是决定能否匹配数学公式的关键,需要注意。
注:我的数据库之前存储的是\\\\(,这时候需要手动处理成 \( ,然后再用 \\( 来匹配
例子如下:
数学公式:函数\\(a{{x}^{2}}+5x+b>0\\)的解集为\\(\\left\\{ x\\left| \\frac{1}{3}
我通过String.raw({ raw: content })处理后变成\\(,最后通过replace(/\\/g,'\')变成\(

2、src地址里面要带config=TeX-MML-AM_CHTML参数,不可以不带

如果还能不能转换,请留言问题和代码,我看到会第一时间回复。

继续阅读 »

近期有个需求,将之前后台录入的MathJax公式解析展示到APP中,研究了一下论坛里的代码,最终实现了需求,将代码和遇到的问题整理一下发出来,分享一下经验。

实现的效果图在下面附件中,目前只测试过安卓APP,H5和苹果APP未测试

核心代码如下:
因为目前只有一个页面使用数学公式,所以未封装,多个页面需要的话可以自行封装一个JS。
将代码完整的复制到vue页面里即可使用

<script module="MathJax" lang="renderjs">  
    export default {  
        mounted() {  
            let that = this;  
            if (typeof window.MathJax === 'object') {  
                that.initMathJax()  
            } else {  
                const script = document.createElement('script')  
                                //MathJax地址,为保持稳定可以下载到自己的服务器上引用,注意config参数不可忽略  
                script.src = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js?config=TeX-MML-AM_CHTML'  
                script.onload = that.initMathJax.bind(that);  
                document.head.appendChild(script)  
            }  
        },  
        methods: {  
            initMathJax() {  
                MathJax.Hub.Config({  
                    showProcessingMessages: false, //关闭js加载过程信息  
                    messageStyle: "none", //不显示信息  
                    jax: ["input/TeX", "output/HTML-CSS"],  
                    tex2jax: {  
                        inlineMath: [  
                            ["$", "$"],  
                            ["\\(", "\\)"]  
                        ], //行内公式选择符  
                        displayMath: [   
                            ["$$", "$$"],  
                            ["\\[", "\\]"]  
                        ], //段内公式选择符  
                        skipTags: ["script", "noscript", "style", "textarea", "pre", "code", "a"] //避开某些标签  
                    },  
                    "HTML-CSS": {  
                        availableFonts: ["STIX", "TeX"], //可选字体  
                        showMathMenu: false //关闭右击菜单显示  
                    }  
                });  
                this.MathQueue();  
            },  
            MathQueue: function() {  
                if (!window.MathJax) {  
                    return;  
                }  
                                //container 是当前页面DOM的ID,可以自定义  
                window.MathJax.Hub.Queue(["Typeset", window.MathJax.Hub, document.getElementById('container')]);  
            }  
        }  
    }  
</script>  

HTML代码:

<view class="problem-content-title" v-html="execQuestionContent(item.questionDto.question.question)"> </view>

此时可以不用v-html,我用v-html是因为公式中还含有html元素,execQuestionContent方法的作用是处理斜杠,如果公式正确可以不用,方法代码在下方图中,有需要的可以参考

遇到的问题:
1、执行后公式没有变化
排查原因:
1、排查公式是否符合inlineMath、displayMath选择符匹配标准,例如\\( 对应公式里的 \(, \\\\(对应\\(,此处是决定能否匹配数学公式的关键,需要注意。
注:我的数据库之前存储的是\\\\(,这时候需要手动处理成 \( ,然后再用 \\( 来匹配
例子如下:
数学公式:函数\\(a{{x}^{2}}+5x+b>0\\)的解集为\\(\\left\\{ x\\left| \\frac{1}{3}
我通过String.raw({ raw: content })处理后变成\\(,最后通过replace(/\\/g,'\')变成\(

2、src地址里面要带config=TeX-MML-AM_CHTML参数,不可以不带

如果还能不能转换,请留言问题和代码,我看到会第一时间回复。

收起阅读 »

坑日落

时间也没过去多久,我清楚记得URLSearchParams在APP中可以用的,否则我也不会写进去,由于用例很少,所以都不知道从什么时候开始就不能用了,也没经历过HBuilderX的版本更新,没脾气了

这框架也就够开发些快餐项目了,不说了,办离职手续去了,愿来生大富大贵不用上班

继续阅读 »

时间也没过去多久,我清楚记得URLSearchParams在APP中可以用的,否则我也不会写进去,由于用例很少,所以都不知道从什么时候开始就不能用了,也没经历过HBuilderX的版本更新,没脾气了

这框架也就够开发些快餐项目了,不说了,办离职手续去了,愿来生大富大贵不用上班

收起阅读 »

uniapp 离线打包的 android 端 权限 动态申请无效

权限 App离线打包 Android
  1. uniapp的 代码 运行在 真机上 ,模拟器都没有·问题
  2. 但是 离线打包后 进入软件 就没有权限 拍照 定位 录像 的权限都 动态申请了 也没有
  3. 关键的
    这时候注意了 得在 android studio的 项目里面的 AndroidManifest.xml 文件里面 吧
    对应的权限都加上 这样打包后才可以

代码 如下 我 添加了常用的权限 拍照 录像 定位
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.uniapp">
<!-- tools:replace="android:name"-->
<application。。。> //我把application收缩了
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" /> <!-- 获取sd卡写的权限,用于文件上传和下载 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <!-- 录像的权限 -->
<uses-permission android:name="android.permission.RECORD_VIDEO" /> <!-- 声音权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

<uses-feature android:name="android.hardware.Camera" /> <!-- 添加读写SD卡的权限 -->  
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEM" />  
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- 硬件支持 -->  
<uses-feature android:name="android.hardware.camera" />  
<uses-feature android:name="android.hardware.camera.autofocus" />  

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />  

</manifest>

继续阅读 »
  1. uniapp的 代码 运行在 真机上 ,模拟器都没有·问题
  2. 但是 离线打包后 进入软件 就没有权限 拍照 定位 录像 的权限都 动态申请了 也没有
  3. 关键的
    这时候注意了 得在 android studio的 项目里面的 AndroidManifest.xml 文件里面 吧
    对应的权限都加上 这样打包后才可以

代码 如下 我 添加了常用的权限 拍照 录像 定位
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.uniapp">
<!-- tools:replace="android:name"-->
<application。。。> //我把application收缩了
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" /> <!-- 获取sd卡写的权限,用于文件上传和下载 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <!-- 录像的权限 -->
<uses-permission android:name="android.permission.RECORD_VIDEO" /> <!-- 声音权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

<uses-feature android:name="android.hardware.Camera" /> <!-- 添加读写SD卡的权限 -->  
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEM" />  
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- 硬件支持 -->  
<uses-feature android:name="android.hardware.camera" />  
<uses-feature android:name="android.hardware.camera.autofocus" />  

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />  

</manifest>

收起阅读 »

基于 china-area-data 的 uniapp H5 地址选择器,使用 uniapp 官方组件 uni-data-picker

查看 原文

china-area-data 数据来源(最新同步可在仓库中查看)
uni-data-picker 使用说明

  1. china-area-data 获取最新的地址数据,保存到项目目录 /static/h5/data.json 中。

  2. 在项目中创建 /static/h5/area.js 文件,提供获取地址信息的操作便捷性。内容如下:

const defaultCode = 86  

const PCAA = require('./data.json')  

export const uniappInitRegionData = (code) => {  
    if (typeof PCAA[code] === 'undefined') {  
        return []  
    }  

    const data = [];  
    for (let [k, v] of Object.entries(PCAA[code])) {  
        const item = {  
            text: v,  
            value: v,  
            children: uniappInitRegionData(k),  
        }  

        data.push(item)  
    }  
    return data  
}  

const createRegionFromString = (address, separator = ',') => {  
    return address.split(separator).map(item => {  
        return {  
            text: item,  
            value: item,  
        }  
    })  
}  

const createRegionTextDataFromString = (address, separator = ',') => {  
    if (typeof address !== 'string') {  
        console.info('area.toRegion', address)  
        throw new TypeError('except string address, get type ' + (typeof address))  
    }  

    return address.split(separator)  
}  

const getRegionTextDataFromUser = (event, field = 'text') => {  
    return event.detail.value.map(item => item[field])  
}  

const getRegionTextStringFromUser = (event, field = 'text', separator = ',') => {  
    return event.detail.value.map(item => item[field]).join(separator)  
}  

const onRegionChange = (event, field = 'text', separator = ',') => {  
    console.log('area.onRegionChange', event)  

    const data = getRegionTextDataFromUser(event, field)  
    const text = getRegionTextStringFromUser(event, field)  

    uni.$emit('region.update', {  
        data,  
        text,  
    })  

    return data  
}  

const onNodeClick = (event) => {  
    console.log('area.onNodeClick', event)  
}  

const replaceSeparator = (address, old, current) => {  
    return address.replace(new RegExp(`${old}`, "g"), '/')  
}  

export default {  
    defaultCode,  
    regionData: uniappInitRegionData(defaultCode),  
    uniappInitRegionData,  
    createRegionFromString,  
    createRegionTextDataFromString,  
    getRegionTextDataFromUser,  
    getRegionTextStringFromUser,  
    replaceSeparator,  
    onRegionChange,  
    onNodeClick,  
}  
  1. 在需要使用地址的地方按照如下示例进行使用。
<template>  
    <!-- #ifdef H5 -->  
    <!-- TODO: 需要获取省市区的数据 -->  
    <uni-data-picker style="flex: 1; margin-left: 30px;"  v-model="region" placeholder="请选择地址" popup-title="请选择城市" :localdata="regionData"  
        @change="regionChange" @nodeclick="nodeclick">  
    </uni-data-picker>  
    <!-- #endif -->  
</template>  

<script>  
// #ifdef H5  
import area from '@/static/h5/area.js'  
// #endif  

export default {  
    data() {  
        return {  
            // #ifdef H5  
            regionData: area.regionData, // 初始化的所有省市区数据  
            onRegionChange: area.onRegionChange, // 需要先注册,才可以直接在页面调用  
            onNodeClick: area.onNodeClick, // 节点点击事件  
            region: [], // v-model 绑定的数据。格式为 [{text: 'xxx', value: 'xxx'}, {text: 'xxx', value: 'xxx'}]  
            regionTextData: [], // 地址信息数组 ['北京市', '市辖区', '东城区']  
            regionText: '', // 地址文字信息,默认分隔符为 ","。示例:'北京市,市辖区,东城区'  
            // #endif  
        }  
    },  
    onLoad() {  
        // #ifdef H5  
        // 用户选择了地址 data: { data: ['北京市', '市辖区', '东城区'], text: '北京市,市辖区,东城区' }  
        uni.$on('region.update', (data) => {  
            this.regionTextData = data.data  
            this.regionText = data.text  
        })  
        // 获取到了用户过去选择的地址信息 data: { address: '北京市,市辖区,东城区', separator: ',' }  
        // 触发更新:uni.$emit('address.update', { address: res.data.address, separator: ',' })  
        uni.$on('address.update', (data) => {  
            const address = data.address || ''  
            const separator = data.separator || ','  

            this.regionText = address  
            this.regionTextData = area.createRegionTextDataFromString(address)  
            this.region = area.createRegionFromString(address, separator)  
        })  
        // #endif  
    },  
}  
</script>
继续阅读 »

查看 原文

china-area-data 数据来源(最新同步可在仓库中查看)
uni-data-picker 使用说明

  1. china-area-data 获取最新的地址数据,保存到项目目录 /static/h5/data.json 中。

  2. 在项目中创建 /static/h5/area.js 文件,提供获取地址信息的操作便捷性。内容如下:

const defaultCode = 86  

const PCAA = require('./data.json')  

export const uniappInitRegionData = (code) => {  
    if (typeof PCAA[code] === 'undefined') {  
        return []  
    }  

    const data = [];  
    for (let [k, v] of Object.entries(PCAA[code])) {  
        const item = {  
            text: v,  
            value: v,  
            children: uniappInitRegionData(k),  
        }  

        data.push(item)  
    }  
    return data  
}  

const createRegionFromString = (address, separator = ',') => {  
    return address.split(separator).map(item => {  
        return {  
            text: item,  
            value: item,  
        }  
    })  
}  

const createRegionTextDataFromString = (address, separator = ',') => {  
    if (typeof address !== 'string') {  
        console.info('area.toRegion', address)  
        throw new TypeError('except string address, get type ' + (typeof address))  
    }  

    return address.split(separator)  
}  

const getRegionTextDataFromUser = (event, field = 'text') => {  
    return event.detail.value.map(item => item[field])  
}  

const getRegionTextStringFromUser = (event, field = 'text', separator = ',') => {  
    return event.detail.value.map(item => item[field]).join(separator)  
}  

const onRegionChange = (event, field = 'text', separator = ',') => {  
    console.log('area.onRegionChange', event)  

    const data = getRegionTextDataFromUser(event, field)  
    const text = getRegionTextStringFromUser(event, field)  

    uni.$emit('region.update', {  
        data,  
        text,  
    })  

    return data  
}  

const onNodeClick = (event) => {  
    console.log('area.onNodeClick', event)  
}  

const replaceSeparator = (address, old, current) => {  
    return address.replace(new RegExp(`${old}`, "g"), '/')  
}  

export default {  
    defaultCode,  
    regionData: uniappInitRegionData(defaultCode),  
    uniappInitRegionData,  
    createRegionFromString,  
    createRegionTextDataFromString,  
    getRegionTextDataFromUser,  
    getRegionTextStringFromUser,  
    replaceSeparator,  
    onRegionChange,  
    onNodeClick,  
}  
  1. 在需要使用地址的地方按照如下示例进行使用。
<template>  
    <!-- #ifdef H5 -->  
    <!-- TODO: 需要获取省市区的数据 -->  
    <uni-data-picker style="flex: 1; margin-left: 30px;"  v-model="region" placeholder="请选择地址" popup-title="请选择城市" :localdata="regionData"  
        @change="regionChange" @nodeclick="nodeclick">  
    </uni-data-picker>  
    <!-- #endif -->  
</template>  

<script>  
// #ifdef H5  
import area from '@/static/h5/area.js'  
// #endif  

export default {  
    data() {  
        return {  
            // #ifdef H5  
            regionData: area.regionData, // 初始化的所有省市区数据  
            onRegionChange: area.onRegionChange, // 需要先注册,才可以直接在页面调用  
            onNodeClick: area.onNodeClick, // 节点点击事件  
            region: [], // v-model 绑定的数据。格式为 [{text: 'xxx', value: 'xxx'}, {text: 'xxx', value: 'xxx'}]  
            regionTextData: [], // 地址信息数组 ['北京市', '市辖区', '东城区']  
            regionText: '', // 地址文字信息,默认分隔符为 ","。示例:'北京市,市辖区,东城区'  
            // #endif  
        }  
    },  
    onLoad() {  
        // #ifdef H5  
        // 用户选择了地址 data: { data: ['北京市', '市辖区', '东城区'], text: '北京市,市辖区,东城区' }  
        uni.$on('region.update', (data) => {  
            this.regionTextData = data.data  
            this.regionText = data.text  
        })  
        // 获取到了用户过去选择的地址信息 data: { address: '北京市,市辖区,东城区', separator: ',' }  
        // 触发更新:uni.$emit('address.update', { address: res.data.address, separator: ',' })  
        uni.$on('address.update', (data) => {  
            const address = data.address || ''  
            const separator = data.separator || ','  

            this.regionText = address  
            this.regionTextData = area.createRegionTextDataFromString(address)  
            this.region = area.createRegionFromString(address, separator)  
        })  
        // #endif  
    },  
}  
</script>
收起阅读 »

uniapp开发微信小程序,动态排列组件的解决方案!

uniapp

微信小程序开发里面,虽然不支持<component is=""/> is not supported,但是微信小程序提供了WXML提供模板(template),<template is="msgItem" data="{{...item}}"/>
,对于uniapp并不管用,编译后,所以解决方案,只有目前(截止2022-04-15)只有两个:

1.使用 v-if,遍历组件,判断位置,来显示组件,达到排列要求

2.第二种没那么麻烦,比较神奇,使用flex布局的order属性,外层设置
display: flex;
flex-direction: column;

里面组件的div,就设置order,越小越在前。所以我只要操控,每个组件的order值就好了

继续阅读 »

微信小程序开发里面,虽然不支持<component is=""/> is not supported,但是微信小程序提供了WXML提供模板(template),<template is="msgItem" data="{{...item}}"/>
,对于uniapp并不管用,编译后,所以解决方案,只有目前(截止2022-04-15)只有两个:

1.使用 v-if,遍历组件,判断位置,来显示组件,达到排列要求

2.第二种没那么麻烦,比较神奇,使用flex布局的order属性,外层设置
display: flex;
flex-direction: column;

里面组件的div,就设置order,越小越在前。所以我只要操控,每个组件的order值就好了

收起阅读 »

uni-app webview 天地图的使用

h5 Webview 地图
作为一个uni-app初始小白,给大家分享一个天地图的使用  

1. 在天地图官网申请key  [天地图官网](https://www.tianditu.gov.cn/)  
    申请浏览器端key,白名单暂时不填  
2. uni-app使用web-view方式引入H5  
3. (目前测试直接在hybrid文件下本地引入,天地图api报403错误,如果有大神了解这个原因欢迎指导!)  
4.   注意点: nvue需要定义宽高,地图才能显示  
5. uni-app代码如下:  

<template>  
    <view :style="{width:width, height:height}">  
        <web-view :style="{width:width, height:height}" :src="webUrl" @onPostMessage="handleMessage"></web-view>  
    </view>  
</template>  

<script>  
    export default {  
        data() {  
            return {  
                webUrl: '',  
                width: 0,  
                height: 0,  
                markers: [],  
            }  
        },  
        onLoad(options) {  
            uni.showLoading({  
                title: '加载中',  
                mask: true  
            })  
            uni.getSystemInfo({ // 获取当前设备的具体信息  
                success: (sysinfo) => {  
                    this.width = sysinfo.windowWidth + 'px'  
                    this.height = sysinfo.windowHeight - sysinfo.statusBarHeight + 'px'  
                    this.markers = [{  
                            id: '1',  
                            name: '站点一',  
                            info: '这是第一个标记点',  
                            position: [112.280637, 24.125178],  
                            status: '正常'  
                        },  
                        {  
                            id: '2',  
                            name: '站点二',  
                            info: '这是第二个标记点',  
                            position: [112.280637, 24.125178],  
                            status: '正常'  
                        },  
                        {  
                            id: '3',  
                            name: '站点三',  
                            info: '这是第三个标记点',  
                            position: [112.280637, 24.125178],  
                            status: '异常'  
                        },  
                    ];  
                    var markersInfo = encodeURIComponent(JSON.stringify(this.markers))  
                    // http://127.0.0.1:8848/app/hybrid/map/map.html 可换成自己部署的h5网址  
                    this.webUrl =  
                        `http://127.0.0.1:8848/app/hybrid/map/map.html?markers=${markersInfo}#1`  
                    setTimeout(function() {  
                        uni.hideLoading();  
                    }, 2000);  
                }  
            });  
        },  
        methods: {  
            handleMessage(evt) {  
                console.log('接收到的消息:', evt.detail.data[0].action);  
                console.log('接收到的消息:', evt.detail);  
            }  
        }  
    }  
</script>  

h5代码如下:  
<!DOCTYPE html>  
<html>  

    <head>  
        <meta charset="UTF-8" />  
        <title>HELLO WORLD</title>  
        <!-- favicon.ico 404 -->  
        <link rel="shortcut icon" href="#" />  
    </head>  

    <body onLoad="onLoad()">  
        <div id="mapDiv"></div>  
    </body>  
    <!-- uni 的 SDK 注意uni sdk放到body下面 -->  
    <script type="text/javascript" src="https://unpkg.com/@dcloudio/uni-webview-js@0.0.1/index.js"></script>  
    <!-- 天地图 api -->  
    <script type="text/javascript" src="http://api.tianditu.gov.cn/api?v=4.0&tk=7db9f33de2e1c4c484682aed6a0764ac">  
    </script>  
    <script type="text/javascript">  
                // 此处是处理url传过来的参数 来自一篇博客 https://blog.csdn.net/qq_42961150/article/details/119890887  
        var getUrlData = {  
            callback: null,  
            _t: 0,  
            init(fn) {  
                this.callback = fn;  
                this.bind();  
                this.change.call(this);  
            },  
            bind() {  
                let that = this;  
                if (("onhashchange" in window) && ((typeof document.documentMode === "undefined") || document  
                        .documentMode == 8)) {  
                    window.onhashchange = () => {  
                        that.change.call(that);  
                    };  
                } else {  
                    clearInterval(this._t);  
                    this._t = setInterval(() => {  
                        that.change.call(that);  
                    }, 150);  
                }  
            },  
            change() {  
                let that = this,  
                    _hash = window.location.hash,  
                    _data = null;  
                try {  
                    _data = JSON.parse(decodeURIComponent(_hash.split('#')[1]));  
                } catch (e) {  
                    _data = decodeURIComponent(_hash.split('#')[1]);  
                }  
                if (that.callback) that.callback({  
                    type: that.getQuery('markers'),  
                    data: _data  
                });  
            },  
            getQuery(name) {  
                let reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");  
                let r = decodeURIComponent(window.location.search).substr(1).match(reg);  
                if (r != null) {  
                    // 对参数值进行解码  
                    return decodeURIComponent(r[2]);  
                }  
                return null;  
            }  
        }  
    </script>  
    <script type="text/javascript">  
        var map;  
        var zoom = 13;  

        // 标注点信息  
        var markers = [{  
                id: '1',  
                name: '站点一',  
                info: '这是第一个标记点',  
                position: [112.280637, 24.125178],  
                status: '正常'  
            },  
            {  
                id: '2',  
                name: '站点二',  
                info: '这是第二个标记点',  
                position: [112.280637, 24.125178],  
                status: '正常'  
            },  
            {  
                id: '3',  
                name: '站点三',  
                info: '这是第三个标记点',  
                position: [112.280637, 24.125178],  
                status: '异常'  
            },  
        ];  

        // 定义uni  
        var _uni;  

        // 待触发 `UniAppJSBridgeReady` 事件后,即可调用 uni 的 API。  
        document.addEventListener('UniAppJSBridgeReady', function() {  
            console.log("111")  
            _uni = uni  
            uni.getEnv(function(res) {  
                console.log('当前环境:' + JSON.stringify(res));  
            });  
        });  

        // 从uni-app拿信息  
        getUrlData.init(function(res) {  
            console.log(res); //返回的格式例如 {type: {}, data: 1}  
            // markers = JSON.parse(res.type)  
        })  

        function onLoad() {  
            map = new T.Map('mapDiv');  
            map.centerAndZoom(new T.LngLat(113.280637, 23.125178), zoom);  
            //创建缩放平移控件对象  
            control = new T.Control.Zoom();  
            //添加缩放平移控件  
            map.addControl(control);  
            // 添加标注点  
            addOverLay(markers);  
        }  

        // 添加标注点  
        function addOverLay(markers) {  
            for (let content of markers) {  
                //创建一个默认的标注点  
                //创建图片对象 img/uni@2x.png 修改成同一文件下图片  
                var icon = new T.Icon({  
                    iconUrl: "img/uni@2x.png",  
                    iconSize: new T.Point(19, 27),  
                    iconAnchor: new T.Point(10, 25)  
                });  
                //向地图上添加自定义标注 创建标注对象,实例化Marker类  
                var marker  
                if (content.status === '正常') {  
                    marker = new T.Marker(new T.LngLat(content.position[0], content.position[1]));  
                } else {  
                    marker = new T.Marker(new T.LngLat(content.position[0], content.position[1]), {  
                        icon: icon  
                    });  
                }  
                //向地图上添加标注。其中addOverLay(overlay:OverLay)方法将覆盖物添加到地图中,一个覆盖物实例只能向地图中添加一次。  
                map.addOverLay(marker);  
                //添加坐标点的监听事件,当鼠标触碰该点时打开信息窗口  
                addMouseoverHandler(content, marker);  
                //   
                label = new T.Label({  
                    text: `<b>${content.name}<b>`,  
                    position: marker.getLngLat(),  
                    offset: new T.Point(-35, 20)  
                });  
                map.addOverLay(label);  
            }  
        }  

        //鼠标在覆盖物上的监听事件  
        function addMouseoverHandler(content, marker) {  
            marker.addEventListener("click", function(e) {  
                openInfo(content, e)  
            });  
        }  

        //窗口信息  
        function openInfo(content, e) {  
            var point = e.lnglat;  
            // 创建信息窗口对象  
            var markerInfoWin = new T.InfoWindow()  
            var sContent =  
                `  
        <div id="win_box" style="height: auto; ">  
            <table style=" width:300px;border-collapse: separate;font-size:14px;border-spacing:0 6px;table-layout:fixed;">  
                <caption style="font-weight:bold;font-size:15px;">${content.info}区域</caption>  
                <tr><td style=" font-weight:bold;text-align:left;"><input type="button"value="详情"  style="cursor: pointer;outline: none;border:none;float: right;height: 25px;width: 50px;background-color:#dddddd;color: #57606f" onclick="getDetail(` +  
                JSON.stringify(content).replace(/"/g, '&quot;') + `)"></td></tr>  
            </table>  
        </div>  
        `;  
            //设置信息窗口要显示的内容  
            markerInfoWin.setContent(sContent);  
            //setOffset设置信息浮窗显示时向右下角偏移量(像素)。-30则代表向上偏移  
            markerInfoWin.setOffset(new T.Point(0, -30))  
            //开启信息窗口  
            map.openInfoWindow(markerInfoWin, point);  
        }  

        // 跳转详情 -- 通信uni-app  
        function getDetail(content) {  
            console.log(content)  
            _uni.postMessage({  
                data: {  
                    action: content,  
                    type: 'getDetail',  
                }  
            });  
        }  
    </script>  
    <style type="text/css">  
        /* 隐藏天地图图标等相关信息 */  
        #mapDiv .tdt-control-copyright.tdt-control>div:not(.tdt-control-copyright) {  
            display: none;  
        }  

        #mapDiv {  
            position: absolute;  
            width: 100%;  
            height: 100%  
        }  
    </style>  

</html>
继续阅读 »
作为一个uni-app初始小白,给大家分享一个天地图的使用  

1. 在天地图官网申请key  [天地图官网](https://www.tianditu.gov.cn/)  
    申请浏览器端key,白名单暂时不填  
2. uni-app使用web-view方式引入H5  
3. (目前测试直接在hybrid文件下本地引入,天地图api报403错误,如果有大神了解这个原因欢迎指导!)  
4.   注意点: nvue需要定义宽高,地图才能显示  
5. uni-app代码如下:  

<template>  
    <view :style="{width:width, height:height}">  
        <web-view :style="{width:width, height:height}" :src="webUrl" @onPostMessage="handleMessage"></web-view>  
    </view>  
</template>  

<script>  
    export default {  
        data() {  
            return {  
                webUrl: '',  
                width: 0,  
                height: 0,  
                markers: [],  
            }  
        },  
        onLoad(options) {  
            uni.showLoading({  
                title: '加载中',  
                mask: true  
            })  
            uni.getSystemInfo({ // 获取当前设备的具体信息  
                success: (sysinfo) => {  
                    this.width = sysinfo.windowWidth + 'px'  
                    this.height = sysinfo.windowHeight - sysinfo.statusBarHeight + 'px'  
                    this.markers = [{  
                            id: '1',  
                            name: '站点一',  
                            info: '这是第一个标记点',  
                            position: [112.280637, 24.125178],  
                            status: '正常'  
                        },  
                        {  
                            id: '2',  
                            name: '站点二',  
                            info: '这是第二个标记点',  
                            position: [112.280637, 24.125178],  
                            status: '正常'  
                        },  
                        {  
                            id: '3',  
                            name: '站点三',  
                            info: '这是第三个标记点',  
                            position: [112.280637, 24.125178],  
                            status: '异常'  
                        },  
                    ];  
                    var markersInfo = encodeURIComponent(JSON.stringify(this.markers))  
                    // http://127.0.0.1:8848/app/hybrid/map/map.html 可换成自己部署的h5网址  
                    this.webUrl =  
                        `http://127.0.0.1:8848/app/hybrid/map/map.html?markers=${markersInfo}#1`  
                    setTimeout(function() {  
                        uni.hideLoading();  
                    }, 2000);  
                }  
            });  
        },  
        methods: {  
            handleMessage(evt) {  
                console.log('接收到的消息:', evt.detail.data[0].action);  
                console.log('接收到的消息:', evt.detail);  
            }  
        }  
    }  
</script>  

h5代码如下:  
<!DOCTYPE html>  
<html>  

    <head>  
        <meta charset="UTF-8" />  
        <title>HELLO WORLD</title>  
        <!-- favicon.ico 404 -->  
        <link rel="shortcut icon" href="#" />  
    </head>  

    <body onLoad="onLoad()">  
        <div id="mapDiv"></div>  
    </body>  
    <!-- uni 的 SDK 注意uni sdk放到body下面 -->  
    <script type="text/javascript" src="https://unpkg.com/@dcloudio/uni-webview-js@0.0.1/index.js"></script>  
    <!-- 天地图 api -->  
    <script type="text/javascript" src="http://api.tianditu.gov.cn/api?v=4.0&tk=7db9f33de2e1c4c484682aed6a0764ac">  
    </script>  
    <script type="text/javascript">  
                // 此处是处理url传过来的参数 来自一篇博客 https://blog.csdn.net/qq_42961150/article/details/119890887  
        var getUrlData = {  
            callback: null,  
            _t: 0,  
            init(fn) {  
                this.callback = fn;  
                this.bind();  
                this.change.call(this);  
            },  
            bind() {  
                let that = this;  
                if (("onhashchange" in window) && ((typeof document.documentMode === "undefined") || document  
                        .documentMode == 8)) {  
                    window.onhashchange = () => {  
                        that.change.call(that);  
                    };  
                } else {  
                    clearInterval(this._t);  
                    this._t = setInterval(() => {  
                        that.change.call(that);  
                    }, 150);  
                }  
            },  
            change() {  
                let that = this,  
                    _hash = window.location.hash,  
                    _data = null;  
                try {  
                    _data = JSON.parse(decodeURIComponent(_hash.split('#')[1]));  
                } catch (e) {  
                    _data = decodeURIComponent(_hash.split('#')[1]);  
                }  
                if (that.callback) that.callback({  
                    type: that.getQuery('markers'),  
                    data: _data  
                });  
            },  
            getQuery(name) {  
                let reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");  
                let r = decodeURIComponent(window.location.search).substr(1).match(reg);  
                if (r != null) {  
                    // 对参数值进行解码  
                    return decodeURIComponent(r[2]);  
                }  
                return null;  
            }  
        }  
    </script>  
    <script type="text/javascript">  
        var map;  
        var zoom = 13;  

        // 标注点信息  
        var markers = [{  
                id: '1',  
                name: '站点一',  
                info: '这是第一个标记点',  
                position: [112.280637, 24.125178],  
                status: '正常'  
            },  
            {  
                id: '2',  
                name: '站点二',  
                info: '这是第二个标记点',  
                position: [112.280637, 24.125178],  
                status: '正常'  
            },  
            {  
                id: '3',  
                name: '站点三',  
                info: '这是第三个标记点',  
                position: [112.280637, 24.125178],  
                status: '异常'  
            },  
        ];  

        // 定义uni  
        var _uni;  

        // 待触发 `UniAppJSBridgeReady` 事件后,即可调用 uni 的 API。  
        document.addEventListener('UniAppJSBridgeReady', function() {  
            console.log("111")  
            _uni = uni  
            uni.getEnv(function(res) {  
                console.log('当前环境:' + JSON.stringify(res));  
            });  
        });  

        // 从uni-app拿信息  
        getUrlData.init(function(res) {  
            console.log(res); //返回的格式例如 {type: {}, data: 1}  
            // markers = JSON.parse(res.type)  
        })  

        function onLoad() {  
            map = new T.Map('mapDiv');  
            map.centerAndZoom(new T.LngLat(113.280637, 23.125178), zoom);  
            //创建缩放平移控件对象  
            control = new T.Control.Zoom();  
            //添加缩放平移控件  
            map.addControl(control);  
            // 添加标注点  
            addOverLay(markers);  
        }  

        // 添加标注点  
        function addOverLay(markers) {  
            for (let content of markers) {  
                //创建一个默认的标注点  
                //创建图片对象 img/uni@2x.png 修改成同一文件下图片  
                var icon = new T.Icon({  
                    iconUrl: "img/uni@2x.png",  
                    iconSize: new T.Point(19, 27),  
                    iconAnchor: new T.Point(10, 25)  
                });  
                //向地图上添加自定义标注 创建标注对象,实例化Marker类  
                var marker  
                if (content.status === '正常') {  
                    marker = new T.Marker(new T.LngLat(content.position[0], content.position[1]));  
                } else {  
                    marker = new T.Marker(new T.LngLat(content.position[0], content.position[1]), {  
                        icon: icon  
                    });  
                }  
                //向地图上添加标注。其中addOverLay(overlay:OverLay)方法将覆盖物添加到地图中,一个覆盖物实例只能向地图中添加一次。  
                map.addOverLay(marker);  
                //添加坐标点的监听事件,当鼠标触碰该点时打开信息窗口  
                addMouseoverHandler(content, marker);  
                //   
                label = new T.Label({  
                    text: `<b>${content.name}<b>`,  
                    position: marker.getLngLat(),  
                    offset: new T.Point(-35, 20)  
                });  
                map.addOverLay(label);  
            }  
        }  

        //鼠标在覆盖物上的监听事件  
        function addMouseoverHandler(content, marker) {  
            marker.addEventListener("click", function(e) {  
                openInfo(content, e)  
            });  
        }  

        //窗口信息  
        function openInfo(content, e) {  
            var point = e.lnglat;  
            // 创建信息窗口对象  
            var markerInfoWin = new T.InfoWindow()  
            var sContent =  
                `  
        <div id="win_box" style="height: auto; ">  
            <table style=" width:300px;border-collapse: separate;font-size:14px;border-spacing:0 6px;table-layout:fixed;">  
                <caption style="font-weight:bold;font-size:15px;">${content.info}区域</caption>  
                <tr><td style=" font-weight:bold;text-align:left;"><input type="button"value="详情"  style="cursor: pointer;outline: none;border:none;float: right;height: 25px;width: 50px;background-color:#dddddd;color: #57606f" onclick="getDetail(` +  
                JSON.stringify(content).replace(/"/g, '&quot;') + `)"></td></tr>  
            </table>  
        </div>  
        `;  
            //设置信息窗口要显示的内容  
            markerInfoWin.setContent(sContent);  
            //setOffset设置信息浮窗显示时向右下角偏移量(像素)。-30则代表向上偏移  
            markerInfoWin.setOffset(new T.Point(0, -30))  
            //开启信息窗口  
            map.openInfoWindow(markerInfoWin, point);  
        }  

        // 跳转详情 -- 通信uni-app  
        function getDetail(content) {  
            console.log(content)  
            _uni.postMessage({  
                data: {  
                    action: content,  
                    type: 'getDetail',  
                }  
            });  
        }  
    </script>  
    <style type="text/css">  
        /* 隐藏天地图图标等相关信息 */  
        #mapDiv .tdt-control-copyright.tdt-control>div:not(.tdt-control-copyright) {  
            display: none;  
        }  

        #mapDiv {  
            position: absolute;  
            width: 100%;  
            height: 100%  
        }  
    </style>  

</html>
收起阅读 »

高德地图的恶心事,集成前不明确告诉你收费,等有请求量了,高德会打电话敲诈勒索你5万起步

地图 高德地图

公司集成高德地图SDK,是先没有哪里能够明文告诉你要收5万/年的接口调用费,等你集成好了,上线了,OK,电话一个接一个的打过来,实施敲诈勒索。所以建议清理高德地图接口,集成有不集成高德,那么多的地图SDK,百度,腾讯等,为啥接受他们的勒索呢,无语!

公司集成高德地图SDK,是先没有哪里能够明文告诉你要收5万/年的接口调用费,等你集成好了,上线了,OK,电话一个接一个的打过来,实施敲诈勒索。所以建议清理高德地图接口,集成有不集成高德,那么多的地图SDK,百度,腾讯等,为啥接受他们的勒索呢,无语!