| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 | <template>  <su-popup :show="show" @close="onCancel" round="20">    <view class="ui-region-picker">      <su-toolbar        :cancelColor="cancelColor"        :confirmColor="confirmColor"        :cancelText="cancelText"        :confirmText="confirmText"        title="选择区域"        @cancel="onCancel"        @confirm="onConfirm('confirm')"      ></su-toolbar>      <view class="ui-picker-body">        <picker-view          :value="state.currentIndex"          @change="change"          class="ui-picker-view"          @pickstart="pickstart"          @pickend="pickend"        >          <picker-view-column>            <view class="ui-column-item" v-for="province in provinceList" :key="province.id">              <view :style="getSizeByNameLength(province.name)">{{ province.name }}</view>            </view>          </picker-view-column>          <picker-view-column>            <view class="ui-column-item" v-for="city in cityList" :key="city.id">              <view :style="getSizeByNameLength(city.name)">{{ city.name }}</view>            </view>          </picker-view-column>          <picker-view-column>            <view class="ui-column-item" v-for="district in districtList" :key="district.id">              <view :style="getSizeByNameLength(district.name)">{{ district.name }}</view>            </view>          </picker-view-column>        </picker-view>      </view>    </view>  </su-popup></template><script setup>  /**   * picker picker弹出选择器   * @property {Object} params 需要显示的参   * @property {Boolean} safe-area-inset-bottom 是否开启底部安全区适配(默认false)   * @property {Boolean} show-time-tag 时间模式时,是否显示后面的年月日中文提示   * @property {String} cancel-color 取消按钮的颜色   * @property {String} confirm-color 确认按钮的颜色   * @property {String} confirm-text 确认按钮的文字   * @property {String} cancel-text 取消按钮的文字   * @property {String} default-region 默认选中的地区,   * @property {String} default-code 默认选中的地区   * @property {Boolean} mask-close-able 是否允许通过点击遮罩关闭Picker(默认true)   * @property {String Number} z-index 弹出时的z-index值(默认1075)   * @property {Array} default-selector 数组形式,其中每一项表示选择了range对应项中的第几个   * @property {String} range-key 当range参数的元素为对象时,指定Object中的哪个key的值作为选择器显示内容   * @event {Function} confirm 点击确定按钮,返回当前选择的值   * @event {Function} cancel 点击取消按钮,返回当前选择的值   */  import { computed, reactive } from 'vue';  const props = defineProps({    show: {      type: Boolean,      default: false,    },    // "取消"按钮的颜色    cancelColor: {      type: String,      default: '#6666',    },    // "确定"按钮的颜色    confirmColor: {      type: String,      default: 'var(--ui-BG-Main)',    },    // 取消按钮的文字    cancelText: {      type: String,      default: '取消',    },    // 确认按钮的文字    confirmText: {      type: String,      default: '确认',    },  });  const areaData = uni.getStorageSync('areaData');  const getSizeByNameLength = (name) => {    let length = name.length;    if (length <= 7) return '';    if (length < 9) {      return 'font-size:28rpx';    } else {      return 'font-size: 24rpx';    }  };  const state = reactive({    currentIndex: [0, 0, 0],    moving: false, // 列是否还在滑动中,微信小程序如果在滑动中就点确定,结果可能不准确  });  const emits = defineEmits(['confirm', 'cancel', 'change']);  const provinceList = areaData;  const cityList = computed(() => {    return areaData[state.currentIndex[0]].children;  });  const districtList = computed(() => {    return cityList.value[state.currentIndex[1]]?.children;  });  // 标识滑动开始,只有微信小程序才有这样的事件  const pickstart = () => {    // #ifdef MP-WEIXIN    state.moving = true;    // #endif  };  // 标识滑动结束  const pickend = () => {    // #ifdef MP-WEIXIN    state.moving = false;    // #endif  };  const init = () => {};  const onCancel = () => {    emits('cancel');  };  // 用户更改picker的列选项  const change = (e) => {    if (      state.currentIndex[0] === e.detail.value[0] &&      state.currentIndex[1] === e.detail.value[1]    ) {      // 不更改省市区列表      state.currentIndex[2] = e.detail.value[2];      return;    } else {      // 更改省市区列表      if (state.currentIndex[0] !== e.detail.value[0]) {        e.detail.value[1] = 0;      }      e.detail.value[2] = 0;      state.currentIndex = e.detail.value;    }    emits('change', state.currentIndex);  };  // 用户点击确定按钮  const onConfirm = (event = null) => {    // #ifdef MP-WEIXIN    if (state.moving) return;    // #endif    let index = state.currentIndex;    let province = provinceList[index[0]];    let city = cityList.value[index[1]];    let district = districtList.value[index[2]];    let result = {      province_name: province.name,      province_id: province.id,      city_name: city.name,      city_id: city.id,      district_name: district.name,      district_id: district.id,    };    if (event) emits(event, result);  };</script><style lang="scss" scoped>  .ui-region-picker {    position: relative;    z-index: 999;  }  .ui-picker-view {    height: 100%;    box-sizing: border-box;  }  .ui-picker-header {    width: 100%;    height: 90rpx;    padding: 0 40rpx;    display: flex;    justify-content: space-between;    align-items: center;    box-sizing: border-box;    font-size: 30rpx;    background: #fff;    position: relative;  }  .ui-picker-header::after {    content: '';    position: absolute;    border-bottom: 1rpx solid #eaeef1;    -webkit-transform: scaleY(0.5);    transform: scaleY(0.5);    bottom: 0;    right: 0;    left: 0;  }  .ui-picker__title {    color: #333;  }  .ui-picker-body {    width: 100%;    height: 500rpx;    overflow: hidden;    background-color: #fff;  }  .ui-column-item {    display: flex;    align-items: center;    justify-content: center;    font-size: 32rpx;    color: #333;    padding: 0 8rpx;  }  .ui-btn-picker {    padding: 16rpx;    box-sizing: border-box;    text-align: center;    text-decoration: none;  }  .ui-opacity {    opacity: 0.5;  }  .ui-btn-picker--primary {    color: blue;  }  .ui-btn-picker--tips {    color: red;  }</style>
 |