uniapp 下拉菜单地区和筛选(使用直接改源代码适配)

 

<template>
  <view class="wrapper">
    <view class="wrapper-tap">
      <view class="tap" @click="handleRegion('region')">
        地区
        <view :class="isShowPopup?'triangle-show':'triangle'"></view>
      </view>
      <view class="tap" @click="handleRegion('screen')">
        筛选
        <view :class="isScreen?'triangle-show':'triangle'"></view>
      </view>
    </view>
    <!-- 遮罩层 -->
    <view :class="isShowPopup?'make':''" @touchmove.stop.prevent="disabledScroll" @click="isShowPopup = false"></view>
    <!-- 地区 -->
    <view class="popup-box" :class="isShowPopup?'popup-transition':'popup-none'">
      <view class="region-box">
        <scroll-view class="region-province" scroll-y="true">
          <view class="item-province" :class="activeProvince == index?'active-item':''" v-for="(item,index) in cityAddr"
            :key="index" @click="handleActiveName('province',index)">
            {{item.name}}
          </view>
        </scroll-view>
        <scroll-view class="region-province" scroll-y="true"
          :style="{width:!cityArea||cityArea.length==0?'100%':'250rpx'}" v-if="cityColumns.length>0">
          <view :style="{width:!cityArea||cityArea.length==0?'100%':'250rpx'}" class="item-province"
            :class="activeCity == index?'active-item-city':''" v-for="(item,index) in cityColumns" :key="index"
            @click="handleActiveName('city',index)">
            {{item.name}}
          </view>
        </scroll-view>
        <scroll-view class="region-province" scroll-y="true" v-if="cityArea&&cityArea.length>0">
          <view class="item-province" :class="activeArea == index?'active-item-city':''"
            v-for="(item,index) in cityArea" :key="index" @click="handleActiveName('area',index)">
            {{item.name}}
          </view>
        </scroll-view>
      </view>
      <view class="region-btn">
        <view class="region-reset" @click="handleReset('region')">
          重置
        </view>
        <view class="region-view" @click="handleViewCode('region')">
          查看
        </view>
      </view>
    </view>
    <view :class="isScreen?'make':''" @click="isScreen = false"></view>
    <!-- 筛选 -->
    <view class="popup-box" :class="isScreen?'popup-transition-screen':'popup-none'">
      <view class="screen-box">
        <view class="screen-title" style="margin-top: 32rpx;">
          品种
        </view>
        <scroll-view scroll-y="true" class="screen-scroll">
          <view class="screen-item-check">
            <view class="screec-item-variety" :class="item.isSelect?'active-item':''"
              v-for="(item,index) in varietyDataList" :key="index" @click="handleSelectData(item)">
              <view class="screec-item-text">
                {{item.name}}
              </view>
              <view v-if="item.isSelect" class="right-icon"></view>
            </view>
          </view>
        </scroll-view>
        <view class="screen-title" style="margin-top: 48rpx;">
          价格区间(元)
        </view>
        <view class="fillIn-the-blank">
          <input placeholder-style="text-align: center;" type="number" @input="(e)=>handleChangePriceMin(e)"
            :value="paramsData.priceMin" class="fillIn-input" placeholder="最低价" />
          <text style="padding: 0 20rpx;">一</text>
          <input placeholder-style="text-align: center;" type="number" @input="(e)=>handleChangePriceMax(e)"
            :value="paramsData.priceMax" class="fillIn-input" placeholder="最高价" />
        </view>
      </view>
      <view class="region-btn">
        <view class="region-reset" @click="handleReset('screen')">
          重置
        </view>
        <view class="region-view" @click="handleViewCode('screen')">
          查看 ({{total>999?'999+':total}}宝贝)
        </view>
      </view>
    </view>
  </view>
</template>

<script>
  import {
    petItemPageCount
  } from "@/api/home.js"
  import {
    debounce
  } from "@/utils/utils.js"
  export default {
    props: {
      // 地区数据
      areaList: {
        type: Array,
        default: () => []
      },
      // 品种数据
      varietyList: {
        type: Array,
        default: () => []
      },

    },
    data() {
      return {
        total: 0, // 商品数量
        activeProvince: -1, // 切换选中的省
        activeCity: -1, //切换选中的市
        activeArea: -1, //切换选中的市
        isShowPopup: false, // 地区控制是否展示
        isScreen: false, // 筛选控制是都展示
        varietyDataList: [], // 品种
        paramsData: {
          provinceCode: [],
          ids: [],
          priceMin: "", //最低值
          priceMax: "" // 最高值
        } // 数据缓存
      }
    },
    watch: {
      varietyList: {
        immediate: true,
        deep: true,
        handler(newVal, oldVal) {
          this.varietyDataList = JSON.parse(JSON.stringify(this.varietyList))
        }
      }
    },
    computed: {
      // 省
      cityAddr() {
        return this.areaList.length > 0 ? this.areaList : []
      },
      //市
      cityColumns() {
        let province = this.cityAddr[this.activeProvince]
        let areaVOList = province ? province.areaVOList : []
        let city = this.cityAddr.length > 0 ? areaVOList : []
        return city
      },
      // 区
      cityArea() {
        let province = this.cityAddr[this.activeProvince] // 省
        let city = province ? province.areaVOList[this.activeCity] : [] // 市
        let areaVOList = city ? city.areaVOList : [] // 区
        let area = this.cityAddr.length > 0 ? areaVOList : []
        return []
      },
    },
    methods: {
      // 获取商品数量
      handleGetCount(param) {
        let params = {
          petBreedIds: param.ids.join(','),
          priceMin: param.priceMin || "",
          priceMax: param.priceMax || ""
        }
        petItemPageCount(params).then((res) => {
          if (res.code == 200) {
            this.total = res.data
          }
        }).catch((err) => {
          console.log(err, 'err')
        })
      },
      // 控件
      handleRegion(type) {
        if (type == 'region') {
          // 地区展开关闭 控制 事件
          this.isShowPopup = !this.isShowPopup
          this.isScreen = false
        } else {
          // 筛选展开关闭 控制 事件
          this.isScreen = !this.isScreen
          this.isShowPopup = false
        }
      },

      // 城市切换
      handleActiveName(type, index) {
        if (type == 'province') {
          this.activeProvince = index
          this.activeCity = 0
        }
        if (type == 'city') {
          this.activeCity = index
          this.activeArea = 0
        }
        if (type == 'area') {
          this.activeArea = index
        }
      },
      // 选择品种
      handleSelectData(data) {
        const {
          id
        } = data
        let newArr = JSON.parse(JSON.stringify(this.varietyDataList))
        newArr = newArr.map((item) => {
          let obj = {
            ...item
          }
          if (item.id === id) {
            obj = {
              ...obj,
              isSelect: !obj.isSelect
            }
          }
          return obj
        })
        this.varietyDataList = newArr
        let ids = this.varietyDataList.map((item) => {
          if (item.isSelect) {
            return item.id
          }
        }).filter((v) => v)
        this.paramsData.ids = ids
        this.handleGetCount(this.paramsData)
      },
      // 
      handleChangePriceMin: debounce(function(val) {
        this.paramsData.priceMin = val.detail.value
        this.handleGetCount(this.paramsData)
      }, 500),
      handleChangePriceMax: debounce(function(val) {
        this.paramsData.priceMax = val.detail.value
        this.handleGetCount(this.paramsData)
      }, 500),
      //查看
      handleViewCode(type) {
        if (type == 'region') {
          let province = this.cityAddr[this.activeProvince].code
          let city = this.cityColumns[this.activeCity].code
          let area
          if (this.cityArea && this.cityArea.length > 0) {
            area = this.cityArea[this.activeArea].code
          }

          let provinceCode = this.cityArea && this.cityArea.length > 0 ? [province, city, area] : [province, city]

          this.paramsData = {
            ...this.paramsData,
            provinceCode
          }

          this.isShowPopup = false
        }
        if (type == 'screen') {
          let {
            priceMin,
            priceMax
          } = this.paramsData
          let ids = this.varietyDataList.map((item) => {
            if (item.isSelect) {
              return item.id
            }
          }).filter((v) => v)
          this.paramsData = {
            ...this.paramsData,
            ids,
            priceMin,
            priceMax
          }
          this.isScreen = false
        }
        console.log(this.paramsData, 'params')

        this.confirm(this.paramsData)
      },
      //触发事件
      confirm(val) {
        this.$emit('confirm', val)
      },
      // 重置
      handleReset(type) {
        if (type == 'region') {
          this.activeProvince = -1
          this.activeCity = -1
          this.activeArea = -1
          this.paramsData = {
            ...this.paramsData,
            provinceCode: []
          }
        }
        if (type == 'screen') {
          let newArr = JSON.parse(JSON.stringify(this.varietyDataList))
          this.varietyDataList = newArr.map((item) => {
            return {
              ...item,
              isSelect: false
            }
          })

          this.paramsData = {
            ...this.paramsData,
            ids: [],
            priceMin: "",
            priceMax: ""
          }
        }
        this.$emit('reset', this.paramsData)
      },
      // 阻止滚动
      disabledScroll() {
        return
      }
    }
  }
</script>

<style lang="scss" scoped>
  .wrapper {
    width: 100%;
    position: relative;
  }

  .make {
    position: fixed;
    width: 100%;
    height: 100vh;
    background: #000000;
    opacity: 0.6;
    z-index: 9;
  }

  .wrapper-tap {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 750rpx;
    height: 72rpx;
    background: linear-gradient(180deg, #FFFFFF 0%, #FBF8F4 100%);
    border-radius: 28rpx 28rpx 0rpx 0rpx;

    .tap {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 50%;
      font-size: 28rpx;
      font-family: PingFangSC-Regular, PingFang SC;
      font-weight: 400;
      color: #333333;
    }
  }

  .popup-box {
    position: absolute;
    z-index: 999;
    width: 100%;
    height: 0rpx;
    background: #ffffff;
    border-radius: 0rpx 0rpx 28rpx 28rpx;
    overflow: hidden;
  }

  .popup-transition {
    // animation-name: example;
    // animation-duration: 2s;
    height: 800rpx;
  }

  .popup-transition-screen {
    height: 770rpx;
  }

  .popup-none {
    display: none;
  }

  //正三角
  .triangle {
    width: 0;
    height: 0;
    border-left: 5px solid transparent;
    border-right: 5px solid transparent;
    border-bottom: 5px solid #D0D0D0;
    margin-left: 10rpx;
  }

  //倒三角
  .triangle-show {
    width: 0;
    height: 0;
    border-left: 5px solid transparent;
    border-right: 5px solid transparent;
    border-top: 5px solid #FD991B;
  }



  // 展开动画
  @keyframes example {
    from {
      height: 0rpx;
    }

    to {
      height: 800rpx;
    }
  }


  // 地区
  .region-box {
    width: 100%;
    height: 648rpx;
    display: flex;
    // align-items: center;
    justify-content: flex-start;
    border-radius: 0rpx 0rpx 28rpx 28rpx;

    .region-province {
      width: 270rpx;
      height: 100%;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;

      .item-province {
        width: 270rpx;
        height: 108rpx;
        background-color: #f7f7f7;
        display: flex;
        align-items: center;
        justify-content: center;
      }

      .active-item {
        color: #FD991B;
        border-left: 1rpx solid #FD991B;
        border-width: 15rpx;
        background-color: #ffffff;
      }

      .active-item-city {
        color: #FD991B;
        background-color: #ffffff;
      }
    }
  }


  // 按钮
  .region-btn {
    position: absolute;
    bottom: 32rpx;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 32rpx 28rpx 0;
    box-sizing: border-box;

    .region-reset {
      width: 335rpx;
      height: 88rpx;
      border-radius: 50rpx;
      border: 2rpx solid #FE8706;
      font-size: 32rpx;
      font-family: PingFangSC-Medium, PingFang SC;
      font-weight: 500;
      color: #FD981A;
      text-align: center;
      line-height: 88rpx;
      margin-right: 10rpx;
    }

    .region-view {
      width: 335rpx;
      height: 88rpx;
      background: linear-gradient(177deg, #FAB33A 0%, #FE8706 100%);
      border-radius: 50rpx;
      font-size: 32rpx;
      font-family: PingFangSC-Medium, PingFang SC;
      font-weight: 500;
      color: #FFFFFF;
      text-align: center;
      line-height: 88rpx;
      margin-left: 10rpx;
    }
  }

  // 筛选
  .screen-box {
    width: 100%;
    height: 620rpx;
    display: flex;
    // align-items: center;
    flex-direction: column;
    justify-content: center;
    border-radius: 0rpx 0rpx 28rpx 28rpx;
    padding: 0 28rpx;
    box-sizing: border-box;

    .screen-title {
      font-size: 28rpx;
      font-family: PingFangSC-Medium, PingFang SC;
      font-weight: 600;
      color: #333333;
      margin-bottom: 18rpx;
    }

    .screen-scroll {
      width: 100%;
      height: 300rpx;
      // margin-top: 20rpx;

      .screen-item-check {
        width: 100%;
        height: 300rpx;
        display: grid;
        grid-template-columns: repeat(3, 31.33%);
        grid-template-rows: repeat(3, 33.33%);
        grid-row-gap: 18rpx;
        grid-column-gap: 18rpx;
        justify-content: center;
        // display: flex;
        // align-items: center;
        // flex-wrap: wrap;
        // justify-content: flex-start;

        .screec-item-variety {
          display: flex;
          align-items: center;
          justify-content: center;
          width: auto;
          height: 60rpx;
          background: #F5F5F5;
          border-radius: 4rpx;
          box-sizing: border-box;
          position: relative;
          // padding: 14px 73rpx;
          // margin-right: 18rpx;
          // margin-bottom: 18rpx;

          .screec-item-text {
            width: auto;
            font-size: 24rpx;
            font-family: PingFangSC-Regular, PingFang SC;
            font-weight: 400;
            color: #333333;
          }

          .right-icon {
            position: absolute;
            width: 33rpx;
            height: 32rpx;
            right: 0rpx;
            bottom: -1rpx;
            background-image: url('https://files.yiyujiehe.com/common/2023-11-13/069de3c6f9bf480d9f8017dfbfc7c8c0.png');
            background-size: 100% 100%;
            background-repeat: no-repeat;
          }
        }

        .active-item {
          border: 2rpx solid #FE8706;
        }
      }

    }

    .fillIn-the-blank {
      display: flex;
      align-items: center;
      justify-content: center;
      box-sizing: border-box;
      margin: 0 auto;

      .fillIn-input {
        width: 290rpx;
        height: 82rpx;
        line-height: 2em;
        border-radius: 50rpx;
        border: 2rpx solid #999999;
        font-size: 24rpx;
        font-family: PingFangSC-Regular, PingFang SC;
        font-weight: 400;
        color: #999999;
        padding: 0rpx 20rpx;
        box-sizing: border-box;
      }
    }
  }
</style>

需要传两个列表也可以优化成,代码比较通俗易懂,直接改动源码即可

data:{
list:[],
list2:[]
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值