ソースを参照

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

Drjnigfubo 4 年 前
コミット
ada90abf5b
39 ファイル変更1757 行追加107 行削除
  1. 14 3
      src/config.json
  2. 3 0
      src/packages/__VUE/barrage/doc.md
  3. 5 1
      src/packages/__VUE/calendaritem/index.vue
  4. 11 0
      src/packages/__VUE/cell/demo.vue
  5. 18 0
      src/packages/__VUE/cell/doc.md
  6. 4 17
      src/packages/__VUE/cell/index.taro.vue
  7. 4 2
      src/packages/__VUE/cell/index.vue
  8. 5 1
      src/packages/__VUE/collapse/demo.vue
  9. 10 5
      src/packages/__VUE/collapse/doc.md
  10. 37 12
      src/packages/__VUE/collapseitem/index.taro.vue
  11. 8 2
      src/packages/__VUE/collapseitem/index.vue
  12. 154 0
      src/packages/__VUE/countdown/demo.vue
  13. 175 0
      src/packages/__VUE/countdown/doc.md
  14. 2 0
      src/packages/__VUE/countdown/index.scss
  15. 0 0
      src/packages/__VUE/countdown/index.taro.vue
  16. 243 0
      src/packages/__VUE/countdown/index.vue
  17. 4 2
      src/packages/__VUE/datepicker/doc.taro.md
  18. 4 2
      src/packages/__VUE/infiniteloading/doc.taro.md
  19. 112 0
      src/packages/__VUE/noticebar/demo.vue
  20. 159 0
      src/packages/__VUE/noticebar/doc.md
  21. 119 0
      src/packages/__VUE/noticebar/index.scss
  22. 0 0
      src/packages/__VUE/noticebar/index.taro.vue
  23. 410 0
      src/packages/__VUE/noticebar/index.vue
  24. 4 2
      src/packages/__VUE/picker/doc.taro.md
  25. 3 3
      src/packages/__VUE/swiper/doc.taro.md
  26. 51 37
      src/packages/__VUE/tab/doc.md
  27. 6 6
      src/packages/__VUE/tab/index.scss
  28. 7 6
      src/packages/utils/raf.ts
  29. BIN
      src/sites/assets/images/cat-back.png
  30. BIN
      src/sites/assets/images/cat-title.png
  31. BIN
      src/sites/assets/images/marketing-back.png
  32. BIN
      src/sites/assets/images/marketing-title.png
  33. 1 1
      src/sites/doc/components/Footer.vue
  34. 1 1
      src/sites/doc/components/Header.vue
  35. 164 3
      src/sites/doc/views/Main.vue
  36. 6 0
      src/sites/mobile-taro/vue/project.private.config.json
  37. 11 0
      src/sites/mobile-taro/vue/src/base/pages/cell/index.vue
  38. 1 0
      src/sites/mobile-taro/vue/src/feedback/pages/collapse/index.vue
  39. 1 1
      src/sites/mobile/components/IndexTaro.vue

+ 14 - 3
src/config.json

@@ -542,9 +542,10 @@
           "type": "component",
           "cName": "公告栏",
           "desc": "用于循环播放展示一组消息通知",
-          "sort": 5,
-          "show": false,
-          "author": "wangyue92"
+          "sort": 8,
+          "show": true,
+          "taro": false,
+          "author": "yangxiaolu"
         }
       ]
     },
@@ -727,6 +728,16 @@
           "show": true,
           "desc": "虚拟数字键盘",
           "author": "Drjingfubo"
+        },
+        {
+          "name": "CountDown",
+          "type": "component",
+          "cName": "倒计时",
+          "desc": "倒计时",
+          "sort": 16,
+          "show": true,
+          "taro": false,
+          "author": "yangxiaolu"
         }
       ]
     },

+ 3 - 0
src/packages/__VUE/barrage/doc.md

@@ -8,7 +8,10 @@
 
 ``` javascript
 import { createApp } from 'vue';
+//vue
 import { Barrage } from '@nutui/nutui';
+//taro
+import { Barrage } from '@nutui/nutui-taro';
 
 const app = createApp();
 app.use(Barrage);

+ 5 - 1
src/packages/__VUE/calendaritem/index.vue

@@ -315,7 +315,11 @@ export default create({
           month = month == 12 ? 1 : ++month;
           break;
       }
-      return [year, Utils.getNumTwoBit(month), monthData.curData[2]];
+      return [
+        year,
+        Utils.getNumTwoBit(month),
+        Utils.getMonthDays(String(year), String(month))
+      ];
     };
 
     // 获取日期状态

+ 11 - 0
src/packages/__VUE/cell/demo.vue

@@ -35,6 +35,17 @@
       </nut-cell>
     </nut-cell-group>
 
+    <nut-cell-group title="自定义左侧 Icon 区域">
+      <nut-cell title="图片">
+        <template v-slot:icon>
+          <img
+            class="nut-icon"
+            src="https://img11.360buyimg.com/imagetools/jfs/t1/137646/13/7132/1648/5f4c748bE43da8ddd/a3f06d51dcae7b60.png"
+          />
+        </template>
+      </nut-cell>
+    </nut-cell-group>
+
     <h2>展示图标</h2>
     <nut-cell title="姓名" icon="my" desc="张三" isLink> </nut-cell>
     <h2>只展示 desc ,可通过 desc-text-align 调整内容位置</h2>

+ 18 - 0
src/packages/__VUE/cell/doc.md

@@ -71,7 +71,17 @@ export default {
   </nut-cell>
 </nut-cell-group>
 ```
+### 自定义左侧 Icon 区域
 
+``` html
+<nut-cell-group title="自定义左侧 Icon 区域">
+  <nut-cell title="图片">
+    <template v-slot:icon>
+      <img class="nut-icon" src="https://img11.360buyimg.com/imagetools/jfs/t1/137646/13/7132/1648/5f4c748bE43da8ddd/a3f06d51dcae7b60.png" />
+    </template>
+  </nut-cell>
+</nut-cell-group>
+```
 
 ### 单元格展示图标
 
@@ -108,3 +118,11 @@ export default {
 | click | 点击事件 | event:Event |
 
 
+## Slots
+
+| 名称          | 说明                 |
+|---------------|----------------------|
+| icon `v3.1.4` | 自定义左侧 icon 区域 |
+| default       | 自定义内容           |
+| link          | 自定义右侧 link 区域 |
+

+ 4 - 17
src/packages/__VUE/cell/index.taro.vue

@@ -3,10 +3,12 @@
     <slot>
       <view
         class="nut-cell__title"
-        :class="{ icon: icon }"
+        :class="{ icon: icon || $slots.icon }"
         v-if="title || subTitle || icon"
       >
-        <nut-icon v-if="icon" class="icon" :name="icon"></nut-icon>
+        <slot v-if="$slots.icon" name="icon"></slot>
+        <nut-icon v-else-if="icon" class="icon" :name="icon"></nut-icon>
+
         <template v-if="subTitle">
           <view class="title">{{ title }}</view>
           <view class="nut-cell__title-desc">{{ subTitle }}</view>
@@ -35,7 +37,6 @@
 <script lang="ts">
 import { computed } from 'vue';
 import { createComponent } from '../../utils/create';
-import { useRouter } from 'vue-router';
 import CellGroup from '../cellgroup/index.vue';
 import { pxCheck } from '../../utils/pxCheck';
 const { componentName, create } = createComponent('cell');
@@ -65,7 +66,6 @@ export default create({
         [`${prefixCls}--clickable`]: props.isLink || props.to
       };
     });
-    const router = useRouter();
 
     const baseStyle = computed(() => {
       return {
@@ -75,19 +75,6 @@ export default create({
 
     const handleClick = (event: Event) => {
       emit('click', event);
-
-      if (props.to && router) {
-        router[props.replace ? 'replace' : 'push'](props.to);
-        // if(props.replace){
-        //   router.replace(props.to)
-        // }else{
-        //    router.push(props.to)
-        // }
-      } else if (props.url) {
-        props.replace
-          ? location.replace(props.url)
-          : (location.href = props.url);
-      }
     };
 
     return {

+ 4 - 2
src/packages/__VUE/cell/index.vue

@@ -3,10 +3,12 @@
     <slot>
       <view
         class="nut-cell__title"
-        :class="{ icon: icon }"
+        :class="{ icon: icon || $slots.icon }"
         v-if="title || subTitle || icon"
       >
-        <nut-icon v-if="icon" class="icon" :name="icon"></nut-icon>
+        <slot v-if="$slots.icon" name="icon"></slot>
+        <nut-icon v-else-if="icon" class="icon" :name="icon"></nut-icon>
+
         <template v-if="subTitle">
           <view class="title">{{ title }}</view>
           <view class="nut-cell__title-desc">{{ subTitle }}</view>

+ 5 - 1
src/packages/__VUE/collapse/demo.vue

@@ -2,7 +2,10 @@
   <div class="demo full">
     <h2>基本用法</h2>
     <nut-collapse v-model:active="active1" icon="down-arrow">
-      <nut-collapse-item :title="title1" :name="1">
+      <nut-collapse-item :name="1">
+        <template v-slot:mTitle>
+          {{ title1 }}
+        </template>
         NutUI是一套拥有京东风格的轻量级的 Vue 组件库
       </nut-collapse-item>
       <nut-collapse-item :title="title2" :name="2">
@@ -41,6 +44,7 @@
       rotate="90"
     >
       <nut-collapse-item :title="title1" :name="1">
+        <template v-slot:sTitle> 文本测试 </template>
         NUTUI3.0重新思考其内在的一致性和可组合性
       </nut-collapse-item>
       <nut-collapse-item :title="title2" :name="2" sub-title="文本内容">

+ 10 - 5
src/packages/__VUE/collapse/doc.md

@@ -25,7 +25,10 @@ app.use(Collapse);
 
 ```html
 <nut-collapse v-model:active="active1" icon="down-arrow">
-  <nut-collapse-item :title="title1" :name="1">
+  <nut-collapse-item :name="1">
+    <template v-slot:mTitle>
+      {{title1}}
+    </template>
     NutUI是一套拥有京东风格的轻量级的 Vue 组件库
   </nut-collapse-item>
   <nut-collapse-item :title="title2" :name="2">
@@ -126,7 +129,10 @@ setup() {
   rotate="90"
 >
   <nut-collapse-item :title="title1" :name="1">
-      NUTUI3.0重新思考其内在的一致性和可组合性
+    <template v-slot:sTitle>
+      文本测试
+    </template>
+    NUTUI3.0重新思考其内在的一致性和可组合性
   </nut-collapse-item>
   <nut-collapse-item :title="title2" :name="2" sub-title="文本内容">
     提⾼产研输出对接的效率,降低输出工作量
@@ -191,7 +197,6 @@ return {
 | icon | 图标链接/或使用 NutUI 的 icon | string | ‘’ |
 | icon-size | 图标大小 | string | 16px |
 | icon-color | 图标颜色 | string | '' |
-| sub-title | 标题栏副标题 | string | - |
 | title-icon | 标题图标链接/或使用 NutUI 的 icon | string | ‘’ |
 | title-icon-size | 标题图标大小 | string | 16px |
 | title-icon-color | 标题图标颜色 | string | ’‘ |
@@ -202,8 +207,8 @@ return {
 | 参数 | 说明 | 类型 | 默认值 | 
 |------|------|------|------|
 | name | 唯一标识符,必填 | string \ number | -1 |
-| title | 标题栏左侧内容 | string | - |
-| sub-title | 标题栏副标题 | string | - |
+| title | 标题栏左侧内容,支持插槽传入(props传入的优先级更高) | string | - |
+| sub-title | 标题栏副标题,支持插槽传入(props传入的优先级更高) | string | - |
 | disabled | 标题栏是否禁用 | boolean | false |
 
 ### Events

+ 37 - 12
src/packages/__VUE/collapseitem/index.taro.vue

@@ -21,11 +21,31 @@
                 titleIconPosition == 'left' ? 'titleIconLeft' : 'titleIconRight'
               ]"
             ></nut-icon>
-            <view v-html="title" class="collapse-icon-title"></view>
+            <template v-if="$slots.mTitle">
+              <slot name="mTitle"></slot>
+            </template>
+            <template v-else>
+              <view v-html="title" class="collapse-icon-title"></view>
+            </template>
+            <!-- <view
+              v-html="title"
+              class="collapse-icon-title"
+              v-if="title"
+            ></view>
+            <mTitle v-else>
+              <slot name="mTitle"></slot>
+            </mTitle> -->
           </view>
         </view>
       </view>
-      <view v-if="subTitle" v-html="subTitle" class="subTitle"></view>
+      <!-- <view v-if="subTitle" v-html="subTitle" class="subTitle"></view>
+      <view class="subTitle" v-else>
+        <slot name="sTitle"></slot>
+      </view> -->
+      <view v-if="$slots.sTitle" class="subTitle">
+        <slot name="sTitle"></slot>
+      </view>
+      <view v-else v-html="subTitle" class="subTitle"></view>
       <nut-icon
         v-if="icon"
         :name="icon"
@@ -167,7 +187,7 @@ export default create({
         const query = Taro.createSelectorQuery();
         query.selectAll('.collapse-content').boundingClientRect();
         query.exec((res) => {
-          getH();
+          getH(res[0]);
         });
         if (!proxyData.openExpanded) {
           onTransitionEnd();
@@ -226,10 +246,15 @@ export default create({
       }
     });
 
-    const getH = () => {
+    const getH = (list: any) => {
       parent.children.forEach((item1: any, index1: number) => {
         let ary: any = Array.from(item1.$el.children);
-        item1.conHeight = ary[1].children[0].offsetHeight;
+        let _uid = ary[1].children[0]['uid'];
+        let tm = list.filter((item2: any) => item2.id == _uid);
+        if (tm && tm.length > 0) {
+          let h = tm[0]['height'];
+          item1.conHeight = h;
+        }
         // ary.forEach((item2: any, index2: number) => {
         //   let ary2 = Array.from(item2.children);
         //   ary2.length > 0 &&
@@ -244,8 +269,8 @@ export default create({
       });
     };
 
-    let list: any = [],
-      domID: any = [];
+    // let list: any = [],
+    //   domID: any = [];
     onMounted(() => {
       const { name } = props;
       const active = parent && parent.props.active;
@@ -254,11 +279,11 @@ export default create({
         const query = Taro.createSelectorQuery();
         query.selectAll('.collapse-content').boundingClientRect();
         query.exec((res) => {
-          list = res[0];
-          list.forEach((item: any) => {
-            domID.push(item.id);
-          });
-          getH();
+          // list = res[0];
+          // list.forEach((item: any) => {
+          //   domID.push(item.id);
+          // });
+          getH(res[0]);
           // parent.activeIndex().forEach((item:any) => {
           //   const h = list[item]?.height;
           //   parent.children[item].conHeight = h;

+ 8 - 2
src/packages/__VUE/collapseitem/index.vue

@@ -20,11 +20,17 @@
                 titleIconPosition == 'left' ? 'titleIconLeft' : 'titleIconRight'
               ]"
             ></nut-icon>
-            <view v-html="title"></view>
+            <slot v-if="$slots.mTitle" name="mTitle"></slot>
+            <template v-else>
+              <view v-html="title"></view>
+            </template>
           </view>
         </view>
       </view>
-      <view v-if="subTitle" v-html="subTitle" class="subTitle"></view>
+      <view v-if="$slots.sTitle" class="subTitle">
+        <slot name="sTitle"></slot>
+      </view>
+      <view v-else v-html="subTitle" class="subTitle"></view>
       <nut-icon
         v-if="icon"
         :name="icon"

+ 154 - 0
src/packages/__VUE/countdown/demo.vue

@@ -0,0 +1,154 @@
+<template>
+  <div class="demo">
+    <h2>基础用法</h2>
+    <nut-cell>
+      <nut-countdown :endTime="end" @on-end="onend"></nut-countdown>
+    </nut-cell>
+    <h2>显示天</h2>
+
+    <nut-cell>
+      <nut-countdown :endTime="end" showDays />
+    </nut-cell>
+
+    <h2>以服务端的时间为准</h2>
+
+    <nut-cell>
+      <nut-countdown :startTime="serverTime" :endTime="end" />
+    </nut-cell>
+
+    <h2>显示为 天时分秒</h2>
+
+    <nut-cell>
+      <nut-countdown showDays showPlainText :endTime="end" />
+    </nut-cell>
+
+    <h2>异步更新结束时间</h2>
+
+    <nut-cell>
+      <nut-countdown showPlainText :endTime="asyncEnd" />
+    </nut-cell>
+
+    <h2>控制开始和暂停的倒计时</h2>
+
+    <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>
+
+    <h2>自定义展示</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 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>
+      </span>
+    </nut-cell>
+
+    <h2>自定义显示</h2>
+
+    <nut-cell>
+      <span>可调用该组件提供的 restTime 方法获取 '天时分秒' 自定义显示</span>
+    </nut-cell>
+  </div>
+</template>
+
+<script lang="ts">
+import {
+  toRefs,
+  onMounted,
+  onUnmounted,
+  reactive,
+  computed,
+  CSSProperties,
+  onActivated,
+  onDeactivated,
+  ref,
+  watch,
+  h
+} from 'vue';
+import { createComponent } from '../../utils/create';
+const { createDemo } = createComponent('countdown');
+export default createDemo({
+  props: {},
+  setup() {
+    const state = reactive({
+      serverTime: Date.now() - 30 * 1000,
+      end: Date.now() + 50 * 1000,
+      asyncEnd: 0,
+      paused: false,
+      resetTime: {
+        d: '1',
+        h: '00',
+        m: '00',
+        s: '00'
+      }
+    });
+
+    const toggle = () => {
+      state.paused = !state.paused;
+    };
+    const onend = () => {
+      console.log('countdown: ended.');
+    };
+    const onpaused = (v) => {
+      console.log('paused: ', v);
+    };
+    const onrestart = (v) => {
+      console.log('restart: ', v);
+    };
+
+    setTimeout(() => {
+      state.asyncEnd = Date.now() + 30 * 1000;
+    }, 3000);
+
+    return {
+      ...toRefs(state),
+      toggle,
+      onend,
+      onpaused,
+      onrestart
+    };
+  }
+});
+</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>

+ 175 - 0
src/packages/__VUE/countdown/doc.md

@@ -0,0 +1,175 @@
+#  countdown组件
+
+### 介绍
+
+### 安装
+
+
+``` javascript
+import { createApp } from 'vue';
+// vue
+import { CountDown } from '@nutui/nutui';
+
+const app = createApp();
+app.use(CountDown);
+```
+
+### 基础用法
+
+```html
+<nut-countdown :end-time="end" ></nut-countdown>
+```
+
+``` javascript
+setup() {
+  const state = reactive({
+      end: Date.now() + 50 * 1000,
+    });
+  return {
+    ...toRefs(state)
+  };
+}
+```
+
+### 显示天
+
+```html
+<nut-countdown :end-time="end" show-days ></nut-countdown>
+```
+
+### 以服务端的时间为准
+
+```html
+<nut-countdown  :start-time="serverTime" :end-time="end" show-days ></nut-countdown>
+```
+
+``` javascript
+setup() {
+  const state = reactive({
+      serverTime: Date.now() - 30 * 1000,
+      end: Date.now() + 50 * 1000,
+    });
+  return {
+    ...toRefs(state)
+  };
+}
+```
+
+### 显示为 天时分秒
+
+```html
+<nut-countdown show-days show-plain-text  :end-time="end"></nut-countdown>
+```
+``` javascript
+setup() {
+  const state = reactive({
+      end: Date.now() + 50 * 1000,
+    });
+  return {
+    ...toRefs(state)
+  };
+}
+```
+
+### 异步更新结束时间
+
+```html
+<nut-countdown  show-days show-plain-text  :end-time="asyncEnd" ></nut-countdown>
+```
+``` javascript
+setup() {
+  const state = reactive({
+      asyncEnd: 0,
+    });
+  return {
+    ...toRefs(state)
+  };
+}
+```
+
+### 控制开始和暂停的倒计时
+
+```html
+<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>
+```
+``` javascript
+setup() {
+  const state = reactive({
+      paused: false,
+      end: Date.now() + 50 * 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)
+  };
+}
+```
+### 自定义展示
+
+```html
+<nut-countdown v-model="resetTime" :endTime="end">
+    <div class="countdown-part-box">
+        <div class="part-item-symbol"> resetTime.d 天</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>
+```
+``` javascript
+setup() {
+  const state = reactive({
+      end: Date.now() + 50 * 1000,
+      resetTime: {
+        d: '1',
+        h: '00',
+        m: '00',
+        s: '00'
+      }
+    });
+  return {
+    ...toRefs(state)
+  };
+}
+```
+
+### API
+
+### Props
+
+| 字段 | 说明 | 类型 | 默认值
+| ----- | ----- | ----- | -----
+| v-model | 当前时间,自定义展示内容时生效 | Object | {}
+| start-time | 开始时间 | String, Number | Date.now()
+| end-time | 结束时间 | String, Number | Date.now()
+| show-days | 是否显示天 | Boolean | false
+| show-plain-text | 显示为纯文本 | Boolean | false
+| paused | 是否暂停 | Boolean | false
+
+
+### Event
+
+| 字段 | 说明 | 回调参数
+| ----- | ----- | ----- 
+| on-end | 倒计时结束时 | 剩余时间戳
+| on-paused | 暂停时 | 剩余时间戳
+| on-restart | 暂停时 | 剩余时间戳

+ 2 - 0
src/packages/__VUE/countdown/index.scss

@@ -0,0 +1,2 @@
+.nut-countdown {
+}

+ 0 - 0
src/packages/__VUE/countdown/index.taro.vue


+ 243 - 0
src/packages/__VUE/countdown/index.vue

@@ -0,0 +1,243 @@
+<template>
+  <view :class="classes" @click="handleClick">
+    <template v-if="slots.default">
+      <slot></slot>
+    </template>
+    <template v-else-if="showPlainText">
+      <view class="nut-cd-block">{{ plainText }}</view>
+    </template>
+    <template v-else>
+      <template v-if="resttime.d >= 0 && showDays">
+        <view class="nut-cd-block">{{ resttime.d }}</view>
+        <view class="nut-cd-dot">天</view>
+      </template>
+      <view class="nut-cd-block">{{ resttime.h }}</view
+      ><view class="nut-cd-dot">:</view
+      ><view class="nut-cd-block">{{ resttime.m }}</view
+      ><view class="nut-cd-dot">:</view
+      ><view class="nut-cd-block">{{ resttime.s }}</view>
+    </template>
+  </view>
+</template>
+<script lang="ts">
+import {
+  toRefs,
+  onMounted,
+  onUnmounted,
+  reactive,
+  computed,
+  CSSProperties,
+  onActivated,
+  onDeactivated,
+  ref,
+  watch,
+  vModelText
+} from 'vue';
+import { createComponent } from '../../utils/create';
+const { componentName, create } = createComponent('countdown');
+
+export default create({
+  props: {
+    modelValue: {
+      type: Object,
+      default: () => {
+        return {};
+      }
+    },
+    paused: {
+      default: false,
+      type: Boolean
+    },
+    showDays: {
+      default: false,
+      type: Boolean
+    },
+    showPlainText: {
+      default: false,
+      type: Boolean
+    },
+    startTime: {
+      // 可以是服务器当前时间
+      type: [Number, String],
+      validator(v) {
+        const dateStr = new Date(v).toString().toLowerCase();
+        return dateStr !== 'invalid date';
+      }
+    },
+    endTime: {
+      type: [Number, String],
+      validator(v) {
+        const dateStr = new Date(v).toString().toLowerCase();
+        return dateStr !== 'invalid date';
+      }
+    }
+  },
+  components: {},
+  emits: ['input', 'on-end', 'on-restart', 'on-paused'],
+
+  setup(props, { emit, slots }) {
+    console.log('componentName', componentName);
+
+    const state = reactive({
+      restTime: 0,
+      p: 0,
+      _curr: 0,
+      timer: null
+    });
+
+    const resttime = computed(() => {
+      const rest = restTime(state.restTime);
+      const { d, h, m, s } = rest;
+      if (!props.showDays && d > 0) {
+        rest.h = fill2(Number(rest.h) + d * 24);
+        rest.d = 0;
+      }
+      return rest;
+    });
+
+    const plainText = computed(() => {
+      const { d, h, m, s } = resttime.value;
+
+      return `${d > 0 && props.showDays ? d + '天' + h : h}小时${m}分${s}秒`;
+    });
+
+    watch(
+      () => props.value,
+      (value) => {}
+    );
+
+    watch(
+      () => state.restTime,
+      (value) => {
+        let tranTime = restTime(value);
+        emit('update:modelValue', tranTime);
+        emit('input', tranTime);
+      }
+    );
+
+    watch(
+      () => props.paused,
+      (v, ov) => {
+        if (!ov) {
+          state._curr = getTimeStamp();
+          emit('on-paused', state.restTime);
+        } else {
+          state.p += getTimeStamp() - state._curr;
+          emit('on-restart', state.restTime);
+        }
+      }
+    );
+
+    watch(
+      () => props.endTime,
+      (value) => {
+        initTimer();
+      }
+    );
+
+    watch(
+      () => props.startTime,
+      (value) => {
+        initTimer();
+      }
+    );
+
+    const classes = computed(() => {
+      const prefixCls = componentName;
+      return {
+        [prefixCls]: true
+      };
+    });
+
+    const getTimeStamp = (timeStr?: string | number) => {
+      if (!timeStr) return Date.now();
+      let t = timeStr;
+      t = t > 0 ? +t : t.toString().replace(/\-/g, '/');
+      return new Date(t).getTime();
+    };
+
+    const initTimer = () => {
+      const delay = 1000;
+      const curr = Date.now();
+      const start = getTimeStamp(props.startTime || curr);
+      const end = getTimeStamp(props.endTime || curr);
+      const diffTime = curr - start;
+
+      state.restTime = end - (start + diffTime);
+      (state.timer as any) = setInterval(() => {
+        if (!props.paused) {
+          let restTime = end - (Date.now() - state.p + diffTime);
+          state.restTime = restTime;
+          if (restTime < delay) {
+            state.restTime = 0;
+            emit('on-end');
+            clearInterval(state.timer as any);
+          }
+        } else {
+          // 暂停
+        }
+      }, delay);
+    };
+
+    const fill2 = (v: any) => {
+      v += '';
+      while (v.length < 2) {
+        v = '0' + v;
+      }
+      return v;
+    };
+    const restTime = (t: any) => {
+      const ts = t;
+      let rest = {
+        d: '-',
+        h: '--',
+        m: '--',
+        s: '--'
+      };
+      if (ts === 0) {
+        rest = {
+          d: '0',
+          h: '00',
+          m: '00',
+          s: '00'
+        };
+      }
+      if (ts) {
+        const ds = 24 * 60 * 60 * 1000;
+        const hs = 60 * 60 * 1000;
+        const ms = 60 * 1000;
+
+        const d = ts >= ds ? parseInt(ts / ds) : 0;
+        const h = ts - d * ds >= hs ? parseInt((ts - d * ds) / hs) : 0;
+        const m =
+          ts - d * ds - h * hs >= ms
+            ? parseInt((ts - d * ds - h * hs) / ms)
+            : 0;
+        const s = Math.round((ts - d * ds - h * hs - m * ms) / 1000);
+
+        if (d >= 0) rest.d = d + '';
+        if (h >= 0) rest.h = fill2(h);
+        if (m >= 0) rest.m = fill2(m);
+        if (s >= 0) rest.s = fill2(s);
+      }
+      return rest;
+    };
+
+    initTimer();
+
+    return {
+      ...toRefs(props),
+      slots,
+      classes,
+      getTimeStamp,
+      initTimer,
+      resttime,
+      plainText
+    };
+  }
+});
+</script>
+
+<style lang="scss">
+@import 'index.scss';
+</style>

+ 4 - 2
src/packages/__VUE/datepicker/doc.taro.md

@@ -3,8 +3,10 @@
 ### 介绍
     
 时间选择器,支持日期、年月、时分等维度,通常与弹出层组件配合使用。
+
+#### 直接使用 Taro 现有 Picker[mode="date"] 组件开发 [参考文档](https://docs.taro.zone/docs/components/forms/picker)
     
-### 安装
+<!-- ### 安装
 
 ```javascript
 import { createApp } from 'vue';
@@ -57,4 +59,4 @@ export default createDemo({
     
 | 事件名  | 说明               | 回调参数     |
 |---------|--------------------|--------------|
-| onChange | 点击确定按钮时触发 | event: Event |
+| onChange | 点击确定按钮时触发 | event: Event | -->

+ 4 - 2
src/packages/__VUE/infiniteloading/doc.taro.md

@@ -4,7 +4,9 @@
 
 列表滚动到底部自动加载更多数据。
 
-### 安装
+#### 直接使用 Taro 现有 ScrollView 组件开发 [参考文档](https://docs.taro.zone/docs/components/viewContainer/scroll-view)
+
+<!-- ### 安装
 
 ```javascript
   import { createApp } from 'vue';
@@ -109,5 +111,5 @@ setup() {
 |--------|----------------|--------------|
 | load-more  | 继续加载的回调函数 | done 函数,用于关闭加载中状态 |
 | scroll-change  | 实时监听滚动高度 | 滚动高度 |
-| refresh  | 下拉刷新事件回调 | done 函数,用于关闭加载中状态 |
+| refresh  | 下拉刷新事件回调 | done 函数,用于关闭加载中状态 | -->
     

+ 112 - 0
src/packages/__VUE/noticebar/demo.vue

@@ -0,0 +1,112 @@
+<template>
+  <div class="demo">
+    <h2>默认用法</h2>
+    <nut-noticebar :text="text"></nut-noticebar>
+
+    <h2>禁用滚动</h2>
+    <nut-noticebar
+      text="华为畅享9新品即将上市,活动期间0元预约可参与抽奖,赢HUAWEI WATCH等好礼,更多产品信息请持续关注!"
+      :scrollable="false"
+    ></nut-noticebar>
+
+    <h2>通告栏模式--关闭模式</h2>
+    <nut-noticebar :closeMode="true" @click="hello"
+      >华为畅享9新品即将上市,活动期间0元预约可参与抽奖,赢HUAWEI
+      WATCH等好礼,更多产品信息请持续关注!
+    </nut-noticebar>
+    <h2>通告栏模式--链接模式</h2>
+    <nut-noticebar
+      left-icon="https://img13.360buyimg.com/imagetools/jfs/t1/72082/2/3006/1197/5d130c8dE1c71bcd6/e48a3b60804c9775.png"
+    >
+      <a href="https://www.jd.com">京东商城</a>
+    </nut-noticebar>
+
+    <h2>纵向滚动</h2>
+    <div class="interstroll-list">
+      <nut-noticebar
+        direction="vertical"
+        :list="horseLamp1"
+        :speed="10"
+        :standTime="1000"
+        @click="go"
+        :closeMode="true"
+      ></nut-noticebar>
+    </div>
+
+    <h2>纵向复杂滚动动画</h2>
+    <nut-noticebar
+      direction="vertical"
+      :list="horseLamp2"
+      :speed="10"
+      :standTime="2000"
+      :complexAm="true"
+    ></nut-noticebar>
+
+    <h2>纵向自定义滚动内容</h2>
+    <nut-noticebar
+      direction="vertical"
+      :height="50"
+      :speed="10"
+      :standTime="1000"
+      :list="[]"
+      @close="go"
+    >
+      <div
+        class="custom-item"
+        :data-index="index"
+        v-for="(item, index) in horseLamp3"
+        style="height: 50px; line-height: 50px"
+        :key="index"
+        >{{ item }}</div
+      >
+    </nut-noticebar>
+
+    <h2>纵向自定义右侧图标</h2>
+    <nut-noticebar
+      direction="vertical"
+      :list="horseLamp1"
+      :speed="10"
+      :standTime="1000"
+    >
+      <template v-slot:rightIcon>
+        <nut-icon type="trolley" color="#f0250f"> </nut-icon>
+      </template>
+    </nut-noticebar>
+  </div>
+</template>
+
+<script lang="ts">
+import { onMounted, reactive, toRefs } from 'vue';
+import { createComponent } from '../../utils/create';
+const { createDemo } = createComponent('noticebar');
+export default createDemo({
+  props: {},
+  setup() {
+    const state = reactive({
+      horseLamp1: ['惊喜红包免费领', '爆款准点秒', '买超值优惠', '赢百万京豆'],
+      horseLamp2: ['惊喜红包免费领', '爆款准点秒', '买超值优惠', '赢百万京豆'],
+      horseLamp3: ['惊喜红包免费领', '爆款准点秒', '买超值优惠', '赢百万京豆'],
+      text: '华为畅享9新品即将上市,活动期间0元预约可参与抽奖,赢HUAWEI WATCH等好礼,更多产品信息请持续关注!'
+    });
+
+    const hello = () => {
+      console.log('hello world');
+    };
+    const go = (item: any) => {
+      console.log(item);
+    };
+
+    return {
+      ...toRefs(state),
+      hello,
+      go
+    };
+  }
+});
+</script>
+
+<style lang="scss" scoped>
+.demo {
+  padding-bottom: 30px !important;
+}
+</style>

+ 159 - 0
src/packages/__VUE/noticebar/doc.md

@@ -0,0 +1,159 @@
+# NoticeBar 通告栏
+
+### 介绍 
+
+
+用于循环播放展示一组消息通知。
+
+
+### 安装
+
+```javascript
+
+import { createApp } from 'vue';
+// vue
+import { NoticeBar } from '@nutui/nutui';
+
+const app = createApp();
+app.use(NoticeBar);
+
+```
+
+### 代码示例
+
+### 基本用法
+
+```html
+    <nut-noticebar
+      text="华为畅享9新品即将上市,活动期间0元预约可参与抽奖,赢HUAWEI WATCH等好礼,更多产品信息请持续关注!"
+    ></nut-noticebar>
+```
+### 禁用滚动
+文字内容多于一行时,可通过scrollable参数控制是否开启滚动
+```html
+    <nut-noticebar
+      text="华为畅享9新品即将上市,活动期间0元预约可参与抽奖,赢HUAWEI WATCH等好礼,更多产品信息请持续关注!"
+      :scrollable="false"
+    ></nut-noticebar>
+```
+### 通告栏模式--关闭模式
+```html
+    <nut-noticebar
+      :closeMode="true"
+      @click="hello"
+    >华为畅享9新品即将上市,活动期间0元预约可参与抽奖,赢HUAWEI WATCH等好礼,更多产品信息请持续关注!
+    </nut-noticebar>
+```
+### 通告栏模式--链接模式
+```html
+    <nut-noticebar
+      left-icon="https://img13.360buyimg.com/imagetools/jfs/t1/72082/2/3006/1197/5d130c8dE1c71bcd6/e48a3b60804c9775.png"
+    >
+      <a href="https://www.jd.com">京东商城</a>
+    </nut-noticebar>
+```
+
+### 纵向滚动
+
+```html
+<nut-noticebar direction='vertical' :list="horseLamp1" :speed='10' :standTime='1000'  @click='go' :closeMode="true"></nut-noticebar>
+```
+```javascript
+data() {
+    return {
+        horseLamp1: ['惊喜红包免费领', '爆款准点秒', '买超值优惠', '赢百万京豆'],
+    };
+},
+
+methods:{
+    go(item){
+        console.log(item)
+    }
+}
+```
+
+
+### 复杂滚动动画
+
+```html
+<nut-noticebar direction='vertical' :list="horseLamp2" :speed='10' :standTime='2000' :complexAm='true'></nut-noticebar>
+```
+```javascript
+data() {
+    return {
+        horseLamp2: ['惊喜红包免费领', '爆款准点秒', '买超值优惠', '赢百万京豆'],
+    };
+}
+```
+
+### 自定义滚动内容
+
+```html
+<nut-noticebar direction='vertical' :height='50' :speed='10' :standTime='1000' :list="[]"  @close='go'>
+  <div class="custom-item" :data-index='index' v-for="(item,index) in horseLamp3" :key="index">{{item}}</div>
+</nut-noticebar>
+```
+```javascript
+data() {
+    return {
+        horseLamp3: ['惊喜红包免费领', '爆款准点秒', '买超值优惠', '赢百万京豆'],
+    };
+}
+```
+
+
+### 纵向自定义右侧图标
+
+```html
+<nut-noticebar direction='vertical' :list="horseLamp1" :speed='10' :standTime='1000' >
+  <template v-slot:rightIcon>
+    <nut-icon 
+      type="trolley" 
+      color="#f0250f"
+    >
+    </nut-icon>
+
+  </template>
+</nut-noticebar>
+```
+```javascript
+data() {
+    return {
+        horseLamp1: ['惊喜红包免费领', '爆款准点秒', '买超值优惠', '赢百万京豆'],
+    };
+}
+```
+
+
+
+### Prop
+
+| 字段       | 说明                                                       | 类型          | 默认值 |
+| ---------- | ---------------------------------------------------------- | ------------- | ------ |
+| direction       | 滚动的方向,可选 across、vertical                         | String        | across     |
+| text       | 提示的信息                                                 | String        | 空     |
+| closeMode  | 是否启用关闭模式                                           | Boolean       | false  |
+| leftIcon   | close为没有左边icon,其他为自定义的图片链接,没有为默认图片 | String        | 空     |
+| color      | 导航栏的文字颜色                                           | String        | 空     |
+| background | 导航栏的背景颜色                                           | String        | 空     |
+| delay      | 延时多少秒                                                 | String/Number | 1      |
+| scrollable | 是否可以滚动                                               | Boolean       | true   |
+| speed      | 滚动速率 (px/s)                                            | Number        | 50     |
+
+### Prop(direction=vertical)
+
+| 参数         | 说明                             | 类型   | 默认值           |
+|--------------|----------------------------------|--------|------------------|
+| list         | 纵向滚动数据列表               | Array | []               |
+| speed        | 滚动的速度                         | Number | 50               |
+| standTime         | 停留时间(毫秒) | Number | 1000                |
+| complexAm | 稍复杂的动画,耗能会高     | Boolean | false |
+| height          | 每一个滚动列的高度(px),注意:在使用 slot 插槽定义滚动单元时,按照实际高度修改此值                 | Number | 40              |
+| closeMode  | 是否启用右侧关闭图标,可以通过slot[name=rightIcon]自定义图标                                   | Boolean       | false  |
+
+### Event
+
+| 字段  | 说明             | 回调参数     |
+| ----- | ---------------- | ------------ |
+| click | 外层点击事件回调 | event: Event |
+| close | 关闭通知栏时触发 | event: Event |

ファイルの差分が大きいため隠しています
+ 119 - 0
src/packages/__VUE/noticebar/index.scss


+ 0 - 0
src/packages/__VUE/noticebar/index.taro.vue


+ 410 - 0
src/packages/__VUE/noticebar/index.vue

@@ -0,0 +1,410 @@
+<template>
+  <view :class="classes">
+    <view
+      v-show="showNoticeBar"
+      class="nut-noticebar-page"
+      :class="{ withicon: closeMode, close: closeMode, wrapable: wrapable }"
+      :style="barStyle"
+      @click="handleClick"
+      v-if="direction == 'across'"
+    >
+      <view
+        class="left-icon"
+        v-if="iconShow"
+        :style="{ 'background-image': `url(${iconBg})` }"
+      >
+        <nut-icon
+          name="notice"
+          size="16"
+          :color="color"
+          v-if="!iconBg"
+        ></nut-icon>
+      </view>
+      <view ref="wrap" class="wrap">
+        <view
+          ref="content"
+          class="content"
+          :class="[
+            animationClass,
+            { 'nut-ellipsis': !scrollable && !wrapable }
+          ]"
+          :style="contentStyle"
+          @animationend="onAnimationEnd"
+          @webkitAnimationEnd="onAnimationEnd"
+        >
+          <slot>{{ text }}</slot>
+        </view>
+      </view>
+      <view v-if="closeMode" class="right-icon" @click.stop="onClickIcon">
+        <nut-icon name="close" size="11" :color="color"></nut-icon>
+      </view>
+    </view>
+
+    <view
+      class="nut-noticebar-vertical"
+      v-if="scrollList.length > 0 && direction == 'vertical'"
+      :style="barStyle"
+    >
+      <template v-if="slots.default">
+        <view class="horseLamp_list" :style="horseLampStyle">
+          <ScrollItem
+            v-for="(item, index) in scrollList"
+            v-bind:key="index"
+            :style="{ height: height + 'px', 'line-height': height + 'px' }"
+            :item="item"
+          ></ScrollItem>
+        </view>
+      </template>
+
+      <template v-else>
+        <ul class="horseLamp_list" :style="horseLampStyle">
+          <li
+            class="horseLamp_list_item"
+            v-for="(item, index) in scrollList"
+            :key="index"
+            :style="{ height: height }"
+            @click="go(item)"
+          >
+            {{ item }}
+          </li>
+        </ul>
+      </template>
+
+      <view class="go" @click="!slots.rightIcon && handleClickIcon()">
+        <template v-if="slots.rightIcon">
+          <slot name="rightIcon"></slot>
+        </template>
+        <template v-else-if="closeMode">
+          <nut-icon type="cross" :color="color" size="11px"></nut-icon>
+        </template>
+      </view>
+    </view>
+  </view>
+</template>
+<script lang="ts">
+import {
+  toRefs,
+  onMounted,
+  onUnmounted,
+  reactive,
+  computed,
+  CSSProperties,
+  onActivated,
+  onDeactivated,
+  ref,
+  watch,
+  h
+} from 'vue';
+import { createComponent } from '../../utils/create';
+const { componentName, create } = createComponent('noticebar');
+
+export default create({
+  props: {
+    // 滚动方向  across 横向 vertical 纵向
+    direction: {
+      type: String,
+      default: 'across'
+    },
+    list: {
+      type: Array,
+      default: () => {
+        return [];
+      }
+    },
+    standTime: {
+      type: Number,
+      default: 1000
+    },
+    complexAm: {
+      type: Boolean,
+      default: false
+    },
+    height: {
+      type: Number,
+      default: 40
+    },
+    text: {
+      type: String,
+      default: ''
+    },
+    closeMode: {
+      type: Boolean,
+      default: false
+    },
+    wrapable: {
+      type: Boolean,
+      default: false
+    },
+    leftIcon: { type: String, default: '' },
+    color: {
+      type: String,
+      default: '#F9911B'
+    },
+    background: {
+      type: String,
+      default: 'rgba(254,250,216,1)'
+    },
+    delay: {
+      type: [String, Number],
+      default: 1
+    },
+    scrollable: {
+      type: Boolean,
+      default: true
+    },
+    speed: {
+      type: Number,
+      default: 50
+    }
+  },
+  components: {
+    ScrollItem: function (props) {
+      props.item.props.style = props.style;
+      return h(props.item);
+    }
+  },
+  emits: ['click', 'close'],
+
+  setup(props, { emit, slots }) {
+    console.log('componentName', componentName);
+
+    const wrap = ref<null | HTMLElement>(null);
+    const content = ref<null | HTMLElement>(null);
+
+    const state = reactive({
+      wrapWidth: 0,
+      firstRound: true,
+      duration: 0,
+      offsetWidth: 0,
+      showNoticeBar: true,
+      animationClass: '',
+
+      animate: false,
+      scrollList: [],
+      distance: 0,
+      timer: null,
+      keepAlive: false
+    });
+
+    const classes = computed(() => {
+      const prefixCls = componentName;
+      return {
+        [prefixCls]: true
+      };
+    });
+
+    const iconShow = computed(() => {
+      if (props.leftIcon == 'close') {
+        return false;
+      } else {
+        return true;
+      }
+    });
+
+    const barStyle = computed(() => {
+      let style: {
+        [props: string]: any;
+      } = {
+        color: props.color,
+        background: props.background
+      };
+
+      if (props.direction == 'vertical') {
+        style.height = `${props.height}px`;
+      }
+      return style;
+    });
+
+    const contentStyle = computed(() => {
+      return {
+        paddingLeft: state.firstRound ? 0 : state.wrapWidth + 'px',
+        animationDelay: (state.firstRound ? props.delay : 0) + 's',
+        animationDuration: state.duration + 's'
+      };
+    });
+    const iconBg = computed(() => {
+      let iconBg = null;
+      if (props.leftIcon) {
+        iconBg = props.leftIcon;
+      }
+      return iconBg;
+    });
+    const horseLampStyle = computed(() => {
+      let styles = {};
+      if (props.complexAm) {
+        styles = {
+          transform: `translateY(${state.distance}px)`
+        };
+      } else {
+        if (state.animate) {
+          styles = {
+            transition: `all ${~~(props.height / props.speed / 4)}s`,
+            'margin-top': `-${props.height}px`
+          };
+        }
+      }
+      return styles;
+    });
+
+    watch(
+      () => props.text,
+      (value) => {
+        initScrollWrap(value);
+      }
+    );
+
+    watch(
+      () => props.list,
+      (value) => {
+        state.scrollList = [].concat(value as any);
+      }
+    );
+
+    const initScrollWrap = (value: string) => {
+      if (state.showNoticeBar == false) {
+        return;
+      }
+      setTimeout(() => {
+        if (!wrap.value || !content.value) {
+          return;
+        }
+        const wrapWidth = wrap.value.getBoundingClientRect().width;
+
+        const offsetWidth = content.value.getBoundingClientRect().width;
+
+        if (props.scrollable && offsetWidth > wrapWidth) {
+          state.wrapWidth = wrapWidth;
+          state.offsetWidth = offsetWidth;
+
+          state.duration = offsetWidth / props.speed;
+          state.animationClass = 'play';
+        } else {
+          state.animationClass = '';
+        }
+      });
+    };
+    const handleClick = (event: Event) => {
+      emit('click', event);
+    };
+
+    const onClickIcon = (event: Event) => {
+      state.showNoticeBar = !props.closeMode;
+      emit('close', event);
+    };
+
+    const onAnimationEnd = () => {
+      state.firstRound = false;
+
+      setTimeout(() => {
+        state.duration = (state.offsetWidth + state.wrapWidth) / props.speed;
+        state.animationClass = 'play-infinite';
+      }, 0);
+    };
+
+    /**
+     * 利益点滚动方式一
+     */
+    const startRollEasy = () => {
+      showhorseLamp();
+      (state.timer as any) = setInterval(
+        showhorseLamp,
+        ~~(props.height / props.speed / 4) * 1000 + props.standTime
+      );
+    };
+    const showhorseLamp = () => {
+      state.animate = true;
+      setTimeout(() => {
+        state.scrollList.push(state.scrollList[0]);
+        state.scrollList.shift();
+        state.animate = false;
+      }, ~~(props.height / props.speed / 4) * 1000);
+    };
+
+    const startRoll = () => {
+      (state.timer as any) = setInterval(() => {
+        let chunk = 100;
+        for (let i = 0; i < chunk; i++) {
+          scroll(i, i < chunk - 1 ? false : true);
+        }
+      }, props.standTime + 100 * props.speed);
+    };
+    const scroll = (n: number, last: boolean) => {
+      setTimeout(() => {
+        state.distance -= props.height / 100;
+        if (last) {
+          state.scrollList.push(state.scrollList[0]);
+          state.scrollList.shift();
+          state.distance = 0;
+        }
+      }, n * props.speed);
+    };
+    /**
+     * 点击滚动单元
+     */
+    const go = (item: any) => {
+      emit('click', item);
+    };
+
+    const handleClickIcon = () => {
+      emit('close', state.scrollList[0]);
+    };
+
+    onMounted(() => {
+      console.log(props.direction);
+      if (props.direction == 'vertical') {
+        if (slots.default) {
+          state.scrollList = [].concat(slots.default()[0].children as any);
+        } else {
+          state.scrollList = [].concat(props.list as any);
+        }
+
+        console.log(state.scrollList);
+
+        setTimeout(() => {
+          props.complexAm ? startRoll() : startRollEasy();
+        }, props.standTime);
+      } else {
+        initScrollWrap(props.text);
+      }
+    });
+
+    onActivated(() => {
+      if (state.keepAlive) {
+        state.keepAlive = false;
+      }
+    });
+
+    onDeactivated(() => {
+      state.keepAlive = true;
+      clearInterval(state.timer as any);
+    });
+
+    onUnmounted(() => {
+      clearInterval(state.timer as any);
+    });
+
+    return {
+      ...toRefs(props),
+      ...toRefs(state),
+      classes,
+      iconShow,
+      barStyle,
+      contentStyle,
+      iconBg,
+      horseLampStyle,
+      wrap,
+      content,
+      handleClick,
+      onClickIcon,
+      onAnimationEnd,
+      go,
+      handleClickIcon,
+      slots
+    };
+  }
+});
+</script>
+
+<style lang="scss">
+@import 'index.scss';
+</style>

+ 4 - 2
src/packages/__VUE/picker/doc.taro.md

@@ -3,8 +3,10 @@
 ### 介绍
     
 提供多个选项集合供用户选择其中一项。
+
+#### 直接使用 Taro 现有 Picker 组件开发 [参考文档](https://docs.taro.zone/docs/components/forms/picker)
     
-## 安装
+<!-- ## 安装
 ```javascript
 import { createApp } from 'vue';
 import { Picker } from '@nutui/nutui-taro';
@@ -106,6 +108,6 @@ export default createDemo({
     
 | 事件名  | 说明             | 回调参数     |
 |---------|------------------|--------------|
-| confirm | 点击确认时候触发 | event: Event |
+| confirm | 点击确认时候触发 | event: Event | -->
 
     

+ 3 - 3
src/packages/__VUE/swiper/doc.taro.md

@@ -4,7 +4,7 @@
 
 常用于一组图片或卡片轮播,当内容空间不足时,可以用走马灯的形式进行收纳,进行轮播展现。
 
-### 安装
+<!-- ### 安装
 
 ```javascript
 import { createApp } from 'vue';
@@ -83,7 +83,7 @@ app.use(Swiper);
     <img src="https://storage.360buyimg.com/jdc-article/fristfabu.jpg" alt="" />
   </nut-swiper-item>
 </nut-swiper>
-```
+``` -->
 
 
-#### API [参考文档](https://docs.taro.zone/docs/components/viewContainer/swiper)
+#### 直接使用 Taro 现有 Swiper 组件开发 [参考文档](https://docs.taro.zone/docs/components/viewContainer/swiper)

+ 51 - 37
src/packages/__VUE/tab/doc.md

@@ -2,21 +2,35 @@
 
 常用于平级区域大块内容的的收纳和展现,支持内嵌标签形式和渲染循环数据形式。
 
+## 安装
+
+```js
+import { createApp } from 'vue';
+// vue
+import { Tab, TabPanel,Swiper } from '@nutui/nutui';
+// taro
+import { Tab, TabPanel,Swiper } from '@nutui/nutui-taro';
+
+const app = createApp();
+app.use(Tab).use(TabPanel).use(Swiper);
+
+```
+
 ## 基础样式,默认 tab-title 宽度均分相等
 
 ```html
 <nut-tab>
   <nut-tab-panel tab-title="全部"
-    ><p class="content">这里是页签全部内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签全部内容</p></nut-tab-panel
   >
   <nut-tab-panel tab-title="待付款"
-    ><p class="content">这里是页签待付款内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签待付款内容</p></nut-tab-panel
   >
   <nut-tab-panel tab-title="待收获"
-    ><p class="content">这里是页签待收获内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签待收获内容</p></nut-tab-panel
   >
   <nut-tab-panel tab-title="已完成"
-    ><p class="content">这里是页签已完成内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签已完成内容</p></nut-tab-panel
   >
 </nut-tab>
 ```
@@ -29,16 +43,16 @@ switchTab 监听切换 tab 返回事件
 ```html
 <nut-tab :defaultIndex="1" @switchTab="switchTab">
   <nut-tab-panel tab-title="全部"
-    ><p class="content">这里是页签全部内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签全部内容</p></nut-tab-panel
   >
   <nut-tab-panel tab-title="待付款"
-    ><p class="content">这里是页签待付款内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签待付款内容</p></nut-tab-panel
   >
   <nut-tab-panel tab-title="待收获"
-    ><p class="content">这里是页签待收获内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签待收获内容</p></nut-tab-panel
   >
   <nut-tab-panel tab-title="已完成"
-    ><p class="content">这里是页签已完成内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签已完成内容</p></nut-tab-panel
   >
 </nut-tab>
 <script lang="ts">
@@ -62,16 +76,16 @@ switchTab 监听切换 tab 返回事件
 ```html
 <nut-tab :animatedTime="500">
   <nut-tab-panel tab-title="全部"
-    ><p class="content">这里是页签全部内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签全部内容</p></nut-tab-panel
   >
   <nut-tab-panel tab-title="待付款"
-    ><p class="content">这里是页签待付款内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签待付款内容</p></nut-tab-panel
   >
   <nut-tab-panel tab-title="待收获"
-    ><p class="content">这里是页签待收获内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签待收获内容</p></nut-tab-panel
   >
   <nut-tab-panel tab-title="已完成"
-    ><p class="content">这里是页签已完成内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签已完成内容</p></nut-tab-panel
   >
 </nut-tab>
 ```
@@ -81,16 +95,16 @@ switchTab 监听切换 tab 返回事件
 ```html
 <nut-tab :no-swiping="true">
   <nut-tab-panel tab-title="全部"
-    ><p class="content">这里是页签全部内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签全部内容</p></nut-tab-panel
   >
   <nut-tab-panel tab-title="待付款"
-    ><p class="content">这里是页签待付款内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签待付款内容</p></nut-tab-panel
   >
   <nut-tab-panel tab-title="待收获"
-    ><p class="content">这里是页签待收获内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签待收获内容</p></nut-tab-panel
   >
   <nut-tab-panel tab-title="已完成"
-    ><p class="content">这里是页签已完成内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签已完成内容</p></nut-tab-panel
   >
 </nut-tab>
 ```
@@ -100,24 +114,24 @@ switchTab 监听切换 tab 返回事件
 切换时会自动将当前标签居中。
 
 ```html
-<nut-tab :animatedTime="500">
+<nut-tab :animatedTime="500" scrollType="scroll">
   <nut-tab-panel tab-title="全部"
-    ><p class="content">这里是页签全部内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签全部内容</p></nut-tab-panel
   >
   <nut-tab-panel tab-title="待付款"
-    ><p class="content">这里是页签待付款内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签待付款内容</p></nut-tab-panel
   >
   <nut-tab-panel tab-title="待收获"
-    ><p class="content">这里是页签待收获内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签待收获内容</p></nut-tab-panel
   >
   <nut-tab-panel tab-title="已完成"
-    ><p class="content">这里是页签已完成内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签已完成内容</p></nut-tab-panel
   >
   <nut-tab-panel tab-title="已取消"
-    ><p class="content">这里是页签已取消内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签已取消内容</p></nut-tab-panel
   >
   <nut-tab-panel tab-title="待评价"
-    ><p class="content">这里是页签待评价内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签待评价内容</p></nut-tab-panel
   >
 </nut-tab>
 ```
@@ -128,22 +142,22 @@ switchTab 监听切换 tab 返回事件
 <nut-tab>
   <nut-tab-panel tab-title="全部">
     <template v-slot:header><nut-icon name="dongdong"></nut-icon></template>
-    <p class="content">这里是页签全部内容</p>
+    <p class="content-tab">这里是页签全部内容</p>
   </nut-tab-panel>
   <nut-tab-panel tab-title="待付款"
-    ><p class="content">这里是页签待付款内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签待付款内容</p></nut-tab-panel
   >
   <nut-tab-panel tab-title="待收获"
-    ><p class="content">这里是页签待收获内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签待收获内容</p></nut-tab-panel
   >
   <nut-tab-panel tab-title="已完成"
-    ><p class="content">这里是页签已完成内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签已完成内容</p></nut-tab-panel
   >
   <nut-tab-panel tab-title="已取消"
-    ><p class="content">这里是页签已取消内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签已取消内容</p></nut-tab-panel
   >
   <nut-tab-panel tab-title="待评价"
-    ><p class="content">这里是页签待评价内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签待评价内容</p></nut-tab-panel
   >
 </nut-tab>
 ```
@@ -153,25 +167,25 @@ switchTab 监听切换 tab 返回事件
 ```html
 <nut-tab direction="vertical" :animatedTime="500" :defaultIndex="2">
   <nut-tab-panel tab-title="页签一"
-    ><p class="content">这里是页签一内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签一内容</p></nut-tab-panel
   >
   <nut-tab-panel tab-title="页签二"
-    ><p class="content">这里是页签二内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签二内容</p></nut-tab-panel
   >
   <nut-tab-panel tab-title="页签三"
-    ><p class="content">这里是页签三内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签三内容</p></nut-tab-panel
   >
   <nut-tab-panel tab-title="页签四"
-    ><p class="content">这里是页签四内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签四内容</p></nut-tab-panel
   >
   <nut-tab-panel tab-title="页签五"
-    ><p class="content">这里是页签五内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签五内容</p></nut-tab-panel
   >
   <nut-tab-panel tab-title="页签六"
-    ><p class="content">这里是页签六内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签六内容</p></nut-tab-panel
   >
   <nut-tab-panel tab-title="页签七"
-    ><p class="content">这里是页签七内容</p></nut-tab-panel
+    ><p class="content-tab">这里是页签七内容</p></nut-tab-panel
   >
 </nut-tab>
 ```
@@ -181,7 +195,7 @@ switchTab 监听切换 tab 返回事件
 ```html
 <nut-tab :animatedTime="500" v-if="editList.length>0">
     <nut-tab-panel :tab-title="item.title" v-for="(item,index) in editList" :key="index">
-      <p class="content">这里是页签{{index}}内容</p>
+      <p class="content-tab">这里是页签{{index}}内容</p>
     </nut-tab-panel>
 </nut-tab>
 <nut-button type="primary" @click="changeList">改变数据</nut-button>

+ 6 - 6
src/packages/__VUE/tab/index.scss

@@ -179,11 +179,11 @@
   }
 }
 
-.horize {
-  display: flex;
-  flex-direction: row;
-  flex-wrap: nowrap;
-}
-.content {
+// .horize {
+//   display: flex;
+//   flex-direction: row;
+//   flex-wrap: nowrap;
+// }
+.content-tab {
   padding: 10px;
 }

+ 7 - 6
src/packages/utils/raf.ts

@@ -1,14 +1,15 @@
+const _window = window as any;
 function requestAniFrame() {
-  if (typeof window !== 'undefined') {
+  if (typeof _window !== 'undefined') {
     return (
-      window.requestAnimationFrame ||
-      window.webkitRequestAnimationFrame ||
-      function(callback) {
-        window.setTimeout(callback, 1000 / 60);
+      _window.requestAnimationFrame ||
+      _window.webkitRequestAnimationFrame ||
+      function (callback: Function) {
+        _window.setTimeout(callback, 1000 / 60);
       }
     );
   } else {
-    return function(callback: Function) {
+    return function (callback: Function) {
       setTimeout(callback, 1000 / 60);
     };
   }

BIN
src/sites/assets/images/cat-back.png


BIN
src/sites/assets/images/cat-title.png


BIN
src/sites/assets/images/marketing-back.png


BIN
src/sites/assets/images/marketing-title.png


+ 1 - 1
src/sites/doc/components/Footer.vue

@@ -74,7 +74,7 @@
           <div class="vx-box">
             <p class="vx-desc">微信交流群</p>
             <p class="vx-desc">扫码添加好友</p>
-            <img class="img-code" src="../../assets/images/vx-code.png" />
+            <img class="img-code" src="../../assets/images/vx-code1.png" />
             <p class="vx-desc">回复<span class="vx-red">NutUI</span>即刻进群</p>
           </div>
         </div>

+ 1 - 1
src/sites/doc/components/Header.vue

@@ -247,7 +247,7 @@ export default defineComponent({
         background-size: 26px;
 
         &.gitee {
-          margin-left: 4px;
+          margin-left: 8px;
           background-image: url('../../assets/images/icon-gitee.png');
         }
       }

+ 164 - 3
src/sites/doc/views/Main.vue

@@ -79,6 +79,41 @@
       </div>
     </div>
 
+    <!-- nutui-cat / nutui-营销 -->
+    <div class="doc-content-cat-marketing">
+      <div class="cat-content">
+        <div class="cat-content-left">
+          <img src="./../../assets/images/cat-back.png" alt="" />
+        </div>
+        <div class="cat-content-right">
+          <div class="cat-content-right-title">
+            <img src="./../../assets/images/cat-title.png" alt="" />
+          </div>
+          <p class="cat-content-right-desc">基于NutUI的大促组件库</p>
+          <div class="cat-content-right-godetail" @click="toDetail"
+            >查看详情</div
+          >
+        </div>
+      </div>
+      <div class="marketing-content">
+        <div class="marketing-content-left">
+          <img src="./../../assets/images/marketing-back.png" alt="" />
+        </div>
+        <div class="marketing-content-right">
+          <div class="marketing-content-right-title">
+            <img src="./../../assets/images/marketing-title.png" alt="" />
+          </div>
+          <p class="marketing-content-right-desc">基于NutUI的营销组件库</p>
+          <div class="marketing-content-right-godetail" @click="goAwait"
+            >敬请期待</div
+          >
+        </div>
+        <div class="marketing-content-mask" v-if="showAwait" @click="hideAwait">
+          正在建设中,敬请期待~
+        </div>
+      </div>
+    </div>
+
     <div class="doc-content-cases" v-if="casesImages.length">
       <div class="doc-content-hd">
         <h4 class="doc-content-title">赋能案例</h4>
@@ -172,7 +207,8 @@ export default defineComponent({
       casesImages: new Array(),
       currentCaseItem: {},
       currentCaseIndex: 0,
-      localTheme: localStorage.getItem('nutui-theme-color')
+      localTheme: localStorage.getItem('nutui-theme-color'),
+      showAwait: false
     });
     let caseSwiper: any = null;
     onMounted(() => {
@@ -225,7 +261,12 @@ export default defineComponent({
         }
       });
     });
-
+    const goAwait = () => {
+      data.showAwait = true;
+    };
+    const hideAwait = () => {
+      data.showAwait = false;
+    };
     const onLeft = () => {
       caseSwiper.slidePrev();
     };
@@ -250,6 +291,9 @@ export default defineComponent({
     function toIntro() {
       router.push({ path: '/intro' });
     }
+    const toDetail = () => {
+      window.open('/cat');
+    };
     return {
       toIntro,
       ...toRefs(data),
@@ -257,7 +301,10 @@ export default defineComponent({
       themeNameValue,
       toLink,
       onLeft,
-      onRight
+      onRight,
+      toDetail,
+      goAwait,
+      hideAwait
     };
   }
 });
@@ -379,6 +426,120 @@ export default defineComponent({
       }
     }
   }
+  &-cat-marketing {
+    width: 1200px;
+    margin: 0 auto 90px;
+    display: flex;
+    .cat-content,
+    .marketing-content {
+      width: 585px;
+      height: 270px;
+      background: linear-gradient(
+        130.16deg,
+        rgba(249, 188, 203, 1) 0%,
+        rgba(247, 239, 247, 1) 26.666302447552447%,
+        rgba(241, 240, 246, 1) 66.69307255244755%,
+        rgba(180, 228, 228, 1) 100%
+      );
+      border-radius: 4px 4px 4px 0 4px;
+      margin-left: 44px;
+    }
+    .cat-content,
+    .marketing-content {
+      margin-left: 0px;
+      display: flex;
+      align-items: center;
+      &-left {
+        height: 182px;
+        width: 270px;
+        margin-left: 14px;
+        img {
+          height: 100%;
+          width: 100%;
+        }
+      }
+      &-right {
+        height: 182px;
+        width: 233px;
+        margin-left: 37px;
+        font-family: PingFangSC;
+        font-weight: normal;
+        padding-top: 11px;
+        box-sizing: border-box;
+        &-title {
+          img {
+            height: 46px;
+            width: 177px;
+          }
+        }
+        &-desc {
+          margin-top: 26px;
+          font-size: 18px;
+          color: rgba(51, 51, 51, 1);
+        }
+        &-godetail {
+          width: 130px;
+          height: 35px;
+          margin-top: 24px;
+          line-height: 35px;
+          text-align: center;
+          font-size: 19px;
+          cursor: pointer;
+          color: rgba(255, 255, 255, 1);
+          background: linear-gradient(
+            135deg,
+            rgba(255, 28, 101, 1) 0%,
+            rgba(255, 133, 202, 1) 67.83430752051981%,
+            rgba(255, 142, 155, 1) 87.35307751528254%,
+            rgba(255, 169, 151, 1) 100%
+          );
+          border-radius: 17px;
+        }
+      }
+    }
+    .marketing-content {
+      position: relative;
+      margin-left: 44px;
+      background: linear-gradient(
+        130.16deg,
+        rgba(219, 210, 255, 1) 0%,
+        rgba(247, 239, 247, 1) 26.666302447552447%,
+        rgba(241, 240, 246, 1) 66.69307255244755%,
+        rgba(255, 236, 203, 1) 100%
+      );
+      &-left {
+        height: 196px;
+        width: 243px;
+        margin-left: 28px;
+      }
+      &-right {
+        height: 196px;
+        padding-top: 20px;
+        &-godetail {
+          background: linear-gradient(
+            135deg,
+            rgba(114, 60, 255, 1) 0%,
+            rgba(111, 58, 255, 1) 63.49938195167575%,
+            rgba(150, 110, 255, 1) 87.35307751528254%,
+            rgba(149, 117, 241, 1) 100%
+          );
+        }
+      }
+      &-mask {
+        position: absolute;
+        top: 0px;
+        left: 0px;
+        height: 100%;
+        width: 100%;
+        background: rgba(0, 0, 0, 0.52);
+        border-radius: 4px 4px 4px 0 4px;
+        text-align: center;
+        line-height: 270px;
+        font-size: 30px;
+        color: #ffffff;
+      }
+    }
+  }
   &-cases {
     width: 1200px;
     overflow: hidden;

+ 6 - 0
src/sites/mobile-taro/vue/project.private.config.json

@@ -29,6 +29,12 @@
           "pathName": "dentry/pages/countup/index",
           "query": "",
           "scene": null
+        },
+        {
+          "name": "feedback/pages/collapse/index",
+          "pathName": "feedback/pages/collapse/index",
+          "query": "",
+          "scene": null
         }
       ]
     }

+ 11 - 0
src/sites/mobile-taro/vue/src/base/pages/cell/index.vue

@@ -35,6 +35,17 @@
       </nut-cell>
     </nut-cell-group>
 
+    <nut-cell-group title="自定义左侧 Icon 区域">
+      <nut-cell title="图片">
+        <template v-slot:icon>
+          <img
+            class="nut-icon"
+            src="https://img11.360buyimg.com/imagetools/jfs/t1/137646/13/7132/1648/5f4c748bE43da8ddd/a3f06d51dcae7b60.png"
+          />
+        </template>
+      </nut-cell>
+    </nut-cell-group>
+
     <h2>展示图标</h2>
     <nut-cell title="姓名" icon="my" desc="张三" isLink> </nut-cell>
     <h2>只展示 desc ,可通过 desc-text-align 调整内容位置</h2>

+ 1 - 0
src/sites/mobile-taro/vue/src/feedback/pages/collapse/index.vue

@@ -23,6 +23,7 @@
     <h2>手风琴</h2>
     <nut-collapse v-model:active="active2" :accordion="true" icon="down-arrow">
       <nut-collapse-item :title="title1" :name="1">
+        <template v-slot:sTitle> 文本测试 </template>
         华为终端操作系统EMUI 11发布,9月11日正式开启
       </nut-collapse-item>
       <nut-collapse-item :title="title2" :name="2" :sub-title="subTitle">

+ 1 - 1
src/sites/mobile/components/IndexTaro.vue

@@ -29,7 +29,7 @@ export default defineComponent({
 .index {
   height: 100%;
   width: 100%;
-  padding-top: 30px;
+  padding-top: 60px;
 
   &-header {
     display: flex;