• vue插件开发-可拖动城市选择插件


    插件通常用来为 Vue 添加全局功能

    使用插件

    通过 Vue 的全局方法 Vue.use() 使用,

    当然,在使用这个方法之前,你的 Vue 实例 必须已经初始化完成

    // 引入自定义chooseCity 提示框
    import chooseCity from './plugin/chooseCity/index'
    Vue.use(chooseCity)

    实际案例:

    返回数据格式:

    {"data":[{"name":"北京","type":"leafNode","value":110000},{"name":"上海","type":"leafNode","value":310000},{"name":"天津","type":"leafNode","value":120000},{"name":"重庆","type":"leafNode","value":500000},{"name":"安徽","type":"next","value":340000},{"name":"福建","type":"next","value":350000},{"name":"甘肃","type":"next","value":620000},{"name":"广东","type":"next","value":440000},{"name":"广西","type":"next","value":450000},{"name":"贵州","type":"next","value":520000},{"name":"海南","type":"next","value":460000},{"name":"河北","type":"next","value":130000},{"name":"河南","type":"next","value":410000},{"name":"黑龙江","type":"next","value":230000},{"name":"湖北","type":"next","value":420000},{"name":"湖南","type":"next","value":430000},{"name":"吉林","type":"next","value":220000},{"name":"江苏","type":"next","value":320000},{"name":"江西","type":"next","value":360000},{"name":"辽宁","type":"next","value":210000},{"name":"内蒙古","type":"next","value":150000},{"name":"宁夏","type":"next","value":640000},{"name":"青海","type":"next","value":630000},{"name":"山东","type":"next","value":370000},{"name":"山西","type":"next","value":140000},{"name":"陕西","type":"next","value":610000},{"name":"四川","type":"next","value":510000},{"name":"西藏","type":"next","value":540000},{"name":"新疆","type":"next","value":650000},{"name":"云南","type":"next","value":530000},{"name":"浙江","type":"next","value":330000},{"name":"港澳台","type":"next","value":800000},{"name":"海外","type":"next","value":810000},{"name":"其它","type":"leafNode","value":999999}],"state":0,"status":"SUCCESS","statusCode":0}
    城市数据结构

    模板部分

    <template>
      <div class="chooseCity_warp" @click="closeCallBack(false,chooseCity)" id="chooseCity" v-if="show" >
            <div class="count el-dialog__header" @click.stop="" @mousedown="dowMos" @mouseup="upMos" @mousemove="move" >
                <div class="count_body">
                    <!-- 头部展示区域 -->
                    <div class="body_header" >
                        <div class="header_tip">{{config.title}}</div>
                        <div class="header_close"><span @click="closeCallBack(false,chooseCity)" class="close"></span></div>
                    </div>
                    <!-- 选中区域显示 -->
                    <div class="body_cont">
                        <!-- 选中文案显示部分 -->
                        <div class="choose_cont">
                            <div class="title">已选择:</div>
                            <div class="choose_msg">
                                <div class="item" v-for="(item,index) in chooseCity" :key="index"><span class="text">{{item.name}}</span><span @click="clearCity(item)" class="delete"></span></div>
                            </div>
                        </div>
                        <!-- 选择省、市部分 -->
                        <div class="choose_list_header">
                            <div class="header_item">省份/直辖市</div>
                            <div class="header_item">城市</div>
                        </div>
                        <div class="choose_list">
                            <div class="choose_provinceList">
                                <div class="provinceList_item city_item" v-for="(itemPro,indexPro) in provinceList" :key="indexPro+'pro'"  @click="choosePro(itemPro)">
                                    <div :class="{'proItem':itemPro.type != 'next','cityItem':itemPro.type == 'next','chooseActiveCity':chooseIds.includes(itemPro.value),'chooseActivePro':chooseProIds.includes(itemPro.value)}">{{itemPro.name}}</div>
                                </div>
                            </div>
                            <div class="cityList">
                                <div class="cityList_item city_item" v-for="(itemCit,indexCit) in cityList" :key="indexCit+'cit'" @click="chooseCit(itemCit)">
                                    <div :class="{'proItem':itemCit.type != 'next','chooseActiveCity':chooseIds.includes(itemCit.value)}">{{itemCit.name}}</div>
                                </div>
                            </div>
                        </div>
                    </div>
                    <!-- 底部按钮区域 -->
                    <div class="body_bot">
                        <span class="sure" v-if="config.r_btn && config.r_btn!=''"  @click="sureCallBack(true,config)">{{config.r_btn}}</span>
                        <span class="close" v-if="config.l_btn && config.l_btn!=''" @click="closeCallBack(false)">{{config.l_btn}}</span>
                    </div>
                    <!-- <div v-if="config.title !=''" class="confirm_header">
                        <slot name="confirm_header">{{config.title}}</slot>
                    </div>
                    <div class="confirm_body">
                            <div v-if="config.vnode && config.vnode!=''" v-html="config.vnode" > </div>
                            <span v-else>{{config.content}}</span>
                    </div>
                    <div class="confirm_footer">
                        <span class="sure" v-if="config.r_btn && config.r_btn!=''"  @click="sureCallBack(true)">{{config.r_btn}}</span>
                        <span class="close" v-if="config.l_btn && config.l_btn!=''" @click="closeCallBack(false)">{{config.l_btn}}</span>
                    </div> -->
                </div>
            </div>
      </div>
    </template>
    
    <script>
    
    export default {
      name: '',
      data() { 
        return {
            show: false,
            // 请求参数 0代表请求省级别 初始化 请求 一次
            cityParams:{
                parentId:'0'
            },
            chooseNum:1,
            proFlag:false,
            // 选中城市id集合
            chooseIds:[],
            // 选中省id集合
            chooseProIds:[],
            // 选中城市集合
            chooseCity:[],
            // 省集合
            provinceList:[],
            // 市集合
            cityList:[]
        }
      },
      props: {
          confirmOption:{
              type:Object,
              default:()=>{
                  return {
                    // 'title':'',
                    // 'content':'',
                    // 'r_btn':'继续',
                    // 'l_btn':'取消',
                  }
              }
          }
      },
      components:{
      },
      mounted() {
        //   console.log('this.config')
        //   console.log(this.config)
      },
      methods:{
    
      },
     }
    </script>
    
    <style scoped>
    .chooseCity_warp{background-color: rgba(255, 255, 255, 0.5);position: fixed;top: 0px;left: 0px;width: 100%;height: 100%;z-index: 1111;}
    .chooseCity_warp .count{min-width: 560px;position: absolute;top: 50%;left: 50%;transform: translateX(-50%) translateY(-50%);background-color: #ffffff;border-radius: 4px;  border-radius: 10px;background-color: rgba(102,102,102,0.2);padding: 10px;}
    .chooseCity_warp .count .count_body{background-color: #ffffff;}
    .chooseCity_warp .count .count_body .body_header{background-color: #555b65;color: #fff;border-radius: 3px 3px 0 0;height: 27px;display: flex;align-items: center;padding-left: 10px;} 
    .chooseCity_warp .count .count_body .body_header .header_tip{flex: 4;}
    .chooseCity_warp .count .count_body .body_header .header_close{flex: 1;}
    .chooseCity_warp .count .count_body .body_header .header_close .close{
        background: transparent url('../../assets/dialog_close.png') left top no-repeat;
        width: 19px;
        height: 19px;
        text-indent: -9999px;
        float: right;
        cursor: pointer;
        margin: 4px;
        overflow: hidden;
    }
    .chooseCity_warp .count .count_body .body_header .header_close .close:hover{
        background: transparent url('../../assets/dialog_close.png') left bottom no-repeat;
    }
    .chooseCity_warp .count .count_body .body_cont{padding: 15px;padding-bottom: 0px;}
    .chooseCity_warp .count .count_body .body_cont .choose_cont{padding: 6px 0px;display: flex;align-items: center;}
    .chooseCity_warp .count .count_body .body_cont .choose_cont .title{}
    .chooseCity_warp .count .count_body .body_cont .choose_cont .choose_msg{display: flex;align-items: center;}
    .chooseCity_warp .count .count_body .body_cont .choose_cont .choose_msg .item{
        background: transparent url('../../assets/pickpad.gif') no-repeat scroll left top;
        cursor: default;
        float: left;
        height: 20px;
        line-height: 20px;
        margin: 4px 2px;
        padding-left: 8px;
        padding-right: 20px;
        white-space: nowrap;
        color: #333;
    }
    .chooseCity_warp .count .count_body .body_cont .choose_cont .choose_msg .item .delete {
        background: url('../../assets/pickpad.gif') no-repeat scroll right top transparent;
        cursor: pointer;
        display: inline-block;
        height: 20px;
        margin-left: 6px;
        margin-right: -20px;
        text-indent: -99999px;
        width: 20px;
    }
    .chooseCity_warp .count .count_body .body_cont .choose_cont .choose_msg .item .delete:hover{
        background: url('../../assets/pickpad.gif') no-repeat scroll right bottom transparent;
    }
    .chooseCity_warp .count .count_body .body_cont .choose_cont .choose_msg .item .text{vertical-align: super;}
    .chooseCity_warp .count .count_body .body_cont .choose_list {display: flex;border: 1px solid #d9d9d9;}
    .chooseCity_warp .count .count_body .body_cont .choose_list_header {display: flex;border: 1px solid #d9d9d9;border-bottom: 0px solid #d9d9d9;border-right: 0px solid #d9d9d9;}
    .chooseCity_warp .count .count_body .body_cont .choose_list_header .header_item {flex: 1; text-align: center;  color: #999999; background: #f5f5f5;    line-height: 34px;border-right: 1px solid #d9d9d9;}
    .chooseCity_warp .count .count_body .body_cont .choose_list .choose_provinceList {flex: 1;height: 340px;overflow-y: scroll;}
    .chooseCity_warp .count .count_body .body_cont .choose_list .cityList {flex: 1;height: 340px;overflow-y: scroll;}
    .chooseCity_warp .count .count_body .body_cont .choose_list .city_item{ line-height: 34px;border-bottom: 1px solid #d9d9d9;}
    .chooseCity_warp .count .count_body .body_cont .choose_list .proItem {
        padding: 0px 10px 0px 20px;
        background-image: url("data:image/IFf;base64,R0lGODlhFQAIAIABAP///wAAACH5BAEAAAEALAAAAAAVAAgAAAIXjH8AyJ3qolFLBviqpRPbTmkfKI6deRQAOw==");
    }
    .chooseCity_warp .count .count_body .body_cont .choose_list .proItem:hover {
        background: #e4f7f9 right center no-repeat;
        background-image: url("data:image/IFf;base64,R0lGODlhFQAIAIABAA+puwAAACH5BAEAAAEALAAAAAAVAAgAAAIXjH8AyJ3qolFLBviqpRPbTmkfKI6deRQAOw==");
    }
    .chooseCity_warp .count .count_body .body_cont .choose_list .cityItem{
        padding: 0px 10px 0px 20px;
        background-image: url("data:image/IFf;base64,R0lGODlhFQAIAIABAP///wAAACH5BAEAAAEALAAAAAAVAAgAAAIXjH8AyJ3qolFLBviqpRPbTmkfKI6deRQAOw==");
    }
    .chooseCity_warp .count .count_body .body_cont .choose_list .cityItem:hover {
        background: #e4f7f9 right center no-repeat;
        background-image: url("data:image/IFf;base64,R0lGODlhFAALAIABAA+puwAAACH5BAEAAAEALAAAAAAUAAsAAAIVRI6pauvbngxxumpZhlt3hG1hNmYFADs=");
    }
    .chooseCity_warp .count .count_body .body_cont .choose_list .chooseActiveCity{
        color: #fff;
        background: #0fa9bb right center no-repeat;
        background-image: url("data:image/IFf;base64,R0lGODlhFQAIAIABAP///wAAACH5BAEAAAEALAAAAAAVAAgAAAIXjH8AyJ3qolFLBviqpRPbTmkfKI6deRQAOw==")
    }
    .chooseCity_warp .count .count_body .body_cont .choose_list .chooseActiveCity:hover{
        color: #fff;
        background: #0fa9bb right center no-repeat;
        background-image: url("data:image/IFf;base64,R0lGODlhFQAIAIABAP///wAAACH5BAEAAAEALAAAAAAVAAgAAAIXjH8AyJ3qolFLBviqpRPbTmkfKI6deRQAOw==")
    }
    .chooseCity_warp .count .count_body .body_cont .choose_list .chooseActivePro{
        color: #fff;
        background: #0fa9bb right center no-repeat;
        background-image: url("data:image/IFf;base64,R0lGODlhFAALAIABAP///wAAACH5BAEAAAEALAAAAAAUAAsAAAIVRI6pauvbngxxumpZhlt3hG1hNmYFADs=")
    }
    .chooseCity_warp .count .count_body .body_cont .choose_list .chooseActivePro:hover{
        color: #fff;
        background: #0fa9bb right center no-repeat;
        background-image: url("data:image/IFf;base64,R0lGODlhFAALAIABAP///wAAACH5BAEAAAEALAAAAAAUAAsAAAIVRI6pauvbngxxumpZhlt3hG1hNmYFADs=")
    }
    .chooseCity_warp .count .count_body .body_bot {background-color: #f6f6f6;padding: 8px 20px 8px 0;text-align: right;}
    .chooseCity_warp .count .count_body .body_bot .sure{color: #333;line-height: 26px;display: inline-block;height: 26px;padding: 2px 20px;border-radius: 4px;margin-right: 10px;background-color: #fee579;border: 1px solid #c6c6c6;cursor: pointer;}
    .chooseCity_warp .count .count_body .body_bot .close{color: #333;line-height: 26px;display: inline-block;height: 26px;padding: 2px 20px;border-radius: 4px;background-color: #f8f8f8;border: 1px solid #c6c6c6;cursor: pointer;}
    /* .chooseCity_warp .count .count_body .body_bot .close{color: #333;} */
    /* .confirm_warp .count .confirm_header{text-align: center;}
    .confirm_warp .count .confirm_body{padding: 20px;min-height: 40px;}
    .confirm_warp .count .confirm_footer{padding: 20px;min-height: 40px;text-align: center;}
    .confirm_warp .count .confirm_footer span{display: inline-block;font-size: 14px;padding: 4px 25px;cursor: pointer;border-radius: 2px;}
    .confirm_warp .count .confirm_footer .sure{background-color: #E62679;color: #ffffff;}
    .confirm_warp .count .confirm_footer .close{background-color: #ffffff;color: #E62679;border: 1px solid #E62679;padding: 3px 25px;margin-left: 20px;} */
    
    </style>
    template模板

    逻辑部分

    import chooseCity from './index.vue'
    import { cityList } from '../../api/accountaudit/talentManagement'
    
    import Vue from 'vue'
    // import { isVNode } from 'element-ui/src/utils/vdom';
    /*
     *    this.$lstchooseCity({
            title:'这是什么东西~',//标题
            chooseNum:1,//选中城市数量
            draco:false,//是否允许拖动
            proFlag: false,// 是否允许获取省级别
            chooseCity:[
                {
                    name: "上海",
                    type: "leafNode",
                    value: 310000
                }
            ],// 选中城市 默认选中
            r_btn:'确定',//左侧按钮
            l_btn:'取消',//右侧按钮
            vnode:'<span>饿哦是内容区域</span>',//内容自定义部分
            content:"我也不知道这是什么东西啊!!!"//内容文本
          }).then(res=>{
              console.log(res)//点击按钮回调函数
          })
     */
    
    let chooseCityIndex = {};
    
    chooseCityIndex.install = function (Vue,options) {
        const confirmIndexConstructor = Vue.extend(chooseCity);
    
        // 生成一个该之类的实例
        const instance = new confirmIndexConstructor();
            // $_getCitylist(){
            //     cityList(this.cityParams).then((res) => {
    
            //     })
            // }
    
        Vue.prototype.$lstchooseCity = (config) => {
            // 这里 return 一个 Promise 
            // 在项目中使用的时候,就可以进行链式调用了~
            return new Promise((resolve,reject) => {
                instance.config = config;
                instance.chooseNum = config.chooseNum || 1;
                instance.draco = config.draco || true;
                instance.proFlag = config.proFlag || false;
                instance.chooseCity = [ ...config.chooseCityArrs ] || [];
                //instance.chooseCity = config.chooseCityArrs  || [];
                instance.show = true;
                instance.moseMove = false;
                instance.mosX = 0;
                instance.mosY = 0;
                let chooseCitArr = []
                // console.log(config)
                // 拖动
                instance.dowMos = (e) => {
                    instance.moseMove = true;
                    instance.mosX = e.clientX;
                    instance.mosY = e.clientY;
                }
                instance.upMos = () => {instance.moseMove = false;}
                instance.move = (e) => {
                    // console.log(e.target)
                    if(!instance.draco){
                        return false;
                    }
                    if(!instance.moseMove){
                        return false;
                    }
                    // let odiv = e.target;        //获取目标元素
                    const odiv = document.querySelector('.el-dialog__header') //获取目标元素
                    // console.log(odiv)
                    //算出鼠标相对元素的位置
                    let disX = e.clientX - odiv.offsetLeft;
                    let disY = e.clientY - odiv.offsetTop;
                    // 计算出 移动的距离
                    let mosx = e.clientX - instance.mosX;
                    let mosy = e.clientY - instance.mosY;
                    document.onmousemove = (e)=>{       //鼠标按下并移动的事件
                        //用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
                        // let left = e.clientX - disX;    
                        // let top = e.clientY - disY;
                        let left = odiv.offsetLeft  + mosx;    
                        let top = odiv.offsetTop + mosy;
                        //绑定元素位置到positionX和positionY上面
                        instance.mosX = e.clientX;
                        instance.mosY = e.clientY;
                        //移动当前元素
                        odiv.style.left = left + 'px';
                        odiv.style.top = top + 'px';
                    };
                    document.onmouseup = (e) => {
                        document.onmousemove = null;
                        document.onmouseup = null;
                    };
                // }  
                }
                instance.getCity = () => {
                    instance.cityList = []
                    cityList(instance.cityParams).then((res) => {
                        if(instance.cityParams.parentId == 0){
                            instance.provinceList = res.data;
                        }else{
                            instance.cityList = res.data;
                        }
                    })
                }
                
                // 获取当前选中城市 id集合
                instance.getCityIds = () => {
                    instance.chooseIds = [];
                    instance.chooseCity.forEach((ele) => {
                        instance.chooseIds.push(ele.value)
                    })
                }
                // 初始化 获取城市 省级别获取后再次打开不在请求接口
                if(instance.provinceList.length  == 0){
                    instance.getCity();
                }
                
                // 初始化 获取已经选中的 // 获取当前选中城市 id集合
                instance.getCityIds();
                // 选择省级别
                instance.choosePro = (val)=>{
                    instance.cityParams.parentId = val.value
                    if(val.type == 'next'){
                        instance.getCity();
                        instance.chooseProIds = []
                        instance.chooseProIds.push(val.value)
                        // 判断是否获取升级别数据
                        if(instance.proFlag){
                            instance.clearCity(val)
                            if(instance.chooseCity.length > instance.chooseNum){
                                instance.chooseCity = instance.chooseCity.splice(1,instance.chooseNum);
                            }
                        }
                    }else{
                        instance.chooseProIds = []
                        instance.cityList = [];
                        instance.chooseIds.push(val.value);
                        instance.clearCity(val)
                        if(instance.chooseCity.length > instance.chooseNum){
                            instance.chooseCity = instance.chooseCity.splice(1,instance.chooseNum);
                        }
                        // 获取当前选中城市 id集合
                        instance.getCityIds();
                    }
                }
                // 选择市级别
                instance.chooseCit = (val)=>{
                    // console.log(val)
                    instance.chooseIds = [];
                    instance.chooseIds.push(val.value)
                    instance.clearCity(val)
                    if(instance.chooseCity.length > instance.chooseNum){
                        instance.chooseCity = instance.chooseCity.splice(1,instance.chooseNum);
                    }
                    // 获取当前选中城市 id集合
                    instance.getCityIds();
                }
                // 双击取消当前选中的城市
                instance.clearCity = (val) => {
                    // console.log(111)
                    let flag = true;
                    instance.chooseCity.forEach((ele,index) => {
                        if(ele.value == val.value){
                            flag = false;
                            instance.chooseCity.splice(index,1);
                            return false;
                        }
                    });
                    if(flag){
                        instance.chooseCity.push(val)
                    }
                    chooseCitArr = instance.chooseCity
                    // 获取当前选中城市 id集合
                    instance.getCityIds();
                }
                instance.sureCallBack = () => {
                    instance.show = false;
                    let params = {
                        type :true,
                        data:instance.chooseCity
                    }
                    resolve(params);
                }
                instance.closeCallBack = () => {
                    instance.show = false;
                    let params = {
                        type :false,
                        // data:instance.chooseCity
                    }
                    resolve(params);
                    // resolve(false)
                }
            })
        }
        // 将这个实例挂载在我创建的div上
        // 并将此div加入全局挂载点内部
    
        instance.$mount(document.createElement('div'))
    
        document.body.appendChild(instance.$el)
    
    }
    
    export default chooseCityIndex;
    js逻辑部分

    效果截图展示

    使用方式

    this.$lstchooseCity({
            title:'这是什么东西~',//标题
            chooseNum:1,//选中城市数量
            draco:false,//是否允许拖动
            proFlag: false,// 是否允许获取省级别
            chooseCity:[
                {
                    name: "上海",
                    type: "leafNode",
                    value: 310000
                }
            ],// 选中城市 默认选中
            r_btn:'确定',//左侧按钮
            l_btn:'取消',//右侧按钮
            vnode:'<span>饿哦是内容区域</span>',//内容自定义部分
            content:"我也不知道这是什么东西啊!!!"//内容文本
          }).then(res=>{
              console.log(res)//点击按钮回调函数
          })
  • 相关阅读:
    [问题2014A05] 复旦高等代数 I(14级)每周一题(第七教学周)
    oracle的相关信息
    进程和线程的区别
    阿里云人脸检测定位
    php与oracle11g经典分页
    Linux 远程复制
    redis的相关信息
    教你编译PHP7 (nginx+mysql+php7)
    nginx的相关信息
    php about session store db or cache
  • 原文地址:https://www.cnblogs.com/lst619247/p/14450873.html
Copyright © 2020-2023  润新知