浏览代码

docs(picker、countdown): add international en-us (#1329)

* feat: datepicker 国际化

* feat: popover 功能补全

* feat: 添加更新版本号

* docs: datepicker 版本号添加

* feat: addresslist/category 组件主题定制修改

* fix: picker问题修改

* feat: picker国际化

* docs: countdown 国际化添加

* docs: countdown 国际化添加
yangxiaolu1993 3 年之前
父节点
当前提交
16d26f29ad

+ 2 - 2
src/packages/__VUE/addresslist/index.scss

@@ -107,10 +107,10 @@
           padding: 0 6px;
           height: 16px;
           line-height: 16px;
-          background: #f2270c;
+          background: $addresslist-contnts-contact-default;
           border-radius: 2px;
           font-size: 12px;
-          color: #fff;
+          color: $addresslist-contnts-contact-color;
         }
       }
       &-handle {

+ 62 - 15
src/packages/__VUE/countdown/demo.vue

@@ -1,33 +1,36 @@
 <template>
   <div class="demo">
-    <h2>基础用法</h2>
+    <h2>{{ translate('basic') }}</h2>
     <nut-cell>
       <nut-countdown :endTime="end" @on-end="onend"></nut-countdown>
     </nut-cell>
-    <h2>自定义格式</h2>
+    <h2>{{ translate('format') }}</h2>
     <nut-cell>
-      <nut-countdown :endTime="end" format="DD 天 HH 时 mm 分 ss 秒" />
+      <nut-countdown
+        :endTime="end"
+        :format="`DD ${translate('day')} HH ${translate('hour')} mm ${translate('minute')} ss ${translate('second')}`"
+      />
     </nut-cell>
 
-    <h2>毫秒级渲染</h2>
+    <h2>{{ translate('millisecond') }}</h2>
 
     <nut-cell>
       <nut-countdown :endTime="end" millisecond format="HH:mm:ss:SS" />
     </nut-cell>
 
-    <h2>以服务端的时间为准</h2>
+    <h2>{{ translate('serverTime') }}</h2>
 
     <nut-cell>
       <nut-countdown :startTime="serverTime" :endTime="end" />
     </nut-cell>
 
-    <h2>异步更新结束时间</h2>
+    <h2>{{ translate('async') }}</h2>
 
     <nut-cell>
       <nut-countdown :endTime="asyncEnd" />
     </nut-cell>
 
-    <h2>控制开始和暂停的倒计时</h2>
+    <h2>{{ translate('controlTime') }}</h2>
 
     <nut-cell>
       <nut-countdown :endTime="end" :paused="paused" @on-paused="onpaused" @on-restart="onrestart" />
@@ -36,13 +39,13 @@
       </div>
     </nut-cell>
 
-    <h2>自定义展示样式</h2>
+    <h2>{{ translate('customStyle') }}</h2>
 
     <nut-cell>
       <span>
         <nut-countdown v-model="resetTime" :endTime="end">
           <div class="countdown-part-box">
-            <div class="part-item-symbol">{{ resetTime.d }}</div>
+            <div class="part-item-symbol">{{ resetTime.d }}{{ translate('day') }}</div>
             <div class="part-item h">{{ resetTime.h }}</div>
             <span class="part-item-symbol">:</span>
             <div class="part-item m">{{ resetTime.m }}</div>
@@ -53,15 +56,21 @@
       </span>
     </nut-cell>
 
-    <h2>手动控制</h2>
+    <h2>{{ translate('handleControl') }}</h2>
     <nut-cell>
       <nut-countdown time="20000" ref="CountDown" :autoStart="false" format="ss:SS" />
     </nut-cell>
 
     <nut-grid :column-num="3">
-      <nut-grid-item><nut-button type="primary" @click="start">开始</nut-button></nut-grid-item>
-      <nut-grid-item><nut-button type="primary" @click="pause">暂停</nut-button></nut-grid-item>
-      <nut-grid-item><nut-button type="primary" @click="reset">重置</nut-button></nut-grid-item>
+      <nut-grid-item
+        ><nut-button type="primary" @click="start">{{ translate('start') }}</nut-button></nut-grid-item
+      >
+      <nut-grid-item
+        ><nut-button type="primary" @click="pause">{{ translate('pause') }}</nut-button></nut-grid-item
+      >
+      <nut-grid-item
+        ><nut-button type="primary" @click="reset">{{ translate('reset') }}</nut-button></nut-grid-item
+      >
     </nut-grid>
   </div>
 </template>
@@ -69,7 +78,44 @@
 <script lang="ts">
 import { toRefs, onMounted, ref, reactive } from 'vue';
 import { createComponent } from '@/packages/utils/create';
-const { createDemo } = createComponent('countdown');
+const { createDemo, translate } = createComponent('countdown');
+import { useTranslate } from '@/sites/assets/util/useTranslate';
+useTranslate({
+  'zh-CN': {
+    basic: '基本用法',
+    format: '自定义格式',
+    millisecond: '毫秒级渲染',
+    serverTime: '以服务端的时间为准',
+    async: '异步更新结束时间',
+    controlTime: '控制开始和暂停的倒计时',
+    customStyle: '自定义展示样式',
+    handleControl: '手动控制',
+    start: '开始',
+    pause: '暂停',
+    reset: '重置',
+    day: '天',
+    hour: '时',
+    minute: '分',
+    second: '秒'
+  },
+  'en-US': {
+    basic: 'Basic Usage',
+    format: 'Custom Format',
+    millisecond: 'Millisecond',
+    serverTime: 'Server Time Prevails',
+    async: 'End-Time of Asyn Update',
+    controlTime: 'Manual Control',
+    customStyle: 'Custom Style',
+    handleControl: 'Handle Control',
+    start: 'Start',
+    pause: 'Pause',
+    reset: 'Reset',
+    day: 'Day',
+    hour: ':',
+    minute: ':',
+    second: ''
+  }
+});
 export default createDemo({
   props: {},
   setup() {
@@ -128,7 +174,8 @@ export default createDemo({
       CountDown,
       start,
       pause,
-      reset
+      reset,
+      translate
     };
   }
 });

+ 347 - 0
src/packages/__VUE/countdown/doc.en-US.md

@@ -0,0 +1,347 @@
+#  CountDown 倒计时
+
+### 介绍
+Used to display the countdown value in real time, and precision supports milliseconds.
+
+### Install
+
+``` javascript
+import { createApp } from 'vue';
+// vue
+import { CountDown } from '@nutui/nutui';
+// taro
+import { CountDown } from '@nutui/nutui-taro';
+
+const app = createApp();
+app.use(CountDown);
+```
+
+### Basic Usage
+
+:::demo
+```html
+<template>
+  <nut-cell>
+    <nut-countdown :end-time="end" ></nut-countdown>
+  </nut-cell>
+</template>
+
+<script>
+  import { ref,reactive,toRefs } from 'vue';
+  export default {
+    setup(props) {
+      const state = reactive({
+        end: Date.now() + 60 * 1000,
+      });
+      return {
+        ...toRefs(state)
+      };
+    }
+  }
+</script>
+
+```
+:::
+
+### 自定义格式
+
+Different countdown display text can be realized by setting the `format` attribute.
+
+:::demo
+```html
+<template>
+  <nut-cell>
+    <nut-countdown :endTime="end" format="DD Day HH : mm : ss" />
+  </nut-cell>
+</template>
+<script>
+  import { ref,reactive,toRefs } from 'vue';
+  export default {
+    setup(props) {
+      const state = reactive({
+        end: Date.now() + 60 * 1000,
+      });
+      return {
+        ...toRefs(state)
+      };
+    }
+  }
+</script>
+```
+:::
+
+### Millisecond
+
+:::demo
+```html
+<template>
+  <nut-cell>
+    <nut-countdown :endTime="end" millisecond format="HH:mm:ss:SS" />
+  </nut-cell>
+</template>
+<script>
+  import { ref,reactive,toRefs } from 'vue';
+  export default {
+    setup(props) {
+      const state = reactive({
+        end: Date.now() + 60 * 1000,
+      });
+      return {
+        ...toRefs(state)
+      };
+    }
+  }
+</script>
+```
+:::
+
+### Server Time Prevails
+
+:::demo
+```html
+<template>
+  <nut-cell>
+    <nut-countdown  :startTime="serverTime" :endTime="end" ></nut-countdown>
+  </nut-cell>
+</template>
+
+<script>
+  import { ref,reactive,toRefs } from 'vue';
+  export default {
+    setup(props) {
+      const state = reactive({
+          serverTime: Date.now() - 20 * 1000,
+          end: Date.now() + 60 * 1000,
+        });
+      return {
+        ...toRefs(state)
+      };
+    }
+  }
+</script>
+```
+:::
+
+### End-Time of Asyn Update
+
+:::demo
+```html
+<template>
+  <nut-cell>
+    <nut-countdown :end-time="asyncEnd" ></nut-countdown>
+  </nut-cell>
+</template>
+
+<script>
+  import { ref,reactive,toRefs } from 'vue';
+  export default {
+    setup(props) {
+      const state = reactive({
+          asyncEnd: 0,
+      });
+      // 模拟异步时间
+      setTimeout(() => {
+        state.asyncEnd = Date.now() + 30 * 1000;
+      }, 3000);
+      return {
+        ...toRefs(state)
+      };
+    }
+  }
+</script>
+```
+:::
+
+### Manual Control
+
+Paused and restarted the countdown with the paused attribute
+
+:::demo
+```html
+<template>
+  <nut-cell>
+      <nut-countdown  :endTime="end" :paused="paused" @on-paused="onpaused" @on-restart="onrestart" />
+      <div style="position:absolute;right:10px;top:9px">
+          <nut-button type="primary" size='small' @click="toggle">{{ paused ? 'start' : 'stop' }}</nut-button>
+      </div>
+  </nut-cell>
+</template>
+<script>
+  import { ref,reactive,toRefs } from 'vue';
+  export default {
+    setup(props) {
+      const state = reactive({
+        paused: false,
+        end: Date.now() + 60 * 1000,
+      });
+
+      const toggle = ()=> {
+        state.paused = !state.paused;
+      }
+      const onpaused = (v)=> {
+        console.log('paused: ', v);
+      }
+      const onrestart = (v)=> {
+        console.log('restart: ', v);
+      }
+      return {
+          toggle,
+          onpaused,
+          onrestart,
+        ...toRefs(state)
+      };
+    }
+  }
+</script>
+
+```
+:::
+
+### Custom Style
+
+:::demo
+```html
+<template>
+  <nut-cell>
+      <nut-countdown v-model="resetTime" :endTime="end">
+          <div class="countdown-part-box">
+              <div class="part-item-symbol">{{ resetTime.d }}Day</div>
+            <div class="part-item h">{{ resetTime.h }}</div>
+            <span class="part-item-symbol">:</span>
+            <div class="part-item m">{{ resetTime.m }}</div>
+            <span class="part-item-symbol">:</span>
+            <div class="part-item s">{{ resetTime.s }}</div>
+          </div>
+      </nut-countdown>
+  </nut-cell>
+</template>
+<script>
+  import { ref,reactive,toRefs } from 'vue';
+  export default {
+    setup(props) {
+      const state = reactive({
+          end: Date.now() + 60 * 1000,
+          resetTime: {
+            d: '1',
+            h: '00',
+            m: '00',
+            s: '00'
+          }
+        });
+      return {
+        ...toRefs(state)
+      };
+    }
+  }
+</script>
+<style lang="scss" scoped>
+.countdown-part-box {
+  display: flex;
+  align-items: center;
+
+  .part-item {
+    flex-shrink: 0;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: 20px;
+    height: 25px;
+    background: #e8220e;
+    color: #fff;
+    font-size: 14px;
+    border-radius: 6px;
+  }
+
+  .part-item-symbol {
+    margin: 0 5px;
+  }
+}
+</style>
+
+```
+:::
+
+### Handle Control
+
+:::demo
+```html
+<template>
+  <nut-cell>
+      <nut-countdown time="20000" ref="CountDown" :autoStart="false" format="ss:SS"/>
+  </nut-cell>
+  <nut-grid :column-num="3">
+    <nut-grid-item><nut-button type="primary" @click="start">Start</nut-button></nut-grid-item>
+    <nut-grid-item><nut-button type="primary" @click="pause">Pause</nut-button></nut-grid-item>
+    <nut-grid-item><nut-button type="primary" @click="reset">Reset</nut-button></nut-grid-item>
+  </nut-grid>
+</template>
+<script>
+  import { ref,reactive,toRefs } from 'vue';
+  export default {
+    setup(props) {
+      const CountDown = ref(null);
+      const start = () => {
+        CountDown.value.start();
+      };
+      const pause = () => {
+        CountDown.value.pause();
+      };
+      const reset = () => {
+        CountDown.value.reset();
+      };
+      return {
+          toggle,
+          onpaused,
+          onrestart,
+        ...toRefs(state)
+      };
+    }
+  }
+</script>
+
+```
+:::
+### API
+
+### Props
+
+| Attribute | Description | Type | Default
+| ----- | ----- | ----- | -----
+| v-model | Current Time | Object | {}
+| start-time | Start Time | String, Number | Date.now()
+| end-time | End Time | String, Number | Date.now()
+| format `v3.1.20` |  Format Time | String | HH:mm:ss
+| millisecond `v3.1.20` |  Whether to enable millisecond render | Boolean | false
+| auto-start `v3.1.20` |  Whether to auto start count down | Boolean | true
+| time `v3.1.20` | Total time, unit milliseconds | String,Number | 0
+| paused | Paused | Boolean | false
+| show-days | Show Text Day `v3.1.20(Abandon)` | Boolean | false
+| show-plain-text | Show Text `v3.1.20(Abandon)` | Boolean | false
+
+### Format
+
+| Name | Description | 
+| ----- | ----- | 
+| DD | Day | 
+| HH | Hour | 
+| mm | Minute | 
+| ss | Second | 
+| S | Millisecond, 1-digit | 
+| SS | Millisecond, 2-digits | 
+| SSS | Millisecond, 3-digits | 
+
+### Event
+
+| Event | Description | Arguments
+| ----- | ----- | ----- 
+| on-end | Emitted when count down end | Residual Timestamp
+| on-paused | Emitted when count down paused | Residual Timestamp
+| on-restart | Emitted when count down restart | Residual Timestamp
+
+### Ref
+
+| Name | Description |
+| ----- | ----- | 
+| start | Count Down Start | 
+| pause | Count Down Pause | 
+| reset | Count Down Reset | 

+ 67 - 62
src/packages/__VUE/picker/demo.vue

@@ -1,8 +1,8 @@
 <template>
   <div class="demo">
-    <h2>基础用法</h2>
+    <h2>{{ translate('basic') }}</h2>
     <nut-cell
-      title="请选择城市"
+      :title="translate('chooseCity')"
       :desc="index"
       @click="
         () => {
@@ -13,14 +13,14 @@
     <nut-picker
       v-model:visible="show"
       :columns="columns"
-      title="城市选择"
+      :title="translate('chooseCity')"
       @change="change"
       @confirm="(options) => confirm('index', options)"
     ></nut-picker>
 
-    <h2>默认选中项</h2>
+    <h2>{{ translate('defaultSelected') }}</h2>
     <nut-cell
-      title="请选择城市"
+      :title="translate('chooseCity')"
       :desc="defult"
       @click="
         () => {
@@ -32,14 +32,14 @@
       v-model="selectedValue"
       v-model:visible="showDefult"
       :columns="columns"
-      title="城市选择"
+      :title="translate('chooseCity')"
       @confirm="(options) => confirm('defult', options)"
     >
     </nut-picker>
 
-    <h2>多列样式</h2>
+    <h2>{{ translate('multipleColumns') }}</h2>
     <nut-cell
-      title="请选择时间"
+      :title="translate('chooseTime')"
       :desc="multiple"
       @click="
         () => {
@@ -50,14 +50,14 @@
     <nut-picker
       v-model:visible="showMultiple"
       :columns="multipleColumns"
-      title="城市选择"
+      :title="translate('chooseCity')"
       @confirm="(options) => confirm('multiple', options)"
     >
     </nut-picker>
 
-    <h2>多级联动</h2>
+    <h2>{{ translate('cascade') }}</h2>
     <nut-cell
-      title="请选择地址"
+      :title="translate('chooseCity')"
       :desc="cascader"
       @click="
         () => {
@@ -68,13 +68,13 @@
     <nut-picker
       v-model:visible="showCascader"
       :columns="cascaderColumns"
-      title="城市选择"
+      :title="translate('chooseCity')"
       @confirm="(options) => confirm('cascader', options)"
     ></nut-picker>
 
-    <h2>异步获取</h2>
+    <h2>{{ translate('async') }}</h2>
     <nut-cell
-      title="请选择地址"
+      :title="translate('chooseCity')"
       :desc="async"
       @click="
         () => {
@@ -86,13 +86,13 @@
       v-model="asyncValue"
       v-model:visible="showAsync"
       :columns="asyncColumns"
-      title="城市选择"
+      :title="translate('chooseCity')"
       @confirm="(options) => confirm('async', options)"
     ></nut-picker>
 
-    <h2>自定义按钮</h2>
+    <h2>{{ translate('custom') }}</h2>
     <nut-cell
-      title="请选择有效日期"
+      :title="translate('validTime')"
       :desc="effect"
       @click="
         () => {
@@ -103,89 +103,92 @@
     <nut-picker
       v-model:visible="showEffect"
       :columns="effectColumns"
-      title="日期选择"
+      :title="translate('chooseDate')"
       @confirm="(options) => confirm('effect', options)"
     >
-      <nut-button block type="primary" @click="alwaysFun">永远有效</nut-button></nut-picker
+      <nut-button block type="primary" @click="alwaysFun">{{ translate('always') }}</nut-button></nut-picker
     >
   </div>
 </template>
 <script lang="ts">
-import { toRefs, ref, onMounted, reactive } from 'vue';
+import { toRefs, ref, onMounted, reactive, computed } from 'vue';
 import { createComponent } from '@/packages/utils/create';
 import { PickerOption } from './types';
-const { createDemo } = createComponent('picker');
+const { createDemo, translate } = createComponent('picker');
+import { useTranslate } from '@/sites/assets/util/useTranslate';
+import { Internation } from './doc.en';
+useTranslate(Internation);
 export default createDemo({
   props: {},
   setup() {
     const selectedValue = ref(['ZheJiang']);
     const asyncValue = ref<string[]>([]);
-    const columns = ref([
-      { text: '南京市', value: 'NanJing' },
-      { text: '无锡市', value: 'WuXi' },
-      { text: '海北藏族自治区', value: 'ZangZu' },
-      { text: '北京市', value: 'BeiJing' },
-      { text: '连云港市', value: 'LianYunGang' },
-      { text: '浙江市', value: 'ZheJiang' },
-      { text: '江苏市', value: 'JiangSu' }
+    const columns = computed(() => [
+      { text: translate('nanJing'), value: 'NanJing' },
+      { text: translate('wuXi'), value: 'WuXi' },
+      { text: translate('zangZu'), value: 'ZangZu' },
+      { text: translate('beiJing'), value: 'BeiJing' },
+      { text: translate('lianYunGang'), value: 'LianYunGang' },
+      { text: translate('zheJiang'), value: 'ZheJiang' },
+      { text: translate('jiangSu'), value: 'JiangSu' }
     ]);
 
-    const multipleColumns = ref([
+    const multipleColumns = computed(() => [
       [
-        { text: '周一', value: 'Monday' },
-        { text: '周二', value: 'Tuesday' },
-        { text: '周三', value: 'Wednesday' },
-        { text: '周四', value: 'Thursday' },
-        { text: '周五', value: 'Friday' }
+        { text: translate('monday'), value: 'Monday' },
+        { text: translate('tuesday'), value: 'Tuesday' },
+        { text: translate('wednesday'), value: 'Wednesday' },
+        { text: translate('thursday'), value: 'Thursday' },
+        { text: translate('friday'), value: 'Friday' }
       ],
       [
-        { text: '上午', value: 'Morning' },
-        { text: '下午', value: 'Afternoon' },
-        { text: '晚上', value: 'Evening' }
+        { text: translate('monday'), value: 'Morning' },
+        { text: translate('afternoon'), value: 'Afternoon' },
+        { text: translate('evening'), value: 'Evening' }
       ]
     ]);
 
-    const cascaderColumns = ref([
+    const cascaderColumns = computed(() => [
       {
-        text: '浙江',
+        text: translate('zheJiang'),
         value: 'ZheJiang',
         children: [
           {
-            text: '杭州',
+            text: translate('hangZhou'),
             value: 'HangZhou',
             children: [
-              { text: '西湖区', value: 'XiHu' },
-              { text: '余杭区', value: 'YuHang' }
+              { text: translate('xiHu'), value: 'XiHu' },
+              { text: translate('yuHang'), value: 'YuHang' }
             ]
           },
           {
-            text: '温州',
+            text: translate('wenZhou'),
             value: 'WenZhou',
             children: [
-              { text: '鹿城区', value: 'LuCheng' },
-              { text: '瓯海区', value: 'OuHai' }
+              { text: translate('luCheng'), value: 'LuCheng' },
+              { text: translate('ouHai'), value: 'OuHai' }
             ]
           }
         ]
       },
       {
-        text: '福建',
+        text: translate('fuJian'),
         value: 'FuJian',
         children: [
           {
-            text: '福州',
+            text: translate('fuZhou'),
             value: 'FuZhou',
             children: [
-              { text: '鼓楼区', value: 'GuLou' },
-              { text: '台江区', value: 'TaiJiang' }
+              { text: translate('guLou'), value: 'GuLou' },
+              { text: translate('taiJiang'), value: 'TaiJiang' }
             ]
           },
           {
-            text: '厦门',
+            text: translate('xiaMen'),
             value: 'XiaMen',
             children: [
-              { text: '思明区', value: 'SiMing' },
-              { text: '海沧区', value: 'HaiCang' }
+              { text: translate('siMing'), value: 'SiMing' },
+              { text: translate('haiCang'), value: 'HaiCang' }
             ]
           }
         ]
@@ -247,15 +250,16 @@ export default createDemo({
     };
 
     onMounted(() => {
+      console.log('monted', multipleColumns.value);
       setTimeout(() => {
         asyncColumns.value = [
-          { text: '南京市', value: 'NanJing' },
-          { text: '无锡市', value: 'WuXi' },
-          { text: '海北藏族自治区', value: 'ZangZu' },
-          { text: '北京市', value: 'BeiJing' },
-          { text: '连云港市', value: 'LianYunGang' },
-          { text: '浙江市', value: 'ZheJiang' },
-          { text: '江苏市', value: 'JiangSu' }
+          { text: translate('nanJing'), value: 'NanJing' },
+          { text: translate('wuXi'), value: 'WuXi' },
+          { text: translate('zangZu'), value: 'ZangZu' },
+          { text: translate('beiJing'), value: 'BeiJing' },
+          { text: translate('lianYunGang'), value: 'LianYunGang' },
+          { text: translate('zheJiang'), value: 'ZheJiang' },
+          { text: translate('jiangSu'), value: 'JiangSu' }
         ];
 
         asyncValue.value = ['ZangZu'];
@@ -271,7 +275,7 @@ export default createDemo({
 
     const alwaysFun = () => {
       showEffect.value = false;
-      desc.effect = '永远有效';
+      desc.effect = translate('always');
     };
     return {
       selectedValue,
@@ -291,7 +295,8 @@ export default createDemo({
       asyncColumns,
       effectColumns,
       showEffect,
-      alwaysFun
+      alwaysFun,
+      translate
     };
   }
 });

+ 407 - 0
src/packages/__VUE/picker/doc.en-US.md

@@ -0,0 +1,407 @@
+# Picker
+
+### 介绍
+
+The picker component is usually used with Popup Component.
+
+### Install
+
+```javascript
+import { createApp } from 'vue';
+// vue
+import { Picker, Popup, OverLay } from '@nutui/nutui';
+// taro
+import { Picker, Popup, OverLay } from '@nutui/nutui-taro';
+
+const app = createApp();
+app.use(Picker);
+app.use(Popup);
+app.use(OverLay);
+```
+
+### Basic Usage
+
+:::demo
+
+```html
+<template>
+  <nut-cell title="Choose City" :desc="desc" @click="()=>{show=true}"></nut-cell>
+  <nut-picker
+    v-model:visible="show"
+    :columns="columns"
+    title="Choose City"
+    @change="change"
+    @confirm="confirm"
+  >
+  </nut-picker>
+</template>
+<script>
+  import { ref } from 'vue';
+  export default {
+    setup(props) {
+      const show = ref(false);
+      const desc = ref('');
+      const columns = ref([
+        { text: 'NanJing', value: 'NanJing' },
+        { text: 'WuXi', value: 'WuXi' },
+        { text: 'ZangZu', value: 'ZangZu' },
+        { text: 'BeiJing', value: 'BeiJing' },
+        { text: 'LianYunGang', value: 'LianYunGang' },
+        { text: 'ZheJiang', value: 'ZheJiang' },
+        { text: 'JiangSu', value: 'JiangSu' }
+      ]);
+    
+      const confirm = ( { selectedValue,selectedOptions })=>{
+        desc.value = selectedValue.join(',');
+      }
+      const change = ({ selectedValue,selectedOptions }) => {
+        console.log(selectedValue);
+      };
+
+      return {show,desc,columns,change, confirm};
+    }
+  };
+</script>
+```
+
+:::
+
+### Default Index
+
+The default selection is implemented by setting `modelValue`, which is an array of values for each configuration。
+
+:::demo
+
+```html
+<template>
+  <nut-cell title="Choose City" :desc="desc" @click="() => { show = true;}"></nut-cell>
+  <nut-picker
+    v-model="selectedValue"
+    v-model:visible="show"
+    :columns="columns"
+    title="Choose City"
+    @confirm="confirm"
+  >
+  </nut-picker>
+</template>
+<script>
+  import { ref } from 'vue';
+  export default {
+    setup(props) {
+      const show = ref(false);
+      const desc = ref('');
+      const selectedValue = ref(['ZheJiang']);
+      const columns = ref([
+        { text: 'NanJing', value: 'NanJing' },
+        { text: 'WuXi', value: 'WuXi' },
+        { text: 'ZangZu', value: 'ZangZu' },
+        { text: 'BeiJing', value: 'BeiJing' },
+        { text: 'LianYunGang', value: 'LianYunGang' },
+        { text: 'ZheJiang', value: 'ZheJiang' },
+        { text: 'JiangSu', value: 'JiangSu' }
+      ]);
+    
+      const confirm = ( { selectedValue,selectedOptions })=>{
+        desc.value = selectedValue.join(',');
+      }
+
+      return {show,desc,columns,selectedValue, confirm};
+    }
+  };
+</script>
+```
+
+:::
+
+### Multiple Columns
+
+:::demo
+
+```html
+<template>
+  <nut-cell title="Choose City" :desc="desc" @click="()=>{show=true}"></nut-cell>
+    <nut-picker
+      v-model:visible="show"
+      :columns="multipleColumns"
+      title="Choose City"
+      @confirm="confirm"
+      @change="change"
+    >
+    </nut-picker>
+</template>
+<script>
+  import { ref } from 'vue';
+  export default {
+    setup(props) {
+      const show = ref(false);
+      const desc = ref('');
+      const multipleColumns = ref([
+        // 第一列
+        [
+          { text: 'Monday', value: 'Monday' },
+          { text: 'Tuesday', value: 'Tuesday' },
+          { text: 'Wednesday', value: 'Wednesday' },
+          { text: 'Thursday', value: 'Thursday' },
+          { text: 'Friday', value: 'Friday' }
+        ],
+        // 第二列
+        [
+          { text: 'Morning', value: 'Morning' },
+          { text: 'Afternoon', value: 'Afternoon' },
+          { text: 'Evening', value: 'Evening' }
+        ]
+      ]);
+    
+      const confirm = ( { selectedValue,selectedOptions })=>{
+        desc.value = selectedValue.join(',');
+      }
+      const change = ({ selectedValue,selectedOptions }) => {
+        console.log(selectedValue);
+      };
+
+      return {show,desc,columns,change, confirm};
+    }
+  };
+</script>
+```
+
+:::
+
+### Cascade
+
+Use the children field of the Columns attribute to cascade options
+
+:::demo
+
+```html
+<template>
+  <nut-cell title="Choose City" :desc="desc" @click="()=>{show=true}"></nut-cell>
+  <nut-picker
+    v-model:visible="show"
+    :columns="cascaderColumns"
+    title="Choose City"
+    @confirm="confirm"
+    @change="change"
+  ></nut-picker>
+</template>
+<script>
+  import { ref } from 'vue';
+  export default {
+    setup(props) {
+      const show = ref(false);
+      const desc = ref('');
+      const cascaderColumns = ref([
+        {
+          text: 'ZheJiang',
+          value: 'ZheJiang',
+          children: [
+            {
+              text: 'HangZhou',
+              value: 'HangZhou',
+              children: [
+                { text: 'XiHu', value: 'XiHu' },
+                { text: 'YuHang', value: 'YuHang' }
+              ]
+            },
+            {
+              text: 'WenZhou',
+              value: 'WenZhou',
+              children: [
+                { text: 'LuCheng', value: 'LuCheng' },
+                { text: 'OuHai', value: 'OuHai' }
+              ]
+            }
+          ]
+        },
+        {
+          text: 'FuJian',
+          value: 'FuJian',
+          children: [
+            {
+              text: 'FuZhou',
+              value: 'FuZhou',
+              children: [
+                { text: 'GuLou', value: 'GuLou' },
+                { text: 'TaiJiang', value: 'TaiJiang' }
+              ]
+            },
+            {
+              text: 'XiaMen',
+              value: 'XiaMen',
+              children: [
+                { text: 'SiMing', value: 'SiMing' },
+                { text: 'HaiCang', value: 'HaiCang' }
+              ]
+            }
+          ]
+        }
+      ]);
+    
+      const confirm = ( { selectedValue,selectedOptions })=>{
+        desc.value = selectedValue.join(',');
+      }
+      const change = ({ selectedValue,selectedOptions }) => {
+        console.log(selectedValue);
+      };
+
+      return {show,desc,cascaderColumns,change, confirm};
+    }
+  };
+</script>
+```
+
+:::
+
+### Async
+
+:::demo
+
+```html
+<template>
+  <nut-cell title="Choose City" :desc="desc" @click="()=>{show=true}"></nut-cell>
+  <nut-picker
+    v-model="asyncValue"
+    v-model:visible="show"
+    :columns="asyncColumns"
+    title="Choose City"
+    @confirm="confirm"
+  ></nut-picker>
+</template>
+<script>
+  import { ref, onMounted } from 'vue';
+  export default {
+    setup(props) {
+      const show = ref(false);
+      const desc = ref('');
+      const asyncColumns = ref([]);
+      const asyncValue = ref<string[]>([]);
+
+      onMounted(() => {
+        // 用于模拟接口请求
+        setTimeout(() => {
+          asyncColumns.value = [
+            { text: 'NanJing', value: 'NanJing' },
+            { text: 'WuXi', value: 'WuXi' },
+            { text: 'ZangZu', value: 'ZangZu' },
+            { text: 'BeiJing', value: 'BeiJing' },
+            { text: 'LianYunGang', value: 'LianYunGang' },
+            { text: 'ZheJiang', value: 'ZheJiang' },
+            { text: 'JiangSu', value: 'JiangSu' }
+          ];
+
+          asyncValue.value = ['ZangZu'];
+        }, 500);
+      });
+      
+      const confirm = ( { selectedValue,selectedOptions })=>{
+        desc.value = selectedValue.join(',');
+      }
+
+      return {show,desc,asyncColumns,asyncValue, confirm};
+    }
+  };
+</script>
+```
+
+:::
+
+### Slots
+
+Slots are arranged at the bottom and top respectively for custom Settings
+
+:::demo
+
+```html
+<template>
+  <nut-cell title="Valid Time" :desc="desc" @click="()=>{show=true}"></nut-cell>
+  <nut-picker
+    v-model:visible="show"
+    :columns="asyncColumns"
+    title="Choose Date"
+    @confirm="confirm"
+  >
+   <nut-button block  @click="alwaysFun">Always</nut-button>
+  </nut-picker>
+</template>
+<script>
+  import { ref, onMounted } from 'vue';
+  export default {
+    setup(props) {
+      const show = ref(false);
+      const desc = ref('');
+      const effectColumns = ref([]);
+
+      onMounted(() => {
+        // 用于模拟接口请求
+        setTimeout(() => {
+          effectColumns.value = [
+            { text: '2022-01', value: 'January' },
+            { text: '2022-02', value: 'February' },
+            { text: '2022-03', value: 'March' },
+            { text: '2022-04', value: 'April' },
+            { text: '2022-05', value: 'May' },
+            { text: '2022-06', value: 'June' },
+            { text: '2022-07', value: 'July' },
+            { text: '2022-08', value: 'August' },
+            { text: '2022-09', value: 'September' },
+            { text: '2022-10', value: 'October' },
+            { text: '2022-11', value: 'November' },
+            { text: '2022-12', value: 'December' }
+          ];
+
+        }, 500);
+      });
+      
+      const confirm = ( { selectedValue,selectedOptions })=>{
+        desc.value = selectedValue.join(',');
+      }
+
+      const alwaysFun = () => {
+        showEffect.value = false;
+        desc.effect = 'Always';
+      };
+
+      return {show,desc,alwaysFun,effectColumns, confirm};
+    }
+  };
+</script>
+```
+
+:::
+
+## API
+
+### Props
+
+| Attribute         | Description                             | Type   | Default           |
+|--------------|----------------------------------|--------|------------------|
+| v-model:value         | Default Index               | Array | []              |
+| v-model:visible          | Is Show               | Boolean | -                |
+| columns         | Columns data              | Array | -                |
+| title                  | Toolbar title                   | String  | -      |
+| cancel-text            | Text of cancel button               | String  | cancel   |
+| ok-text                | Text of confirm button               | String  | confirm   |
+
+### Data Structure of Columns
+
+| Attribute         | Description                             | Type   | Default           |
+|--------------|----------------------------------|--------|------------------|
+| text        | Text of column              | String|Number |               |
+| value          | Value of column               | String|Number |            |
+| children         | Cascader Option              | Array | -                |
+| className                  | Extra CalssName                   | String  |      |
+
+### Events
+
+| Event | Description           | Arguments     |
+|--------|----------------|--------------|
+| confirm  | Emitted when click confirm button. | { selectedValue, selectedOptions } |
+| close  | Emitted when click close button. | { selectedValue, selectedOptions } |
+| change  | Emitted when current option changed. | { columnIndex, selectedValue, selectedOptions } |
+
+### Slots
+
+| Event | Description           |
+|--------|----------------|
+| default  | Custom content bottom columns |
+| top  | Custom content top columns |

+ 82 - 0
src/packages/__VUE/picker/doc.en.ts

@@ -0,0 +1,82 @@
+export const Internation = {
+  'zh-CN': {
+    basic: '基本用法',
+    chooseCity: '请选择城市',
+    defaultSelected: '默认选中项',
+    multipleColumns: '多列样式',
+    chooseTime: '请选择时间',
+    cascade: '多级联动',
+    async: '异步获取',
+    custom: '自定义按钮',
+    validTime: '请选择有效日期',
+    chooseDate: '选择日期',
+    always: '永远有效',
+    monday: '周一',
+    tuesday: '周二',
+    wednesday: '周三',
+    thursday: '周四',
+    friday: '周五',
+    morning: '上午',
+    afternoon: '下午',
+    evening: '晚上',
+    nanJing: '南京市',
+    wuXi: '无锡市',
+    zangZu: '海北藏族自治区',
+    beiJing: '北京市',
+    lianYunGang: '连云港市',
+    zheJiang: '浙江市',
+    jiangSu: '江苏市',
+    hangZhou: '杭州',
+    xiHu: '西湖区',
+    yuHang: '余杭区',
+    wenZhou: '温州',
+    luCheng: '鹿城区',
+    ouHai: '瓯海区',
+    fuJian: '福建',
+    fuZhou: '福州',
+    guLou: '鼓楼区',
+    taiJiang: '台江区',
+    siMing: '思明区',
+    haiCang: '海沧区'
+  },
+  'en-US': {
+    basic: 'Basic Usage',
+    chooseCity: 'Choose City',
+    defaultSelected: 'Default Index',
+    multipleColumns: 'Multiple Columns',
+    chooseTime: 'Choose Time',
+    cascade: 'Cascade',
+    async: 'Async',
+    custom: 'Slots',
+    validTime: 'Valid Time',
+    chooseDate: 'Choose Date',
+    always: 'Always',
+    monday: 'Monday',
+    tuesday: 'Tuesday',
+    wednesday: 'Wednesday',
+    thursday: 'Thursday',
+    friday: 'Friday',
+    morning: 'Morning',
+    afternoon: 'Afternoon',
+    evening: 'Evening',
+    nanJing: 'NanJing',
+    wuXi: 'WuXi',
+    zangZu: 'ZangZu',
+    beiJing: 'BeiJing',
+    lianYunGang: 'LianYunGang',
+    zheJiang: 'ZheJiang',
+    jiangSu: 'JiangSu',
+    hangZhou: 'HangZhou',
+    xiHu: 'XiHu',
+    yuHang: 'YuHang',
+    wenZhou: 'WenZhou',
+    luCheng: 'LuCheng',
+    ouHai: 'OuHai',
+    fuJian: 'FuJian',
+    fuZhou: 'FuZhou',
+    guLou: 'GuLou',
+    taiJiang: 'TaiJiang',
+    siMing: 'SiMing',
+    haiCang: 'HaiCang'
+  }
+};

+ 4 - 3
src/packages/__VUE/picker/doc.md

@@ -13,20 +13,21 @@ Picker 组件在 3.1.18 版本进行重构,调整了之前 API 设计不合理
 * 重新定义 `columns` 属性的数据格式,是由对象构成的一维或多维数组
 * 重新定义 `confirm`、`close`、`change` 事件的回调参数
 
-同时也对重构前的 Picker 组件进行了保留,如有需要可通过 [OldPicker 组件](https://nutui.jd.com/#/oldpicker) 进行查看。
+同时也对重构前的 Picker 组件进行了保留,如有需要可通过 [OldPicker 组件](https://nutui.jd.com/#/component/oldpicker) 进行查看。
 
 ### 安装
 
 ```javascript
 import { createApp } from 'vue';
 // vue
-import { Picker, Popup } from '@nutui/nutui';
+import { Picker, Popup, OverLay } from '@nutui/nutui';
 // taro
-import { Picker, Popup } from '@nutui/nutui-taro';
+import { Picker, Popup, OverLay } from '@nutui/nutui-taro';
 
 const app = createApp();
 app.use(Picker);
 app.use(Popup);
+app.use(OverLay);
 ```
 
 ### 基础用法

+ 2 - 1
src/packages/__VUE/picker/index.taro.vue

@@ -175,7 +175,7 @@ export default create({
             cursor = cursor.children[0];
           }
         } else {
-          defaultValues.value[columnIndex] = option.value ? option.value : '';
+          defaultValues.value[columnIndex] = option.hasOwnProperty('value') ? option.value : '';
         }
 
         emit('change', {
@@ -195,6 +195,7 @@ export default create({
     };
 
     onMounted(() => {
+      console.log('更新');
       if (props.visible) state.show = props.visible;
     });
 

+ 4 - 1
src/packages/__VUE/picker/index.vue

@@ -139,6 +139,7 @@ export default create({
       }
     });
 
+    // 级联数据格式化
     const formatCascade = (columns: import('./types').PickerOption[], defaultValues: (number | string)[]) => {
       const formatted: import('./types').PickerOption[][] = [];
       let cursor: import('./types').PickerOption = {
@@ -180,7 +181,7 @@ export default create({
             cursor = cursor.children[0];
           }
         } else {
-          defaultValues.value[columnIndex] = option.value ? option.value : '';
+          defaultValues.value[columnIndex] = option.hasOwnProperty('value') ? option.value : '';
         }
 
         emit('change', {
@@ -200,6 +201,7 @@ export default create({
     };
 
     onMounted(() => {
+      console.log(11, props.columns);
       if (props.visible) state.show = props.visible;
     });
 
@@ -232,6 +234,7 @@ export default create({
     watch(
       () => props.visible,
       (val) => {
+        console.log('props更新', props.columns);
         state.show = val;
       }
     );

+ 6 - 2
src/packages/styles/variables-jdb.scss

@@ -825,12 +825,16 @@ $list-item-margin: 0 0 10px 0 !default;
 //Ecard
 $ecard-bg-color: #f0f2f5 !default;
 
+//addresslist
+$addresslist-contnts-contact-default: $primary-color !default;
+$addresslist-contnts-contact-color: $white !default;
+
 //category
 $category-bg-color: rgba(255, 255, 255, 1) !default;
 $category-ListLeft-bg-color: rgba(246, 247, 249, 1) !default;
-$category-ListItem-color: rgba(51, 51, 51, 1) !default;
+$category-ListItem-color: $title-color !default;
 $category-ListItemChecked-color: rgba(255, 255, 255, 1) !default;
-$category-ListItemChecked-img-bg-color: rgba(240, 37, 15, 1) !default;
+$category-ListItemChecked-img-bg-color: $primary-color !default;
 
 // circleProgress
 $circleprogress-primary-color: $primary-color !default;

+ 6 - 2
src/packages/styles/variables-jdt.scss

@@ -731,12 +731,16 @@ $list-item-margin: 0 0 10px 0 !default;
 //Ecard
 $ecard-bg-color: #f0f2f5 !default;
 
+//addresslist
+$addresslist-contnts-contact-default: $primary-color !default;
+$addresslist-contnts-contact-color: $white !default;
+
 //category
 $category-bg-color: rgba(255, 255, 255, 1) !default;
 $category-ListLeft-bg-color: rgba(246, 247, 249, 1) !default;
-$category-ListItem-color: rgba(51, 51, 51, 1) !default;
+$category-ListItem-color: $title-color !default;
 $category-ListItemChecked-color: rgba(255, 255, 255, 1) !default;
-$category-ListItemChecked-img-bg-color: rgba(240, 37, 15, 1) !default;
+$category-ListItemChecked-img-bg-color: $primary-color !default;
 
 // circleProgress
 $circleprogress-primary-color: $primary-color !default;

+ 6 - 2
src/packages/styles/variables.scss

@@ -756,12 +756,16 @@ $list-item-margin: 0 0 10px 0 !default;
 //Ecard
 $ecard-bg-color: #f0f2f5 !default;
 
+//addresslist
+$addresslist-contnts-contact-default: $primary-color !default;
+$addresslist-contnts-contact-color: $white !default;
+
 //category
 $category-bg-color: rgba(255, 255, 255, 1) !default;
 $category-ListLeft-bg-color: rgba(246, 247, 249, 1) !default;
-$category-ListItem-color: rgba(51, 51, 51, 1) !default;
+$category-ListItem-color: $title-color !default;
 $category-ListItemChecked-color: rgba(255, 255, 255, 1) !default;
-$category-ListItemChecked-img-bg-color: rgba(240, 37, 15, 1) !default;
+$category-ListItemChecked-img-bg-color: $primary-color !default;
 
 // circleProgress
 $circleprogress-primary-color: $primary-color !default;

+ 60 - 49
src/sites/mobile-taro/vue/project.config.json

@@ -1,51 +1,62 @@
 {
-	"miniprogramRoot": "dist/",
-	"projectname": "%40nutui%2Fnutui-taro-mobile",
-	"description": "nutui-taro-vue",
-	"appid": "wxf2b976b67dab3882",
-	"setting": {
-		"urlCheck": true,
-		"es6": false,
-		"enhance": true,
-		"postcss": true,
-		"preloadBackgroundData": false,
-		"minified": true,
-		"newFeature": false,
-		"coverView": true,
-		"nodeModules": false,
-		"autoAudits": false,
-		"showShadowRootInWxmlPanel": true,
-		"scopeDataCheck": false,
-		"uglifyFileName": false,
-		"checkInvalidKey": true,
-		"checkSiteMap": true,
-		"uploadWithSourceMap": true,
-		"compileHotReLoad": false,
-		"lazyloadPlaceholderEnable": false,
-		"useMultiFrameRuntime": true,
-		"useApiHook": true,
-		"useApiHostProcess": true,
-		"babelSetting": {
-				"ignore": [],
-				"disablePlugins": [],
-				"outputPath": ""
-		},
-		"enableEngineNative": false,
-		"useIsolateContext": false,
-		"userConfirmedBundleSwitch": false,
-		"packNpmManually": false,
-		"packNpmRelationList": [],
-		"minifyWXSS": true,
-		"disableUseStrict": false,
-		"minifyWXML": true,
-		"showES6CompileOption": false,
-		"useCompilerPlugins": false
-	},
-	"compileType": "miniprogram",
-	"simulatorType": "wechat",
-	"simulatorPluginLibVersion": {},
-	"libVersion": "2.17.3",
-	"condition": {
-			"miniprogram": {}
-	}
+  "miniprogramRoot": "dist/",
+  "projectname": "%40nutui%2Fnutui-taro-mobile",
+  "description": "项目配置文件,详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
+  "appid": "wxf2b976b67dab3882",
+  "setting": {
+    "urlCheck": true,
+    "es6": false,
+    "enhance": true,
+    "postcss": true,
+    "preloadBackgroundData": false,
+    "minified": true,
+    "newFeature": false,
+    "coverView": true,
+    "nodeModules": false,
+    "autoAudits": false,
+    "showShadowRootInWxmlPanel": true,
+    "scopeDataCheck": false,
+    "uglifyFileName": false,
+    "checkInvalidKey": true,
+    "checkSiteMap": true,
+    "uploadWithSourceMap": true,
+    "compileHotReLoad": false,
+    "lazyloadPlaceholderEnable": false,
+    "useMultiFrameRuntime": true,
+    "useApiHook": true,
+    "useApiHostProcess": true,
+    "babelSetting": {
+      "ignore": [],
+      "disablePlugins": [],
+      "outputPath": ""
+    },
+    "enableEngineNative": false,
+    "useIsolateContext": false,
+    "userConfirmedBundleSwitch": false,
+    "packNpmManually": false,
+    "packNpmRelationList": [],
+    "minifyWXSS": true,
+    "disableUseStrict": false,
+    "minifyWXML": true,
+    "showES6CompileOption": false,
+    "useCompilerPlugins": false,
+    "ignoreUploadUnusedFiles": true,
+    "useStaticServer": true
+  },
+  "compileType": "miniprogram",
+  "simulatorType": "wechat",
+  "simulatorPluginLibVersion": {},
+  "libVersion": "2.17.3",
+  "condition": {
+    "miniprogram": {}
+  },
+  "srcMiniprogramRoot": "dist/",
+  "packOptions": {
+    "ignore": [],
+    "include": []
+  },
+  "editorSetting": {
+    "tabIndent": "insertSpaces",
+    "tabSize": 2
+  }
 }

+ 2 - 10
src/sites/mobile-taro/vue/project.private.config.json

@@ -1,15 +1,6 @@
 {
   "setting": {},
   "condition": {
-    "plugin": {
-      "list": []
-    },
-    "game": {
-      "list": []
-    },
-    "gamePlugin": {
-      "list": []
-    },
     "miniprogram": {
       "list": [
         {
@@ -56,5 +47,6 @@
         }
       ]
     }
-  }
+  },
+  "description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html"
 }

+ 99 - 94
src/sites/mobile-taro/vue/src/app.config.ts

@@ -1,99 +1,104 @@
+const subpackages = [
+  {
+    root: 'base',
+    pages: ['pages/button/index', 'pages/cell/index', 'pages/icon/index', 'pages/overlay/index', 'pages/popup/index']
+  },
+  {
+    root: 'layout',
+    pages: ['pages/layout/index', 'pages/sticky/index', 'pages/divider/index', 'pages/grid/index']
+  },
+  {
+    root: 'nav',
+    pages: [
+      'pages/navbar/index',
+      'pages/fixednav/index',
+      'pages/menu/index',
+      'pages/tabbar/index',
+      'pages/elevator/index',
+      'pages/pagination/index',
+      'pages/tabs/index',
+      'pages/indicator/index',
+      'pages/sidenavbar/index'
+    ]
+  },
+  {
+    root: 'dentry',
+    pages: [
+      'pages/range/index',
+      'pages/searchbar/index',
+      'pages/cascader/index',
+      'pages/calendar/index',
+      'pages/checkbox/index',
+      'pages/datepicker/index',
+      'pages/inputnumber/index',
+      'pages/input/index',
+      'pages/radio/index',
+      'pages/rate/index',
+      'pages/picker/index',
+      'pages/shortpassword/index',
+      'pages/textarea/index',
+      'pages/uploader/index',
+      'pages/numberkeyboard/index',
+      'pages/form/index'
+    ]
+  },
+  {
+    root: 'feedback',
+    pages: [
+      'pages/swipe/index',
+      'pages/actionsheet/index',
+      'pages/backtop/index',
+      'pages/drag/index',
+      'pages/dialog/index',
+      'pages/infiniteloading/index',
+      'pages/notify/index',
+      'pages/switch/index',
+      'pages/toast/index'
+    ]
+  },
+  {
+    root: 'exhibition',
+    pages: [
+      'pages/avatar/index',
+      'pages/list/index',
+      'pages/progress/index',
+      'pages/circleprogress/index',
+      'pages/noticebar/index',
+      'pages/empty/index',
+      'pages/steps/index',
+      'pages/swiper/index',
+      'pages/price/index',
+      'pages/imagepreview/index',
+      'pages/countup/index',
+      'pages/countdown/index',
+      'pages/badge/index',
+      'pages/tag/index',
+      'pages/popover/index',
+      'pages/skeleton/index',
+      'pages/collapse/index',
+      'pages/table/index'
+    ]
+  },
+  {
+    root: 'business',
+    pages: [
+      'pages/address/index',
+      'pages/barrage/index',
+      'pages/signature/index',
+      'pages/timeselect/index',
+      'pages/sku/index',
+      'pages/card/index',
+      'pages/ecard/index',
+      'pages/addresslist/index',
+      'pages/category/index',
+      'pages/comment/index'
+    ]
+  }
+];
+
 export default {
   pages: ['pages/index/index'],
-  subpackages: [
-    {
-      root: 'base',
-      pages: ['pages/button/index', 'pages/cell/index', 'pages/icon/index', 'pages/overlay/index', 'pages/popup/index']
-    },
-    { root: 'layout', pages: ['pages/layout/index', 'pages/sticky/index', 'pages/divider/index', 'pages/grid/index'] },
-    {
-      root: 'nav',
-      pages: [
-        'pages/navbar/index',
-        'pages/fixednav/index',
-        'pages/menu/index',
-        'pages/tabbar/index',
-        'pages/elevator/index',
-        'pages/pagination/index',
-        'pages/tabs/index',
-        'pages/indicator/index',
-        'pages/sidenavbar/index'
-      ]
-    },
-    {
-      root: 'dentry',
-      pages: [
-        'pages/range/index',
-        'pages/searchbar/index',
-        'pages/cascader/index',
-        'pages/calendar/index',
-        'pages/checkbox/index',
-        'pages/datepicker/index',
-        'pages/inputnumber/index',
-        'pages/input/index',
-        'pages/radio/index',
-        'pages/rate/index',
-        'pages/picker/index',
-        'pages/shortpassword/index',
-        'pages/textarea/index',
-        'pages/uploader/index',
-        'pages/numberkeyboard/index',
-        'pages/form/index'
-      ]
-    },
-    {
-      root: 'feedback',
-      pages: [
-        'pages/swipe/index',
-        'pages/actionsheet/index',
-        'pages/backtop/index',
-        'pages/drag/index',
-        'pages/dialog/index',
-        'pages/infiniteloading/index',
-        'pages/notify/index',
-        'pages/switch/index',
-        'pages/toast/index'
-      ]
-    },
-    {
-      root: 'exhibition',
-      pages: [
-        'pages/avatar/index',
-        'pages/list/index',
-        'pages/progress/index',
-        'pages/circleprogress/index',
-        'pages/noticebar/index',
-        'pages/empty/index',
-        'pages/steps/index',
-        'pages/swiper/index',
-        'pages/price/index',
-        'pages/imagepreview/index',
-        'pages/countup/index',
-        'pages/countdown/index',
-        'pages/badge/index',
-        'pages/tag/index',
-        'pages/popover/index',
-        'pages/skeleton/index',
-        'pages/collapse/index',
-        'pages/table/index'
-      ]
-    },
-    {
-      root: 'business',
-      pages: [
-        'pages/address/index',
-        'pages/barrage/index',
-        'pages/signature/index',
-        'pages/timeselect/index',
-        'pages/sku/index',
-        'pages/card/index',
-        'pages/ecard/index',
-        'pages/addresslist/index',
-        'pages/category/index',
-        'pages/comment/index'
-      ]
-    }
-  ],
+  subpackages,
   window: {
     backgroundTextStyle: 'light',
     navigationBarBackgroundColor: '#fff',