ソースを参照

Merge branch 'next' of https://github.com/jdf2e/nutui into next

richard1015 4 年 前
コミット
77a4e26c6d

+ 35 - 1
src/packages/__VUE/address/demo.vue

@@ -19,6 +19,27 @@
       custom-address-title="请选择所在地区"
     ></nut-address>
 
+    <h2>选择自定义地址2</h2>
+    <nut-cell
+      title="选择地址"
+      :desc="five"
+      is-link
+      @click="showAddress2"
+    ></nut-cell>
+
+    <nut-address
+      v-model:visible="normal2"
+      type="custom2"
+      :province="province"
+      :city="city"
+      :country="country"
+      :town="town"
+      height="270px"
+      @change="(cal) => onChange(cal, 'normal2')"
+      @close="close5"
+      custom-address-title="请选择所在地区"
+    ></nut-address>
+
     <h2>选择已有地址</h2>
     <nut-cell
       title="选择地址"
@@ -149,6 +170,7 @@ export default createDemo({
 
     const showPopup = reactive({
       normal: false,
+      normal2: false,
       exist: false,
       customImg: false,
       other: false
@@ -201,13 +223,18 @@ export default createDemo({
       one: '请选择地址',
       two: '请选择地址',
       three: '请选择地址',
-      four: '请选择地址'
+      four: '请选择地址',
+      five: '请选择地址'
     });
 
     const showAddress = () => {
       showPopup.normal = !showPopup.normal;
     };
 
+    const showAddress2 = () => {
+      showPopup.normal2 = !showPopup.normal2;
+    };
+
     const onChange = (cal: CalBack, tag: string) => {
       const name = (address as any)[cal.next];
       if (name.length < 1) {
@@ -219,6 +246,11 @@ export default createDemo({
       text.one = val.data.addressStr;
     };
 
+    const close5 = (val: CalResult) => {
+      console.log(val);
+      text.five = val.data.addressStr;
+    };
+
     const showAddressExist = () => {
       showPopup.exist = true;
     };
@@ -288,11 +320,13 @@ export default createDemo({
 
     return {
       showAddress,
+      showAddress2,
       showPopup,
       onChange,
       close1,
       showAddressExist,
       close2,
+      close5,
       selected,
       existAddress,
       showAddressOther,

+ 72 - 11
src/packages/__VUE/address/doc.md

@@ -8,9 +8,9 @@
 
 ``` javascript
 import { createApp } from 'vue';
-// vue
+//vue
 import { Address, Icon, Popup } from '@nutui/nutui';
-// taro
+//taro
 import { Address, Icon, Popup } from '@nutui/nutui-taro';
 
 const app = createApp();
@@ -82,6 +82,66 @@ setup() {
 }
 ```
 
+### 选择自定义地址2
+
+```html
+<nut-cell title="选择地址" :desc="text" type="custom2" is-link @click="showAddress"></nut-cell>
+<nut-address
+    v-model:visible="showPopup"
+    :province="province"
+    :city="city"
+    :country="country"
+    :town="town"
+    @change="onChange"
+    @close="close"
+    custom-address-title="请选择所在地区"
+></nut-address>
+```
+```javascript
+setup() {
+    const showPopup = ref(false);
+    const address = reactive({
+      province:[
+        { id: 1, name: '北京' },
+        { id: 2, name: '广西' },
+        { id: 3, name: '江西' },
+        { id: 4, name: '四川' }
+      ],
+      city:[
+        { id: 7, name: '朝阳区' },
+        { id: 8, name: '崇文区' },
+        { id: 9, name: '昌平区' },
+        { id: 6, name: '石景山区' }
+      ],
+      country:[
+        { id: 3, name: '八里庄街道' },
+        { id: 9, name: '北苑' },
+        { id: 4, name: '常营乡' }
+      ],
+      town:[]
+    })
+
+    const text = ref('请选择地址')
+
+    const showAddress = () => {
+      showPopup.value = !showPopup.value;
+    };
+
+    const onChange = (cal) => {
+      const name = address[cal.next]
+      if (name.value.length < 1) {
+        showPopup.value = false;
+      }
+    };
+    const close = val => {
+      console.log(val);
+      text.value = val.data.addressStr;
+    };
+
+    return { showPopup, text, showAddress, onChange, close, ...toRefs(address) };
+}
+```
+
 ### 选择已有地址
 
 ```html
@@ -364,20 +424,21 @@ setup() {
 | 字段 | 说明 | 类型 | 默认值
 |----- | ----- | ----- | ----- 
 | v-model:visible | 是否打开地址选择 | String | ''
-| type | 地址选择类型 exist/custom | String | 'custom'
+| type | 地址选择类型 exist/custom/custom2 | String | 'custom'
 | province | 省,每个省的对象中,必须有 name 字段 | Array | []
 | city | 市,每个市的对象中,必须有 name 字段 | Array | []
 | country | 县,每个县的对象中,必须有 name 字段 | Array | []
 | town | 乡/镇,每个乡/镇的对象中,必须有 name 字段 | Array | []
+| height | 弹层中内容容器的高度,仅在type="custom2"时有效 | String、Number | '200px'
 | exist-address | 已存在地址列表,每个地址对象中,必传值provinceName、cityName、countyName、townName、addressDetail、selectedAddress(字段解释见下) | Array | []
-| default-icon | 已有地址列表默认图标,type=‘exist’ 时生效 | string | ''
-| selected-icon | 已有地址列表选中图标,type=‘exist’ 时生效 | string | ''
+| default-icon | 已有地址列表默认图标,type=‘exist’ 时生效 | String | ''
+| selected-icon | 已有地址列表选中图标,type=‘exist’ 时生效 | String | ''
 | close-btn-icon | 自定义关闭弹框按钮图标 | string | -
-| back-btn-icon | 自定义地址与已有地址切换时,自定义返回的按钮图标 | string | -
+| back-btn-icon | 自定义地址与已有地址切换时,自定义返回的按钮图标 | String | -
 | is-show-custom-address | 是否可以切换自定义地址选择,type=‘exist’ 时生效 | Boolean | true
-| custom-address-title  | 自定义地址选择文案,type='custom' 时生效 | string | '请选择所在地区'
-| exist-address-title| 已有地址文案 ,type=‘exist’ 时生效| string | '配送至'
-| custom-and-exist-title| 自定义地址与已有地址切换按钮文案 ,type=‘exist’ 时生效| string | '选择其他地址'
+| custom-address-title  | 自定义地址选择文案,type='custom' 时生效 | String | '请选择所在地区'
+| exist-address-title| 已有地址文案 ,type=‘exist’ 时生效| String | '配送至'
+| custom-and-exist-title| 自定义地址与已有地址切换按钮文案 ,type=‘exist’ 时生效| String | '选择其他地址'
 
 
   * provinceName 省的名字
@@ -394,7 +455,7 @@ setup() {
 | selected | 选择已有地址列表时触发 | 参考 selected
 | close | 地址选择弹框关闭时触发 | 参考 close
 | close-mask |点击遮罩层或点击右上角叉号关闭时触发 | {closeWay:'mask'/'cross'}
-| switch-module | 点击‘选择其他地址’或自定义地址选择左上角返回按钮触发 | {type:'exist'/'custom'}
+| switch-module | 点击‘选择其他地址’或自定义地址选择左上角返回按钮触发 | {type:'exist'/'custom'/'custom2'}
 
 
 ## change 回调参数
@@ -414,6 +475,6 @@ setup() {
 ## close 回调参数
 | 参数 | 说明 | 可能值 
 |----- | ----- | ----- 
-| type | 地址选择类型 exist/custom  |  exist/custom
+| type | 地址选择类型 exist/custom/custom2  |  exist/custom/custom2
 | data | 选择地址的值,custom 时,addressStr 为选择的地址组合 | {} 
     

+ 11 - 71
src/packages/__VUE/address/index.scss

@@ -61,42 +61,20 @@
 
     .region-con {
       display: block;
-      margin: 20px 0 0;
-      position: relative;
+      margin: 20px 20px 0;
       .region-group {
+        padding-top: 15px;
         height: 270px;
         overflow-y: auto;
 
         .region-item {
+          display: flex;
+          align-items: center;
+          margin-bottom: 20px;
           font-size: $font-size-1;
           color: #333;
-          &-code {
-            position: relative;
-            height: 35px;
-            line-height: 35px;
-            font-size: $font-size-2;
-            color: $title-color;
-            padding: 0 20px;
-            font-weight: 500;
-            &:after {
-              content: ' ';
-              width: 100%;
-              height: 1px;
-              position: absolute;
-              left: 0;
-              bottom: 0;
-              background-color: $help-color;
-            }
-          }
-          &-name {
-            display: flex;
-            align-items: center;
-            padding: 0 20px;
-            height: 30px;
-            line-height: 30px;
-            &.active {
-              font-weight: bold;
-            }
+          &.active {
+            font-weight: bold;
           }
 
           .region-item-icon {
@@ -104,36 +82,10 @@
           }
         }
       }
-      &-current-code {
-        position: absolute;
-        right: 60px;
-        top: 50%;
-        transform: translateY(-50%);
-        width: 45px;
-        height: 45px;
-        line-height: 45px;
-        border-radius: 50%;
-        background: $white;
-        box-shadow: 0 3px 3px 1px rgba(240, 240, 240, 1);
-        text-align: center;
-      }
-      &-codes-wrapper {
-        position: absolute;
-        right: 8px;
-        top: 50%;
-        transform: translateY(-50%);
-        padding: 15px 0;
-        background-color: #eeeff2;
-        border-radius: 6px;
-        text-align: center;
-        z-index: 10;
-      }
-      &-codes {
-        &-item {
-          padding: 3px;
-          font-size: $font-size-0;
-        }
-      }
+    }
+    .elevator-group {
+      display: flex;
+      margin-top: 20px;
     }
   }
 
@@ -149,7 +101,6 @@
 
       .exist-ul {
         .exist-item {
-          width: 100%;
           display: flex;
           align-items: center;
           margin-bottom: 20px;
@@ -160,19 +111,8 @@
             font-weight: bold;
           }
           .exist-item-icon {
-            width: 15px;
             margin-right: 9px;
           }
-          &-info {
-            flex: 1;
-            &-top {
-              display: flex;
-              justify-content: space-between;
-              margin-bottom: 10px;
-              color: #292929;
-              font-size: 14px;
-            }
-          }
           span {
             display: inline-block;
             flex: 1;

+ 81 - 182
src/packages/__VUE/address/index.taro.vue

@@ -44,6 +44,7 @@
           >
             <view>{{ getTabName(item, index) }}</view>
           </view-block>
+
           <view-block
             class="region-tab-line"
             ref="regionLine"
@@ -51,63 +52,58 @@
           ></view-block>
         </view-block>
 
-        <view-block
-          class="region-con"
-          v-if="regionList[tabName[tabIndex]].length"
-        >
-          <ul class="region-group" ref="listview">
+        <view-block class="region-con">
+          <ul class="region-group">
             <li
+              v-for="(item, index) in regionList[tabName[tabIndex]]"
+              :key="index"
               class="region-item"
-              v-for="item in regionList[tabName[tabIndex]]"
-              :key="item.title"
-              :ref="setListGroup"
+              :class="[
+                selectedRegion[tabName[tabIndex]].id == item.id ? 'active' : ''
+              ]"
+              @click="nextAreaList(item)"
             >
-              <div class="region-item-code">{{ item.title }}</div>
-              <div
-                class="region-item-name"
-                v-for="subitem in item.list"
-                :key="subitem.id"
-                :class="[
-                  selectedRegion[tabName[tabIndex]].id == subitem.id
-                    ? 'active'
-                    : ''
-                ]"
-                @click="nextAreaList(subitem)"
-              >
-                <nut-icon
-                  class="region-item-icon"
-                  type="self"
-                  :name="selectedIcon"
-                  color="#FA2C19"
-                  size="13px"
-                  v-if="selectedRegion[tabName[tabIndex]].id == subitem.id"
-                ></nut-icon>
-                {{ subitem.name }}
-              </div>
+              <nut-icon
+                class="region-item-icon"
+                type="self"
+                :name="selectedIcon"
+                color="#FA2C19"
+                size="13px"
+                v-if="selectedRegion[tabName[tabIndex]].id == item.id"
+              ></nut-icon
+              >{{ item.name }}
             </li>
           </ul>
-          <div class="region-con-current-code" v-show="scrollStart">{{
-            regionList[tabName[tabIndex]][currentIndex].title
-          }}</div>
-          <div
-            class="region-con-codes-wrapper"
-            @touchstart="touchStart"
-            @touchmove.stop.prevent="touchMove"
-            @touchend="touchEnd"
-          >
-            <div class="region-con-codes">
-              <div
-                class="region-con-codes-item"
-                :data-index="index"
-                v-for="(item, index) in regionList[tabName[tabIndex]]"
-                :key="item.title"
-                >{{ item.title }}</div
-              >
-            </div>
-          </div>
         </view-block>
       </view-block>
 
+      <view-block class="custom-address" v-else-if="privateType === 'custom2'">
+        <view class="region-tab">
+          <view
+            class="tab-item"
+            :class="[index == tabIndex ? 'active' : '']"
+            v-for="(item, key, index) in selectedRegion"
+            :key="index"
+            :ref="key"
+            @click="changeRegionTab(item, key, index)"
+          >
+            <view>{{ getTabName(item, index) }}</view>
+          </view>
+          <view
+            class="region-tab-line"
+            ref="regionLine"
+            :style="{ left: lineDistance + 'px' }"
+          ></view>
+        </view>
+        <view class="elevator-group" v-if="showPopup">
+          <nut-elevator
+            :height="height"
+            :index-list="regionList[tabName[tabIndex]]"
+            @click-item="handleElevatorItem"
+          ></nut-elevator>
+        </view>
+      </view-block>
+
       <!-- 配送至 -->
       <view-block class="exist-address" v-else-if="privateType == 'exist'">
         <div class="exist-address-group">
@@ -126,7 +122,6 @@
                 :color="item.selectedAddress ? '#FA2C19' : ''"
                 size="13px"
               ></nut-icon>
-
               <div class="exist-item-info">
                 <div class="exist-item-info-top" v-if="item.name && item.phone">
                   <div class="exist-item-info-name">{{ item.name }}</div>
@@ -160,21 +155,13 @@
   </nut-popup>
 </template>
 <script lang="ts">
-import {
-  reactive,
-  ref,
-  toRefs,
-  watch,
-  nextTick,
-  computed,
-  Ref,
-  onMounted
-} from 'vue';
+import { reactive, ref, toRefs, watch, nextTick, computed } from 'vue';
 import { createComponent } from '../../utils/create';
 import Icon from '../icon/index.taro.vue';
 import Popup from '../popup/index.taro.vue';
 import Taro from '@tarojs/taro';
 import { transformData } from './transformData';
+import Elevator from './../elevator/index.taro.vue';
 
 const { create, componentName } = createComponent('address');
 
@@ -200,6 +187,7 @@ interface AddressList {
   selectedAddress: boolean;
 }
 export default create({
+  children: [Elevator],
   inheritAttrs: false,
   props: {
     visible: {
@@ -265,11 +253,16 @@ export default create({
       // 选择其他地址左上角返回 icon
       type: String,
       default: 'left'
+    },
+    height: {
+      type: [String, Number],
+      default: '200px'
     }
   },
   components: {
     'nut-icon': Icon,
-    'nut-popup': Popup
+    'nut-popup': Popup,
+    'nut-elevator': Elevator
   },
   emits: [
     'update:visible',
@@ -302,11 +295,15 @@ export default create({
     const tabIndex = ref(0);
     const tabName = ref(['province', 'city', 'country', 'town']);
 
+    const isCustom2 = computed(() => props.type === 'custom2');
+
     const regionList = reactive({
-      province: transformData(props.province),
-      city: transformData(props.city),
-      country: transformData(props.country),
-      town: transformData(props.town)
+      province: isCustom2.value
+        ? transformData(props.province)
+        : props.province,
+      city: isCustom2.value ? transformData(props.city) : props.city,
+      country: isCustom2.value ? transformData(props.country) : props.country,
+      town: isCustom2.value ? transformData(props.town) : props.town
     });
 
     const selectedRegion = reactive({
@@ -322,20 +319,6 @@ export default create({
 
     const lineDistance = ref(20);
 
-    const listview = ref(null);
-
-    const scrollState = reactive({
-      anchorIndex: 0,
-      listHeight: [] as number[],
-      listGroup: [] as HTMLLIElement[],
-      touchState: {
-        y1: 0,
-        y2: 0
-      },
-      scrollStart: false,
-      currentIndex: 0
-    });
-
     //获取已选地区列表名称
     const getTabName = (item: RegionData, index: number) => {
       if (item.name) return item.name;
@@ -358,25 +341,13 @@ export default create({
     const clickOverlay = () => {
       closeWay.value = 'mask';
     };
-    //重置滚动参数
-    const resetScrollState = () => {
-      scrollState.anchorIndex = 0;
-      scrollState.listHeight = [];
-      scrollState.listGroup = [];
-      scrollState.currentIndex = 0;
-      scrollState.scrollStart = false;
-      scrollState.touchState = {
-        y1: 0,
-        y2: 0
-      };
-    };
     // 移动下面的红线
     const lineAnimation = () => {
       setTimeout(() => {
         Taro.createSelectorQuery()
           .selectAll(`.${tabName.value[tabIndex.value]}`)
           .boundingClientRect((rects) => {
-            (rects as any).forEach((rect: any) => {
+            (rects as any).forEach((rect) => {
               if (rect.width > 0) lineDistance.value = rect.left;
             });
           })
@@ -400,7 +371,9 @@ export default create({
 
       if (tabIndex.value < 3) {
         tabIndex.value = tabIndex.value + 1;
+
         lineAnimation();
+
         // 切换下一个
         calBack.next = tabName.value[tabIndex.value];
         calBack.value = item as string;
@@ -408,9 +381,6 @@ export default create({
       } else {
         handClose();
       }
-
-      resetScrollState();
-      (listview.value as any).scrollTo(0, 0);
     };
     //切换地区Tab
     const changeRegionTab = (item: RegionData, key: number, index: number) => {
@@ -422,14 +392,13 @@ export default create({
     const selectedExist = (item: RegionData) => {
       const copyExistAdd = props.existAddress as AddressList[];
       let prevExistAdd = {};
-      if (copyExistAdd != null) {
-        copyExistAdd.forEach((list, index) => {
-          if (list && (list as AddressList).selectedAddress) {
-            prevExistAdd = list;
-          }
-          (list as AddressList).selectedAddress = false;
-        });
-      }
+
+      copyExistAdd.forEach((list, index) => {
+        if (list && (list as AddressList).selectedAddress) {
+          prevExistAdd = list;
+        }
+        (list as AddressList).selectedAddress = false;
+      });
 
       item.selectedAddress = true;
 
@@ -463,7 +432,7 @@ export default create({
         type: privateType.value
       };
 
-      if (privateType.value == 'custom') {
+      if (privateType.value == 'custom' || privateType.value == 'custom2') {
         const { province, city, country, town } = resCopy;
 
         resCopy.addressIdStr = [
@@ -506,67 +475,8 @@ export default create({
       emit('switch-module', { type: privateType.value });
     };
 
-    const getData = (el: any, name: string, val?: string) => {
-      const prefix = 'data-';
-      if (val) {
-        return el.setAttribute(prefix + name, val);
-      }
-      return +el.getAttribute(prefix + name);
-    };
-
-    const setListGroup = (el: HTMLLIElement) => {
-      nextTick(() => {
-        if (!scrollState.listGroup.includes(el) && el != null) {
-          scrollState.listGroup.push(el);
-        }
-      });
-    };
-
-    const calculateHeight = () => {
-      let height = 0;
-      scrollState.listHeight.push(height);
-      for (let i = 0; i < scrollState.listGroup.length; i++) {
-        let item = scrollState.listGroup[i];
-        height += item.clientHeight;
-        scrollState.listHeight.push(height);
-      }
-    };
-
-    const scrollTo = (index: number) => {
-      if (!index && index !== 0) {
-        return;
-      }
-      if (!scrollState.listHeight.length) {
-        calculateHeight();
-      }
-      if (index < 0) index = 0;
-      if (index > scrollState.listHeight.length - 2)
-        index = scrollState.listHeight.length - 2;
-      scrollState.currentIndex = index;
-      (listview.value as any).scrollTo(0, scrollState.listHeight[index]);
-    };
-
-    const touchStart = (e: TouchEvent) => {
-      scrollState.scrollStart = true;
-      let index = getData(e.target, 'index');
-      let firstTouch = e.touches[0];
-      scrollState.touchState.y1 = firstTouch.pageY;
-      scrollState.anchorIndex = index;
-      scrollState.currentIndex = index;
-      scrollTo(index);
-    };
-
-    const touchMove = (e: TouchEvent) => {
-      let firstTouch = e.touches[0];
-      scrollState.touchState.y2 = firstTouch.pageY;
-      let delta =
-        ((scrollState.touchState.y2 - scrollState.touchState.y1) / 23) | 0;
-      scrollState.currentIndex = scrollState.anchorIndex + delta;
-      scrollTo(scrollState.currentIndex);
-    };
-
-    const touchEnd = (e: TouchEvent) => {
-      resetScrollState();
+    const handleElevatorItem = (key: string, item: RegionData | string) => {
+      nextAreaList(item);
     };
 
     watch(
@@ -588,31 +498,32 @@ export default create({
     watch(
       () => props.province,
       (value) => {
-        regionList.province = transformData(value);
+        regionList.province = isCustom2.value ? transformData(value) : value;
       }
     );
     watch(
       () => props.city,
       (value) => {
-        regionList.city = transformData(value);
+        regionList.city = isCustom2.value ? transformData(value) : value;
       }
     );
     watch(
       () => props.country,
       (value) => {
-        regionList.country = transformData(value);
+        regionList.country = isCustom2.value ? transformData(value) : value;
       }
     );
     watch(
       () => props.town,
       (value) => {
-        regionList.town = transformData(value);
+        regionList.town = isCustom2.value ? transformData(value) : value;
       }
     );
 
     watch(
       () => props.existAddress,
       (value) => {
+        //  existAddress.value = value;
         value.forEach((item, index) => {
           if ((item as AddressList).selectedAddress) {
             selectedExistAddress = item as {};
@@ -621,13 +532,6 @@ export default create({
       }
     );
 
-    watch(
-      () => props.type,
-      (value) => {
-        privateType.value = value;
-      }
-    );
-
     return {
       classes,
       showPopup,
@@ -648,12 +552,7 @@ export default create({
       selectedExist,
       clickOverlay,
       handClose,
-      touchStart,
-      touchMove,
-      touchEnd,
-      setListGroup,
-      listview,
-      ...toRefs(scrollState),
+      handleElevatorItem,
       ...toRefs(props),
       ...toRefs(tabItemRef)
     };

+ 78 - 169
src/packages/__VUE/address/index.vue

@@ -51,57 +51,56 @@
           ></view>
         </view>
 
-        <view class="region-con" v-if="regionList[tabName[tabIndex]].length">
-          <ul class="region-group" ref="listview">
+        <view class="region-con">
+          <ul class="region-group">
             <li
+              v-for="(item, index) in regionList[tabName[tabIndex]]"
+              :key="index"
               class="region-item"
-              v-for="item in regionList[tabName[tabIndex]]"
-              :key="item.title"
-              :ref="setListGroup"
+              :class="[
+                selectedRegion[tabName[tabIndex]].id == item.id ? 'active' : ''
+              ]"
+              @click="nextAreaList(item)"
             >
-              <div class="region-item-code">{{ item.title }}</div>
-              <div
-                class="region-item-name"
-                v-for="subitem in item.list"
-                :key="subitem.id"
-                :class="[
-                  selectedRegion[tabName[tabIndex]].id == subitem.id
-                    ? 'active'
-                    : ''
-                ]"
-                @click="nextAreaList(subitem)"
-              >
-                <nut-icon
-                  class="region-item-icon"
-                  type="self"
-                  :name="selectedIcon"
-                  color="#FA2C19"
-                  size="13px"
-                  v-if="selectedRegion[tabName[tabIndex]].id == subitem.id"
-                ></nut-icon>
-                {{ subitem.name }}
-              </div>
+              <nut-icon
+                class="region-item-icon"
+                type="self"
+                :name="selectedIcon"
+                color="#FA2C19"
+                size="13px"
+                v-if="selectedRegion[tabName[tabIndex]].id == item.id"
+              ></nut-icon
+              >{{ item.name }}
             </li>
           </ul>
-          <div class="region-con-current-code" v-show="scrollStart">{{
-            regionList[tabName[tabIndex]][currentIndex].title
-          }}</div>
-          <div
-            class="region-con-codes-wrapper"
-            @touchstart="touchStart"
-            @touchmove.stop.prevent="touchMove"
-            @touchend="touchEnd"
+        </view>
+      </view>
+
+      <!-- 请选择 -->
+      <view class="custom-address" v-else-if="privateType == 'custom2'">
+        <view class="region-tab">
+          <view
+            class="tab-item"
+            :class="[index == tabIndex ? 'active' : '']"
+            v-for="(item, key, index) in selectedRegion"
+            :key="index"
+            :ref="key"
+            @click="changeRegionTab(item, key, index)"
           >
-            <div class="region-con-codes">
-              <div
-                class="region-con-codes-item"
-                :data-index="index"
-                v-for="(item, index) in regionList[tabName[tabIndex]]"
-                :key="item.title"
-                >{{ item.title }}</div
-              >
-            </div>
-          </div>
+            <view>{{ getTabName(item, index) }}</view>
+          </view>
+          <view
+            class="region-tab-line"
+            ref="regionLine"
+            :style="{ left: lineDistance + 'px' }"
+          ></view>
+        </view>
+        <view class="elevator-group">
+          <nut-elevator
+            :height="height"
+            :index-list="regionList[tabName[tabIndex]]"
+            @click-item="handleElevatorItem"
+          ></nut-elevator>
         </view>
       </view>
 
@@ -143,7 +142,6 @@
             </li>
           </ul>
         </div>
-
         <div
           class="choose-other"
           @click="switchModule"
@@ -156,10 +154,11 @@
   </nut-popup>
 </template>
 <script lang="ts">
-import { reactive, ref, toRefs, watch, nextTick, Ref, onMounted } from 'vue';
+import { reactive, ref, toRefs, watch, nextTick, computed } from 'vue';
 import { createComponent } from '../../utils/create';
-import { transformData } from './transformData';
 const { componentName, create } = createComponent('address');
+import { transformData } from './transformData';
+import Elevator from './../elevator/index.vue';
 interface RegionData {
   name: string;
   [key: string]: any;
@@ -182,6 +181,7 @@ interface AddressList {
   selectedAddress: boolean;
 }
 export default create({
+  children: [Elevator],
   inheritAttrs: false,
   props: {
     visible: {
@@ -247,6 +247,10 @@ export default create({
       // 选择其他地址左上角返回 icon
       type: String,
       default: 'left'
+    },
+    height: {
+      type: [String, Number],
+      default: '200px'
     }
   },
   emits: [
@@ -259,7 +263,7 @@ export default create({
     'switch-module'
   ],
 
-  setup(props, { emit }) {
+  setup(props: any, { emit }) {
     const regionLine = ref<null | HTMLElement>(null);
 
     const tabItemRef = reactive({
@@ -273,11 +277,15 @@ export default create({
     const tabIndex = ref(0);
     const tabName = ref(['province', 'city', 'country', 'town']);
 
+    const isCustom2 = computed(() => props.type === 'custom2');
+
     const regionList = reactive({
-      province: transformData(props.province),
-      city: transformData(props.city),
-      country: transformData(props.country),
-      town: transformData(props.town)
+      province: isCustom2.value
+        ? transformData(props.province)
+        : props.province,
+      city: isCustom2.value ? transformData(props.city) : props.city,
+      country: isCustom2.value ? transformData(props.country) : props.country,
+      town: isCustom2.value ? transformData(props.town) : props.town
     });
 
     const selectedRegion = reactive({
@@ -293,20 +301,6 @@ export default create({
 
     const lineDistance = ref(20);
 
-    const listview = ref(null);
-
-    const scrollState = reactive({
-      anchorIndex: 0,
-      listHeight: [] as number[],
-      listGroup: [] as HTMLLIElement[],
-      touchState: {
-        y1: 0,
-        y2: 0
-      },
-      scrollStart: false,
-      currentIndex: 0
-    });
-
     //获取已选地区列表名称
     const getTabName = (item: RegionData, index: number) => {
       if (item.name) return item.name;
@@ -329,18 +323,6 @@ export default create({
     const clickOverlay = () => {
       closeWay.value = 'mask';
     };
-    //重置滚动参数
-    const resetScrollState = () => {
-      scrollState.anchorIndex = 0;
-      scrollState.listHeight = [];
-      scrollState.listGroup = [];
-      scrollState.currentIndex = 0;
-      scrollState.scrollStart = false;
-      scrollState.touchState = {
-        y1: 0,
-        y2: 0
-      };
-    };
     // 移动下面的红线
     const lineAnimation = () => {
       const name = (tabItemRef as any)[tabName.value[tabIndex.value]];
@@ -348,6 +330,7 @@ export default create({
         if (name) {
           const distance = name.offsetLeft;
           lineDistance.value = distance;
+          console.log(name);
         }
       });
     };
@@ -378,8 +361,6 @@ export default create({
       } else {
         handClose();
       }
-      resetScrollState();
-      (listview.value as any).scrollTo(0, 0);
     };
     //切换地区Tab
     const changeRegionTab = (item: RegionData, key: number, index: number) => {
@@ -392,14 +373,12 @@ export default create({
       const copyExistAdd = props.existAddress as AddressList[];
       let prevExistAdd = {};
 
-      if (copyExistAdd != null) {
-        copyExistAdd.forEach((list, index) => {
-          if (list && (list as AddressList).selectedAddress) {
-            prevExistAdd = list;
-          }
-          (list as AddressList).selectedAddress = false;
-        });
-      }
+      copyExistAdd.forEach((list, index) => {
+        if (list && (list as AddressList).selectedAddress) {
+          prevExistAdd = list;
+        }
+        (list as AddressList).selectedAddress = false;
+      });
 
       item.selectedAddress = true;
 
@@ -433,7 +412,7 @@ export default create({
         type: privateType.value
       };
 
-      if (privateType.value == 'custom') {
+      if (privateType.value == 'custom' || privateType.value == 'custom2') {
         const { province, city, country, town } = resCopy;
 
         resCopy.addressIdStr = [
@@ -476,67 +455,8 @@ export default create({
       emit('switch-module', { type: privateType.value });
     };
 
-    const getData = (el: any, name: string, val?: string) => {
-      const prefix = 'data-';
-      if (val) {
-        return el.setAttribute(prefix + name, val);
-      }
-      return +el.getAttribute(prefix + name);
-    };
-
-    const setListGroup = (el: HTMLLIElement) => {
-      nextTick(() => {
-        if (!scrollState.listGroup.includes(el) && el != null) {
-          scrollState.listGroup.push(el);
-        }
-      });
-    };
-
-    const calculateHeight = () => {
-      let height = 0;
-      scrollState.listHeight.push(height);
-      for (let i = 0; i < scrollState.listGroup.length; i++) {
-        let item = scrollState.listGroup[i];
-        height += item.clientHeight;
-        scrollState.listHeight.push(height);
-      }
-    };
-
-    const scrollTo = (index: number) => {
-      if (!index && index !== 0) {
-        return;
-      }
-      if (!scrollState.listHeight.length) {
-        calculateHeight();
-      }
-      if (index < 0) index = 0;
-      if (index > scrollState.listHeight.length - 2)
-        index = scrollState.listHeight.length - 2;
-      scrollState.currentIndex = index;
-      (listview.value as any).scrollTo(0, scrollState.listHeight[index]);
-    };
-
-    const touchStart = (e: TouchEvent) => {
-      scrollState.scrollStart = true;
-      let index = getData(e.target, 'index');
-      let firstTouch = e.touches[0];
-      scrollState.touchState.y1 = firstTouch.pageY;
-      scrollState.anchorIndex = index;
-      scrollState.currentIndex = index;
-      scrollTo(index);
-    };
-
-    const touchMove = (e: TouchEvent) => {
-      let firstTouch = e.touches[0];
-      scrollState.touchState.y2 = firstTouch.pageY;
-      let delta =
-        ((scrollState.touchState.y2 - scrollState.touchState.y1) / 23) | 0;
-      scrollState.currentIndex = scrollState.anchorIndex + delta;
-      scrollTo(scrollState.currentIndex);
-    };
-
-    const touchEnd = (e: TouchEvent) => {
-      resetScrollState();
+    const handleElevatorItem = (key: string, item: RegionData | string) => {
+      nextAreaList(item);
     };
 
     watch(
@@ -558,27 +478,28 @@ export default create({
     watch(
       () => props.province,
       (value) => {
-        regionList.province = transformData(value);
+        regionList.province = isCustom2.value ? transformData(value) : value;
       }
     );
     watch(
       () => props.city,
       (value) => {
-        regionList.city = transformData(value);
+        regionList.city = isCustom2.value ? transformData(value) : value;
       }
     );
     watch(
       () => props.country,
       (value) => {
-        regionList.country = transformData(value);
+        regionList.country = isCustom2.value ? transformData(value) : value;
       }
     );
     watch(
       () => props.town,
       (value) => {
-        regionList.town = transformData(value);
+        regionList.town = isCustom2.value ? transformData(value) : value;
       }
     );
+
     watch(
       () => props.existAddress,
       (value) => {
@@ -591,13 +512,6 @@ export default create({
       }
     );
 
-    watch(
-      () => props.type,
-      (value) => {
-        privateType.value = value;
-      }
-    );
-
     return {
       showPopup,
       privateType,
@@ -617,12 +531,7 @@ export default create({
       selectedExist,
       clickOverlay,
       handClose,
-      touchStart,
-      touchMove,
-      touchEnd,
-      setListGroup,
-      listview,
-      ...toRefs(scrollState),
+      handleElevatorItem,
       ...toRefs(props),
       ...toRefs(tabItemRef)
     };
@@ -630,6 +539,6 @@ export default create({
 });
 </script>
 
-<style lang="scss">
+<style lang="scss" scoped>
 @import 'index.scss';
 </style>

+ 7 - 4
src/packages/__VUE/elevator/index.taro.vue

@@ -25,9 +25,12 @@
         >
       </view>
     </scroll-view>
-    <view class="nut-elevator__code--current" v-show="scrollStart">{{
-      indexList[currentIndex][acceptKey]
-    }}</view>
+    <view
+      class="nut-elevator__code--current"
+      v-show="scrollStart"
+      v-if="indexList.length"
+      >{{ indexList[currentIndex][acceptKey] }}</view
+    >
     <view
       class="nut-elevator__bars"
       @touchstart="touchStart"
@@ -188,7 +191,7 @@ export default create({
     };
 
     onMounted(() => {
-      eventCenter.once((getCurrentInstance() as any).router.onReady, () => {
+      Taro.nextTick(() => {
         calculateHeight();
       });
     });

+ 6 - 3
src/packages/__VUE/elevator/index.vue

@@ -23,9 +23,12 @@
         >
       </view>
     </view>
-    <view class="nut-elevator__code--current" v-show="scrollStart">{{
-      indexList[currentIndex][acceptKey]
-    }}</view>
+    <view
+      class="nut-elevator__code--current"
+      v-show="scrollStart"
+      v-if="indexList.length"
+      >{{ indexList[currentIndex][acceptKey] }}</view
+    >
     <view
       class="nut-elevator__bars"
       @touchstart="touchStart"

+ 3 - 3
src/sites/mobile-taro/vue/src/app.ts

@@ -1,8 +1,8 @@
 import { createApp } from 'vue';
 import './app.scss';
-import NutUI from '../../../../packages/nutui.taro.vue';
-// import NutUI from '@nutui/nutui';
-// import '@nutui/nutui/dist/style.css';
+// import NutUI from '../../../../packages/nutui.taro.vue';
+import NutUI from '@nutui/nutui-taro';
+import '@nutui/nutui-taro/dist/style.css';
 const App = createApp({
   onShow(options) {}
   // 入口组件不需要实现 render 方法,即使实现了也会被 taro 所覆盖

+ 2 - 1
src/sites/mobile-taro/vue/src/business/pages/address/index.config.js

@@ -1,3 +1,4 @@
 export default {
-  navigationBarTitleText: 'Address'
+  navigationBarTitleText: 'Address',
+  disableScroll: true
 };

+ 52 - 8
src/sites/mobile-taro/vue/src/business/pages/address/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <view class="demo">
+  <div class="demo">
     <h2>选择自定义地址</h2>
     <nut-cell
       title="选择地址"
@@ -19,6 +19,27 @@
       custom-address-title="请选择所在地区"
     ></nut-address>
 
+    <h2>选择自定义地址2</h2>
+    <nut-cell
+      title="选择地址"
+      :desc="five"
+      is-link
+      @click="showAddress2"
+    ></nut-cell>
+
+    <nut-address
+      v-model:visible="normal2"
+      type="custom2"
+      :province="province"
+      :city="city"
+      :country="country"
+      :town="town"
+      height="270px"
+      @change="(cal) => onChange(cal, 'normal2')"
+      @close="close5"
+      custom-address-title="请选择所在地区"
+    ></nut-address>
+
     <h2>选择已有地址</h2>
     <nut-cell
       title="选择地址"
@@ -83,12 +104,11 @@
       @switch-module="switchModule"
       @close-mask="closeMask"
     ></nut-address>
-  </view>
+  </div>
 </template>
 
 <script lang="ts">
-import { reactive, ref, toRefs } from 'vue';
-
+import { reactive, ref, toRefs, defineComponent } from 'vue';
 interface CalBack {
   next: string;
   value: string;
@@ -119,12 +139,11 @@ interface AddressResult extends AddressList {
   country: RegionData[];
   town: RegionData[];
 }
-export default {
+export default defineComponent({
   props: {},
   setup() {
     const address = reactive({
       province: [
-        { id: 10, name: '安徽' },
         { id: 1, name: '北京' },
         { id: 2, name: '广西' },
         { id: 3, name: '江西' },
@@ -149,6 +168,7 @@ export default {
 
     const showPopup = reactive({
       normal: false,
+      normal2: false,
       exist: false,
       customImg: false,
       other: false
@@ -201,13 +221,18 @@ export default {
       one: '请选择地址',
       two: '请选择地址',
       three: '请选择地址',
-      four: '请选择地址'
+      four: '请选择地址',
+      five: '请选择地址'
     });
 
     const showAddress = () => {
       showPopup.normal = !showPopup.normal;
     };
 
+    const showAddress2 = () => {
+      showPopup.normal2 = !showPopup.normal2;
+    };
+
     const onChange = (cal: CalBack, tag: string) => {
       const name = (address as any)[cal.next];
       if (name.length < 1) {
@@ -219,6 +244,11 @@ export default {
       text.one = val.data.addressStr;
     };
 
+    const close5 = (val: CalResult) => {
+      console.log(val);
+      text.five = val.data.addressStr;
+    };
+
     const showAddressExist = () => {
       showPopup.exist = true;
     };
@@ -288,11 +318,13 @@ export default {
 
     return {
       showAddress,
+      showAddress2,
       showPopup,
       onChange,
       close1,
       showAddressExist,
       close2,
+      close5,
       selected,
       existAddress,
       showAddressOther,
@@ -307,5 +339,17 @@ export default {
       ...toRefs(address)
     };
   }
-};
+});
 </script>
+
+<style lang="scss">
+.demo {
+  .nut-cell {
+    align-items: center;
+
+    .nut-cell__value {
+      margin-right: 8px;
+    }
+  }
+}
+</style>