Browse Source

first commit

kaileyhao 2 years ago
commit
2f97920583
100 changed files with 7008 additions and 0 deletions
  1. 0 0
      README.md
  2. 170 0
      app.js
  3. 73 0
      app.json
  4. 17 0
      app.wxss
  5. BIN
      assets/images/iconfont-about-active.png
  6. BIN
      assets/images/iconfont-about.png
  7. BIN
      assets/images/iconfont-demo-active.png
  8. BIN
      assets/images/iconfont-demo.png
  9. BIN
      assets/images/iconfont-empty.png
  10. BIN
      assets/images/iconfont-order.png
  11. BIN
      assets/images/logo.png
  12. 105 0
      assets/styles/skyvow.wxss
  13. 1019 0
      assets/styles/weui.wxss
  14. 107 0
      dist/accordion-group/index.js
  15. 6 0
      dist/accordion-group/index.json
  16. 3 0
      dist/accordion-group/index.wxml
  17. 4 0
      dist/accordion-group/index.wxss
  18. 52 0
      dist/accordion/index.js
  19. 3 0
      dist/accordion/index.json
  20. 18 0
      dist/accordion/index.wxml
  21. 87 0
      dist/accordion/index.wxss
  22. 71 0
      dist/actionsheet/index.js
  23. 7 0
      dist/actionsheet/index.json
  24. 17 0
      dist/actionsheet/index.wxml
  25. 115 0
      dist/actionsheet/index.wxss
  26. 44 0
      dist/alert/index.js
  27. 6 0
      dist/alert/index.json
  28. 25 0
      dist/alert/index.wxml
  29. 67 0
      dist/alert/index.wxss
  30. 407 0
      dist/animation-group/index.js
  31. 3 0
      dist/animation-group/index.json
  32. 3 0
      dist/animation-group/index.wxml
  33. 250 0
      dist/animation-group/index.wxss
  34. 54 0
      dist/avatar/index.js
  35. 3 0
      dist/avatar/index.json
  36. 6 0
      dist/avatar/index.wxml
  37. 53 0
      dist/avatar/index.wxss
  38. 43 0
      dist/backdrop/index.js
  39. 6 0
      dist/backdrop/index.json
  40. 1 0
      dist/backdrop/index.wxml
  41. 15 0
      dist/backdrop/index.wxss
  42. 40 0
      dist/badge/index.js
  43. 3 0
      dist/badge/index.json
  44. 10 0
      dist/badge/index.wxml
  45. 116 0
      dist/badge/index.wxss
  46. 207 0
      dist/barcode/barcode.js
  47. 51 0
      dist/barcode/index.js
  48. 3 0
      dist/barcode/index.json
  49. 1 0
      dist/barcode/index.wxml
  50. 0 0
      dist/barcode/index.wxss
  51. 98 0
      dist/button/index.js
  52. 3 0
      dist/button/index.json
  53. 22 0
      dist/button/index.wxml
  54. 309 0
      dist/button/index.wxss
  55. 717 0
      dist/calendar/index.js
  56. 7 0
      dist/calendar/index.json
  57. 53 0
      dist/calendar/index.wxml
  58. 322 0
      dist/calendar/index.wxss
  59. 32 0
      dist/card/index.js
  60. 3 0
      dist/card/index.json
  61. 15 0
      dist/card/index.wxml
  62. 101 0
      dist/card/index.wxss
  63. 38 0
      dist/cell-group/index.js
  64. 3 0
      dist/cell-group/index.json
  65. 7 0
      dist/cell-group/index.wxml
  66. 33 0
      dist/cell-group/index.wxss
  67. 79 0
      dist/cell/index.js
  68. 3 0
      dist/cell/index.json
  69. 21 0
      dist/cell/index.wxml
  70. 78 0
      dist/cell/index.wxss
  71. 46 0
      dist/checkbox-group/index.js
  72. 6 0
      dist/checkbox-group/index.json
  73. 3 0
      dist/checkbox-group/index.wxml
  74. 0 0
      dist/checkbox-group/index.wxss
  75. 76 0
      dist/checkbox/index.js
  76. 6 0
      dist/checkbox/index.json
  77. 6 0
      dist/checkbox/index.wxml
  78. 17 0
      dist/checkbox/index.wxss
  79. 229 0
      dist/circle/index.js
  80. 3 0
      dist/circle/index.json
  81. 6 0
      dist/circle/index.wxml
  82. 14 0
      dist/circle/index.wxss
  83. 38 0
      dist/col/index.js
  84. 3 0
      dist/col/index.json
  85. 3 0
      dist/col/index.wxml
  86. 161 0
      dist/col/index.wxss
  87. 176 0
      dist/countdown/index.js
  88. 220 0
      dist/countup/index.js
  89. 193 0
      dist/dialog/index.js
  90. 6 0
      dist/dialog/index.json
  91. 23 0
      dist/dialog/index.wxml
  92. 95 0
      dist/dialog/index.wxss
  93. 21 0
      dist/divider/index.js
  94. 3 0
      dist/divider/index.json
  95. 6 0
      dist/divider/index.wxml
  96. 54 0
      dist/divider/index.wxss
  97. 268 0
      dist/filterbar/index.js
  98. 11 0
      dist/filterbar/index.json
  99. 80 0
      dist/filterbar/index.wxml
  100. 0 0
      dist/filterbar/index.wxss

+ 0 - 0
README.md


+ 170 - 0
app.js

@@ -0,0 +1,170 @@
+//app.js
+App({
+  onLaunch: function () {
+  
+    //红点提示公用方法
+    var that=this
+    setInterval(function(){
+
+      if (that.globalData.userToken!=""){
+        console.log(that.globalData.userToken+'111111111111111111111111111')
+        wx.request({
+          method: "get",
+          url: that.globalData.localApi + '/saapi/chat/unread',
+          data: {
+            token: that.globalData.userToken,
+          },
+          header: {
+            "Content-Type": "application/json"
+          },
+          success: function (res) {
+            console.log(res)
+            if (res.data.code == 1) {
+              //聊天消息 
+              that.globalData.chatAllNum = res.data.data.next_count + res.data.data.previous_count + res.data.data.pay_notice;
+              that.globalData.chatPreNum = res.data.data.previous_count;
+              that.globalData.chatNextNum = res.data.data.next_count;
+
+
+              //系统消息
+              that.globalData.stytemRadio = res.data.data.sys_count;
+              if (res.data.data.sys_count == 0) {
+                wx.hideTabBarRedDot({
+                  index: 2,
+                });
+              } else {
+                // wx.setTabBarBadge({
+                //   index: 2,
+                //   text: String(res.data.data.sys_count)
+                // });
+              }
+            } else {
+              // wx.showModal({
+              //   content: res.data.msg,
+              //   showCancel: false,
+              //   success: function (res) {
+              //     if (res.confirm) {
+              //     }
+              //   }
+              // });
+            }
+          },
+          fail: function (err) {
+            console.log(err)
+          }
+        });
+      }
+      
+    }, that.globalData.timer)
+    
+    
+
+    // 展示本地存储能力
+    var logs = wx.getStorageSync('logs') || []
+    logs.unshift(Date.now())
+    wx.setStorageSync('logs', logs)
+
+    // 登录
+    wx.login({
+      success: res => {
+        //console.log(res)
+        // 发送 res.code 到后台换取 openId, sessionKey, unionId
+      }
+    })
+
+    //看看缓存是否在
+    wx.checkSession({
+      success() {
+        //console.log(10)
+        //session_key 未过期,并且在本生命周期一直有效
+      },
+      fail() {
+        // session_key 已经失效,需要重新执行登录流程
+        //console.log(11)
+        //wx.login() //重新登录
+      }
+    })
+
+
+    // 获取用户信息
+    wx.getSetting({
+      success: res => {
+        if (res.authSetting['scope.userInfo']) {
+          // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
+          wx.getUserInfo({
+            success: res => {            
+              // 可以将 res 发送给后台解码出 unionId
+              this.globalData.userInfo = res.userInfo
+              
+              // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
+              // 所以此处加入 callback 以防止这种情况
+              if (this.userInfoReadyCallback) {
+                this.userInfoReadyCallback(res)
+              }
+            }, 
+          })
+          
+          console.log("用户有授权")
+        }else{
+          wx.reLaunch({
+            url: '../auth/index'
+          })
+          console.log("用户还没有授权")
+        }
+      },
+      
+    })
+
+    
+  },
+
+
+  globalData: {
+    localDomin:"https://test.ttq.so",   //图片地址
+    //localApi: "https://tanghua.ttq.so",   //接口地址正式网
+    localApi:"https://thtest.ttq.so",   //接口地址测试网
+    userInfo: null,
+    userToken: "",                        //全局TOKEN  e84cf729ec649cb2e71207bfe878be75
+
+    latitude:"",
+    longitude:"",
+
+    orderRest:0,                       //判断是否是订单返回后丢瓶子状态 0 否  1是   
+    returnBack:0,         //订单,或者下单回退页面,如果为1,就代表从扔瓶子页面进去了,如果为0,就代表直接返回就行
+ 
+
+    ttqBind:1,
+    ttqImg:"",
+    ttqNickName:"",
+
+    jumpHref: "",
+
+
+    chatAllNum:0,
+    chatPreNum: 0,
+    chatNextNum: 0,
+    stytemRadio:0,
+    timer:3000,    //延时请求接口 3000
+    timerChild:100,            //100
+
+    bottleShow:false,   //判断是否用户第一次进来展示漂流信息 
+
+    province:"",
+    city:"",
+    district:"",
+
+    name:"",
+    tel:"",
+    addressDesc:"",
+    message:"",
+    title: '缘分糖化漂流',
+    desc: '全国糖友都在参与!你也来测糖化识糖友吧~',
+    path: "/pages/index/index",
+    imageUrl: "../images/shareImg.png"
+
+
+  }
+
+})
+
+

+ 73 - 0
app.json

@@ -0,0 +1,73 @@
+{
+  "pages":[
+    
+    "pages/index/index",
+    "pages/driftingRecord/index",
+    "pages/driftingOrder/index",
+    "pages/driftingProcess/index",
+    "pages/vedioPlay/index",
+    "pages/animation/index",
+    "pages/myBottle/index",
+    "pages/otherBottle/index",
+    "pages/coupon/index",
+    "pages/bind/index",
+    "pages/register/index",
+    "pages/systemMessage/index",
+    "pages/feedBack/index",
+    "pages/helpCoupon/index",
+    
+    "pages/orderDesc/index",
+    "pages/payCosts/index",
+    "pages/editBottle/index",
+    "pages/order/index",
+    "pages/lucky/index",
+    
+    "pages/personCenter/index",
+    "pages/auth/index",
+    "pages/chat/index", 
+   
+    "pages/editBlood/index",
+    "pages/heartAnimation/index",
+    
+    "pages/getLocation/index",  
+    "pages/map/index",
+    "pages/pickBottle/index",
+    "pages/orderSuccess/index",
+    "pages/myOrderList/index",
+    "pages/joinRule/index", 
+    "pages/logs/logs"
+  ],
+
+  "tabBar": {
+    "color":"#929292",
+    "selectedColor":"#11c0f9",
+    "backgroundColor":"#fff",
+    "list": [
+      {
+        "pagePath": "pages/index/index",
+        "text": "首页",
+        "iconPath":"pages/images/icon1.png",
+        "selectedIconPath":"pages/images/icon1-1.png"
+      },
+      {
+        "pagePath": "pages/personCenter/index",
+        "text": "我的",
+        "iconPath": "pages/images/icon3.png",
+        "selectedIconPath": "pages/images/icon3-3.png"
+      }
+    ]
+  },
+
+  "permission": {
+    "scope.userLocation": {
+      "desc": "你的位置信息将用于您扔出瓶子的位置"
+    }
+  },
+
+  "window":{
+    "backgroundTextStyle":"light",
+    "navigationBarBackgroundColor": "#fff",
+    "navigationBarTitleText": "糖化缘分漂流",
+    "navigationBarTextStyle":"black"
+  }
+}

+ 17 - 0
app.wxss

@@ -0,0 +1,17 @@
+/**app.wxss**/
+@import 'assets/styles/weui.wxss';
+@import 'assets/styles/skyvow.wxss';
+@import 'weui.wxss';
+.container {
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: space-between;
+  padding: 100rpx 0;
+  box-sizing: border-box;
+} 
+
+.left{float: left}
+
+.empty{margin-top:100rpx; font-size:32rpx; color:#04a6fa; text-align: center;}

BIN
assets/images/iconfont-about-active.png


BIN
assets/images/iconfont-about.png


BIN
assets/images/iconfont-demo-active.png


BIN
assets/images/iconfont-demo.png


BIN
assets/images/iconfont-empty.png


BIN
assets/images/iconfont-order.png


BIN
assets/images/logo.png


+ 105 - 0
assets/styles/skyvow.wxss

@@ -0,0 +1,105 @@
+page{
+	width: 100%;
+	height: 100%;
+	position: relative;
+	color: #333;
+    background-color: #f8f8f8;
+    font-size: 16px;
+    font-family: -apple-system-font,Helvetica Neue,Helvetica,sans-serif;
+    -ms-text-size-adjust: 100%;
+	-webkit-text-size-adjust: 100%;
+	-webkit-tap-highlight-color: transparent;
+}
+
+.page__hd {
+    padding: 40px;
+}
+
+.page__bd {
+    padding-bottom: 40px;
+}
+
+.page__bd_spacing {
+    padding-left: 15px;
+    padding-right: 15px;
+}
+
+.page__ft{
+    padding-bottom: 10px;
+    text-align: center;
+}
+
+.page__title {
+    text-align: left;
+    font-size: 20px;
+    font-weight: 400;
+}
+
+.page__desc {
+    margin-top: 5px;
+    color: #888888;
+    text-align: left;
+    font-size: 14px;
+}
+
+.placeholder {
+    background-color: #ebebef;
+    color: #bbb;
+    text-align: center;
+    height: 30px;
+    line-height: 30px;
+    width: 100%;
+    box-sizing: border-box;
+}
+
+.sub-title {
+    padding: 30rpx 30rpx 18rpx;
+    font-size: 28rpx;
+    color: #888;
+    width: 100%;
+    box-sizing: border-box;
+}
+
+.button-sp-area {
+    margin: 20px auto 0;
+    width: 80%;
+    text-align: center;
+}
+
+.text-left {
+    text-align: left;
+}
+
+.text-center {
+    text-align: center;
+}
+
+.text-right {
+    text-align: right;
+}
+
+.btn-group {
+    position: relative;
+    z-index: 1010;
+    margin-bottom: 50px;
+}
+
+.logo {
+    padding: 30rpx;
+    text-align: center;
+}
+
+.logo image {
+    width: 200rpx;
+    height: 200rpx;
+}
+
+.logo__text {
+    font-size: 48rpx;
+    font-weight: bold;
+    font-style: italic;
+    background: -webkit-linear-gradient(left, #04BE02 , #2d8cf0);
+    -webkit-background-clip: text;
+    -webkit-text-fill-color: transparent;
+    text-align: center;
+}

File diff suppressed because it is too large
+ 1019 - 0
assets/styles/weui.wxss


+ 107 - 0
dist/accordion-group/index.js

@@ -0,0 +1,107 @@
+Component({
+    externalClasses: ['wux-class'],
+    relations: {
+        '../accordion/index': {
+            type: 'child',
+            linked() {
+                this.changeCurrent()
+            },
+            linkChanged() {
+                this.changeCurrent()
+            },
+            unlinked() {
+                this.changeCurrent()
+            },
+        },
+    },
+    properties: {
+        defaultCurrent: {
+            type: Array,
+            value: [],
+        },
+        current: {
+            type: Array,
+            value: [],
+            observer: 'changeCurrent',
+        },
+        auto: {
+            type: Boolean,
+            value: true,
+        },
+        accordion: {
+            type: Boolean,
+            value: false,
+        },
+        title: {
+            type: String,
+            value: '',
+        },
+        label: {
+            type: String,
+            value: '',
+        },
+    },
+    data: {
+        activeKey: '',
+        keys: [],
+    },
+    methods: {
+        updated(activeKey, condition) {
+            const elements = this.getRelationNodes('../accordion/index')
+
+            if (elements.length > 0) {
+                if (condition) {
+                    this.setData({
+                        activeKey,
+                    })
+
+                    elements.forEach((element, index) => {
+                        const key = element.data.key || String(index)
+                        const current = this.data.accordion ? activeKey[0] === key : activeKey.indexOf(key) !== -1
+
+                        element.changeCurrent(current, key)
+                    })
+                }
+            }
+
+            if (this.data.keys.length !== elements.length) {
+                this.setData({
+                    keys: elements.map((element) => element.data)
+                })
+            }
+        },
+        changeCurrent(activeKey = this.data.current) {
+            this.updated(activeKey, !this.data.auto)
+        },
+        emitEvent(key) {
+            this.triggerEvent('change', {
+                key,
+                keys: this.data.keys,
+            })
+        },
+        setActiveKey(activeKey) {
+            if (this.data.activeKey !== activeKey) {
+                this.updated(activeKey, this.data.auto)
+            }
+
+            this.emitEvent(this.data.accordion ? activeKey[0] : activeKey)
+        },
+        onClickItem(key) {
+            let activeKey = [...this.data.activeKey]
+
+            if (this.data.accordion) {
+                activeKey = activeKey[0] === key ? [] : [key]
+            } else {
+                activeKey = activeKey.indexOf(key) !== -1 ? activeKey.filter((n) => n !== key) : [...activeKey, key]
+            }
+
+            this.setActiveKey(activeKey)
+        },
+    },
+    ready() {
+        const { defaultCurrent, current, auto } = this.data
+        const activeKey = !auto ? current : defaultCurrent
+
+        this.updated(activeKey, true)
+    },
+})

+ 6 - 0
dist/accordion-group/index.json

@@ -0,0 +1,6 @@
+{
+    "component": true,
+    "usingComponents": {
+        "wux-cell-group": "../cell-group/index"
+    }
+}

+ 3 - 0
dist/accordion-group/index.wxml

@@ -0,0 +1,3 @@
+<wux-cell-group wux-class="wux-accordion-group" title="{{ title }}" label="{{ label }}">
+    <slot></slot>
+</wux-cell-group>

+ 4 - 0
dist/accordion-group/index.wxss

@@ -0,0 +1,4 @@
+.wux-accordion-group {
+  position: relative;
+  border: none;
+}

+ 52 - 0
dist/accordion/index.js

@@ -0,0 +1,52 @@
+Component({
+    externalClasses: ['wux-class'],
+    relations: {
+        '../accordion-group/index': {
+            type: 'parent',
+        },
+    },
+    properties: {
+        key: {
+            type: String,
+            value: '',
+        },
+        thumb: {
+            type: String,
+            value: '',
+        },
+        title: {
+            type: String,
+            value: '',
+        },
+        content: {
+            type: String,
+            value: '',
+        },
+        disabled: {
+            type: Boolean,
+            value: false,
+        },
+    },
+    data: {
+        current: false,
+        index: '0',
+    },
+    methods: {
+        changeCurrent(current, index) {
+            this.setData({
+                current,
+                index,
+            })
+        },
+        onTap() {
+            const { index, disabled } = this.data
+            const parent = this.getRelationNodes('../accordion-group/index')[0]
+
+            if (disabled || !parent) {
+                return false
+            }
+
+            parent.onClickItem(index)
+        },
+    },
+})

+ 3 - 0
dist/accordion/index.json

@@ -0,0 +1,3 @@
+{
+    "component": true
+}

+ 18 - 0
dist/accordion/index.wxml

@@ -0,0 +1,18 @@
+<view class="wux-class wux-accordion {{ current ? 'wux-accordion--current' : '' }}" bindtap="onTap">
+    <view class="wux-accordion__hd">
+        <block wx:if="{{ thumb }}">
+            <image class="wux-accordion__thumb" src="{{ thumb }}" />
+        </block>
+        <block wx:if="{{ title }}">
+            <view class="wux-accordion__title">{{ title }}</view>
+        </block>
+        <block wx:else>
+            <slot name="header"></slot>
+        </block>
+        <view class="wux-accordion__arrow"></view>
+    </view>
+    <view class="wux-accordion__bd">
+        <view class="wux-accordion__content" wx:if="{{ content }}">{{ content }}</view>
+        <slot></slot>
+    </view>
+</view>

+ 87 - 0
dist/accordion/index.wxss

@@ -0,0 +1,87 @@
+.wux-accordion__hd {
+  position: relative;
+  padding: 20rpx 30rpx;
+  color: #000000;
+  background-color: #ffffff;
+  box-sizing: border-box;
+  padding-left: 30rpx;
+  padding-right: 60rpx;
+  width: auto;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  overflow: hidden;
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: flex;
+  -webkit-box-align: center;
+  -webkit-align-items: center;
+          align-items: center;
+}
+.wux-accordion__hd:after {
+  content: " ";
+  position: absolute;
+  bottom: 0;
+  right: 0;
+  height: 2rpx;
+  border-bottom: 2rpx solid #D9D9D9;
+  color: #D9D9D9;
+  -webkit-transform-origin: 0 100%;
+          transform-origin: 0 100%;
+  -webkit-transform: scaleY(0.5);
+          transform: scaleY(0.5);
+  left: 0;
+}
+.wux-accordion__thumb {
+  display: block;
+  width: 40rpx;
+  height: 40rpx;
+  margin-right: 10rpx;
+}
+.wux-accordion__arrow {
+  position: absolute;
+  display: block;
+  top: 30rpx;
+  right: 30rpx;
+  width: 30rpx;
+  height: 30rpx;
+  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='26' viewBox='0 0 16 26' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M2 0L0 2l11.5 11L0 24l2 2 14-13z' fill='%23C7C7CC' fill-rule='evenodd'/%3E%3C/svg%3E");
+  background-size: contain;
+  background-repeat: no-repeat;
+  background-position: 50% 50%;
+  -webkit-transform: rotate(90deg);
+          transform: rotate(90deg);
+  -webkit-transition: -webkit-transform .2s ease;
+  transition: -webkit-transform .2s ease;
+  transition: transform .2s ease;
+  transition: transform .2s ease, -webkit-transform .2s ease;
+}
+.wux-accordion--current .wux-accordion__arrow {
+  -webkit-transform: rotate(270deg);
+          transform: rotate(270deg);
+}
+.wux-accordion__bd {
+  display: none;
+  overflow: hidden;
+  background: #fff;
+  font-size: 30rpx;
+  color: #333;
+  position: relative;
+  padding: 30rpx;
+}
+.wux-accordion__bd:after {
+  content: " ";
+  position: absolute;
+  bottom: 0;
+  right: 0;
+  height: 2rpx;
+  border-bottom: 2rpx solid #D9D9D9;
+  color: #D9D9D9;
+  -webkit-transform-origin: 0 100%;
+          transform-origin: 0 100%;
+  -webkit-transform: scaleY(0.5);
+          transform: scaleY(0.5);
+  left: 0;
+}
+.wux-accordion--current .wux-accordion__bd {
+  display: block;
+}

+ 71 - 0
dist/actionsheet/index.js

@@ -0,0 +1,71 @@
+import baseBehavior from '../helpers/baseBehavior'
+import mergeOptionsToData from '../helpers/mergeOptionsToData'
+import { $wuxBackdrop } from '../index'
+
+const defaults = {
+    theme: 'ios',
+    className: '',
+    titleText: '',
+    buttons: [],
+    buttonClicked() {},
+    cancelText: '取消',
+    cancel() {},
+    // destructiveText: '删除', 
+    // destructiveButtonClicked() {}, 
+}
+
+Component({
+    behaviors: [baseBehavior],
+    externalClasses: ['wux-class'],
+    data: mergeOptionsToData(defaults),
+    methods: {
+        /**
+         * 显示
+         */
+        showSheet(opts = {}) {
+            const options = this.$$mergeOptionsAndBindMethods(Object.assign({}, defaults, opts))
+            this.removed = false
+            this.$$setData({ in: true, ...options })
+            this.$wuxBackdrop.retain()
+            return this.cancel.bind(this)
+        },
+        /**
+         * 隐藏
+         */
+        removeSheet(callback) {
+            if (this.removed) return false
+            this.removed = true
+            this.$$setData({ in: false })
+            this.$wuxBackdrop.release()
+            if (typeof callback === 'function') {
+                callback(this.data.buttons)
+            }
+        },
+        /**
+         * 按钮点击事件
+         */
+        buttonClicked(e) {
+            const { index } = e.currentTarget.dataset
+            if (this.fns.buttonClicked(index, this.data.buttons[index]) === true) {
+                this.removeSheet()
+            }
+        },
+        /**
+         * 删除按钮点击事件
+         */
+        destructiveButtonClicked() {
+            if (this.fns.destructiveButtonClicked() === true) {
+                this.removeSheet()
+            }
+        },
+        /**
+         * 取消按钮点击事件
+         */
+        cancel() {
+            this.removeSheet(this.fns.cancel)
+        },
+    },
+    created() {
+        this.$wuxBackdrop = $wuxBackdrop('#wux-backdrop', this)
+    },
+})

+ 7 - 0
dist/actionsheet/index.json

@@ -0,0 +1,7 @@
+{
+    "component": true,
+    "usingComponents": {
+        "wux-animation-group": "../animation-group/index",
+        "wux-backdrop": "../backdrop/index"
+    }
+}

+ 17 - 0
dist/actionsheet/index.wxml

@@ -0,0 +1,17 @@
+<wux-backdrop id="wux-backdrop" bind:click="cancel" />
+<wux-animation-group wux-class="wux-actionsheet" in="{{ in }}" class-names="wux-animate--slideInUp">
+    <view class="wux-actionsheet__content {{ theme === 'wx' ? 'wux-actionsheet__content--theme-wx' : '' }}">
+        <view class="wux-actionsheet__group wux-actionsheet__group--options">
+            <view class="wux-actionsheet__title" wx:if="{{ titleText }}">{{ titleText }}</view>
+            <block wx:for="{{ buttons }}" wx:key="">
+                <button class="wux-actionsheet__button wux-actionsheet__button--option {{ item.classNmae }}" hover-class="wux-actionsheet__button--hover" data-index="{{ index }}" catchtap="buttonClicked">
+                    {{ item.text }}
+                </button>
+            </block>
+            <button class="wux-actionsheet__button wux-actionsheet__button--destructive" wx:if="{{ destructiveText }}" catchtap="destructiveButtonClicked">{{ destructiveText }}</button>
+        </view>
+        <view class="wux-actionsheet__group wux-actionsheet__group--cancel" wx:if="{{ cancelText }}">
+            <button class="wux-actionsheet__button wux-actionsheet__button--cancel" hover-class="wux-actionsheet__button--hover" catchtap="cancel">{{ cancelText }}</button>
+        </view>
+    </view>
+</wux-animation-group>

+ 115 - 0
dist/actionsheet/index.wxss

@@ -0,0 +1,115 @@
+.wux-actionsheet {
+  position: fixed;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  z-index: 1010;
+  width: 100%;
+  max-width: 1000rpx;
+  margin: auto;
+}
+.wux-actionsheet__content {
+  margin-left: 16rpx;
+  margin-right: 16rpx;
+  width: auto;
+  overflow: hidden;
+}
+.wux-actionsheet__group {
+  margin-bottom: 16rpx;
+  border-radius: 8rpx;
+  background-color: #fff;
+  overflow: hidden;
+}
+.wux-actionsheet__title {
+  padding: 32rpx;
+  color: #8f8f8f;
+  text-align: center;
+  font-size: 26rpx;
+}
+.wux-actionsheet__button {
+  position: relative;
+  display: block;
+  margin: 0;
+  padding: 0;
+  min-width: 104rpx;
+  min-height: 96rpx;
+  vertical-align: top;
+  text-align: center;
+  text-overflow: ellipsis;
+  cursor: pointer;
+  width: 100%;
+  border-radius: 0;
+  background-color: transparent;
+  color: #007aff;
+  font-size: 42rpx;
+  line-height: 96rpx;
+}
+.wux-actionsheet__button--hover {
+  box-shadow: none;
+  border-color: #d1d3d6;
+  color: #007aff;
+  background: #e4e5e7;
+}
+.wux-actionsheet__button--destructive {
+  color: #ff3b30 !important;
+}
+.wux-actionsheet__button--cancel {
+  font-weight: 500;
+}
+.wux-actionsheet__group {
+  margin-bottom: 16rpx;
+  border-radius: 8rpx;
+  background-color: #fff;
+  overflow: hidden;
+}
+.wux-actionsheet__group--options {
+  background: #f1f2f3;
+}
+.wux-actionsheet__group .wux-actionsheet__button {
+  border-top: none;
+}
+.wux-actionsheet__group .wux-actionsheet__button:after {
+  -webkit-transform: none;
+          transform: none;
+  -webkit-transform-origin: none;
+          transform-origin: none;
+  border: none;
+  border-radius: 0;
+  content: " ";
+  position: absolute;
+  left: 0;
+  top: 0;
+  right: 0;
+  height: 2rpx;
+  border-top: 2rpx solid #D9D9D9;
+  color: #D9D9D9;
+  -webkit-transform-origin: 0 0;
+          transform-origin: 0 0;
+  -webkit-transform: scaleY(0.5);
+          transform: scaleY(0.5);
+}
+.wux-actionsheet__group .wux-actionsheet__button:first-child:last-child:after {
+  border-width: 0;
+}
+.wux-actionsheet__content--theme-wx.wux-actionsheet__content {
+  margin-left: 0;
+  margin-right: 0;
+  background-color: #efeff4;
+}
+.wux-actionsheet__content--theme-wx .wux-actionsheet__group {
+  border-radius: 0;
+  margin-bottom: 12rpx;
+}
+.wux-actionsheet__content--theme-wx .wux-actionsheet__group--options {
+  background-color: #fff;
+}
+.wux-actionsheet__content--theme-wx .wux-actionsheet__group--cancel {
+  margin-bottom: 0;
+}
+.wux-actionsheet__content--theme-wx .wux-actionsheet__button {
+  font-size: 36rpx;
+  color: #000;
+}
+.wux-actionsheet__content--theme-wx .wux-actionsheet__button--cancel {
+  font-weight: normal;
+}

+ 44 - 0
dist/alert/index.js

@@ -0,0 +1,44 @@
+Component({
+	externalClasses: ['wux-class'],
+    options: {
+        multipleSlots: true,
+    },
+    properties: {
+        theme: {
+            type: String,
+            value: 'balanced',
+        },
+        thumb: {
+            type: String,
+            value: '',
+        },
+        title: {
+            type: String,
+            value: '',
+        },
+        label: {
+            type: String,
+            value: '',
+        },
+        closable: {
+            type: Boolean,
+            value: false,
+        },
+    },
+    data: {
+        visible: true,
+    },
+    methods: {
+        onClose() {
+            if (this.data.closable) {
+                this.setData({
+                    visible: false
+                })
+            }
+            this.triggerEvent('click')
+        },
+        onClick() {
+            this.triggerEvent('click')
+        },
+    },
+})

+ 6 - 0
dist/alert/index.json

@@ -0,0 +1,6 @@
+{
+    "component": true,
+    "usingComponents": {
+        "wux-animation-group": "../animation-group/index"
+    }
+}

+ 25 - 0
dist/alert/index.wxml

@@ -0,0 +1,25 @@
+<wux-animation-group in="{{ visible }}" class-names="wux-animate--fadeIn">
+	<view class="wux-class wux-alert {{ theme ? 'wux-alert--' + theme : '' }}" bindtap="onClick">
+	    <view class="wux-alert__hd">
+	        <block wx:if="{{ thumb }}">
+	            <image class="wux-alert__thumb" src="{{ thumb }}" />
+	        </block>
+	        <block wx:else>
+	            <slot name="header"></slot>
+	        </block>
+	    </view>
+	    <view class="wux-alert__bd">
+	        <view wx:if="{{ title }}" class="wux-alert__text">{{ title }}</view>
+	        <view wx:if="{{ label }}" class="wux-alert__desc">{{ label }}</view>
+	        <slot></slot>
+	    </view>
+	    <view class="wux-alert__ft">
+	        <block wx:if="{{ closable }}">
+	        	<view class="wux-alert__closable" catchtap="onClose">×</view>
+	        </block>
+	        <block wx:else>
+	            <slot name="footer"></slot>
+	        </block>
+	    </view>
+	</view>
+</wux-animation-group>

+ 67 - 0
dist/alert/index.wxss

@@ -0,0 +1,67 @@
+.wux-alert {
+  padding: 20rpx 30rpx;
+  position: relative;
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: flex;
+  -webkit-box-align: center;
+  -webkit-align-items: center;
+          align-items: center;
+  border-radius: 4rpx;
+  font-size: 28rpx;
+}
+.wux-alert__thumb {
+  display: block;
+  width: 40rpx;
+  height: 40rpx;
+  margin-right: 10rpx;
+}
+.wux-alert__bd {
+  -webkit-box-flex: 1;
+  -webkit-flex: 1;
+          flex: 1;
+}
+.wux-alert__text {
+  text-align: left;
+}
+.wux-alert__desc {
+  text-align: left;
+  line-height: 1.2;
+  font-size: 24rpx;
+}
+.wux-alert--light {
+  color: #fff;
+  background-color: #ddd;
+}
+.wux-alert--stable {
+  color: #fff;
+  background-color: #b2b2b2;
+}
+.wux-alert--positive {
+  color: #fff;
+  background-color: #387ef5;
+}
+.wux-alert--calm {
+  color: #fff;
+  background-color: #11c1f3;
+}
+.wux-alert--assertive {
+  color: #fff;
+  background-color: #ef473a;
+}
+.wux-alert--balanced {
+  color: #fff;
+  background-color: #33cd5f;
+}
+.wux-alert--energized {
+  color: #fff;
+  background-color: #ffc900;
+}
+.wux-alert--royal {
+  color: #fff;
+  background-color: #886aea;
+}
+.wux-alert--dark {
+  color: #fff;
+  background-color: #444;
+}

+ 407 - 0
dist/animation-group/index.js

@@ -0,0 +1,407 @@
+const ENTER = 'enter'
+const ENTERING = 'entering'
+const ENTERED = 'entered'
+const EXIT = 'exit'
+const EXITING = 'exiting'
+const EXITED = 'exited'
+const UNMOUNTED = 'unmounted'
+
+const TRANSITION = 'transition'
+const ANIMATION = 'animation'
+
+const TIMEOUT = 1000 / 60
+
+const defaultClassNames = {
+    enter: '', // 进入过渡的开始状态,在过渡过程完成之后移除
+    enterActive: '', // 进入过渡的结束状态,在过渡过程完成之后移除
+    enterDone: '', // 进入过渡的完成状态
+    exit: '', // 离开过渡的开始状态,在过渡过程完成之后移除
+    exitActive: '', // 离开过渡的结束状态,在过渡过程完成之后移除
+    exitDone: '', // 离开过渡的完成状态
+}
+
+Component({
+    externalClasses: ['wux-class'],
+    data: {
+        animateCss: '', // 动画样式
+        animateStatus: EXITED, // 动画状态,可选值 entering、entered、exiting、exited
+        isMounting: false, // 是否首次挂载
+    },
+    properties: {
+        // 触发组件进入或离开过渡的状态
+        in: {
+            type: Boolean,
+            value: false,
+            observer(newVal) {
+                if (this.data.isMounting) {
+                    this.updated(newVal)
+                }
+            },
+        },
+        // 过渡的类名
+        classNames: {
+            type: null,
+            value: defaultClassNames,
+        },
+        // 过渡持续时间
+        duration: {
+            type: null,
+            value: null,
+        },
+        // 过渡动效的类型
+        type: {
+            type: String,
+            value: TRANSITION,
+        },
+        // 首次挂载时是否触发进入过渡
+        appear: {
+            type: Boolean,
+            value: false,
+        },
+        // 是否启用进入过渡
+        enter: {
+            type: Boolean,
+            value: true,
+        },
+        // 是否启用离开过渡
+        exit: {
+            type: Boolean,
+            value: true,
+        },
+        // 首次进入过渡时是否懒挂载组件
+        mountOnEnter: {
+            type: Boolean,
+            value: true,
+        },
+        // 离开过渡完成时是否卸载组件
+        unmountOnExit: {
+            type: Boolean,
+            value: true,
+        },
+    },
+    methods: {
+        /**
+         * 监听过渡或动画的回调函数
+         */
+        addEventListener() {
+            const { animateStatus } = this.data
+            const { enter, exit } = this.getTimeouts()
+
+            if (animateStatus === ENTERING && !enter && this.data.enter) {
+                this.performEntered()
+            }
+
+            if (animateStatus === EXITING && !exit && this.data.exit) {
+                this.performExited()
+            }
+        },
+        /**
+         * 会在 WXSS transition 或 wx.createAnimation 动画结束后触发
+         */
+        onTransitionEnd() {
+            if (this.data.type === TRANSITION) {
+                this.addEventListener()
+            }
+        },
+        /**
+         * 会在一个 WXSS animation 动画完成时触发
+         */
+        onAnimationEnd() {
+            if (this.data.type === ANIMATION) {
+                this.addEventListener()
+            }
+        },
+        /**
+         * 更新组件状态
+         * @param {String} nextStatus 下一状态,ENTERING 或 EXITING
+         * @param {Boolean} mounting 是否首次挂载
+         */
+        updateStatus(nextStatus, mounting = false) {
+            if (nextStatus !== null) {
+                this.cancelNextCallback()
+                this.isAppearing = mounting
+
+                if (nextStatus === ENTERING) {
+                    this.performEnter()
+                } else {
+                    this.performExit()
+                }
+            }
+        },
+        /**
+         * 进入过渡
+         */
+        performEnter() {
+            const { className, activeClassName } = this.getClassNames(ENTER)
+            const { enter } = this.getTimeouts()
+            const enterParams = {
+                animateStatus: ENTER,
+                animateCss: className,
+            }
+            const enteringParams = {
+                animateStatus: ENTERING,
+                animateCss: `${className} ${activeClassName}`,
+            }
+
+            // 若已禁用进入过渡,则更新状态至 ENTERED
+            if (!this.isAppearing && !this.data.enter) {
+                return this.performEntered()
+            }
+
+            // 第一阶段:设置进入过渡的开始状态,并触发 ENTER 事件
+            // 第二阶段:延迟一帧后,设置进入过渡的结束状态,并触发 ENTERING 事件
+            // 第三阶段:若已设置过渡的持续时间,则延迟指定时间后触发进入过渡完成 performEntered,否则等待触发 onTransitionEnd 或 onAnimationEnd
+            this.safeSetData(enterParams, () => {
+                this.triggerEvent('change', { animateStatus: ENTER })
+                this.triggerEvent(ENTER, { isAppearing: this.isAppearing })
+
+                // 由于有些时候不能正确的触发动画完成的回调,具体原因未知
+                // 所以采用延迟一帧的方式来确保可以触发回调
+                this.delayHandler(TIMEOUT, () => {
+                    this.safeSetData(enteringParams, () => {
+                        this.triggerEvent('change', { animateStatus: ENTERING })
+                        this.triggerEvent(ENTERING, { isAppearing: this.isAppearing })
+
+                        if (enter) {
+                            this.delayHandler(enter, this.performEntered)
+                        }
+                    })
+                })
+            })
+        },
+        /**
+         * 进入过渡完成
+         */
+        performEntered() {
+            const { doneClassName } = this.getClassNames(ENTER)
+            const enteredParams = {
+                animateStatus: ENTERED,
+                animateCss: doneClassName,
+            }
+
+            // 第三阶段:设置进入过渡的完成状态,并触发 ENTERED 事件            
+            this.safeSetData(enteredParams, () => {
+                this.triggerEvent('change', { animateStatus: ENTERED })
+                this.triggerEvent(ENTERED, { isAppearing: this.isAppearing })
+            })
+        },
+        /**
+         * 离开过渡
+         */
+        performExit() {
+            const { className, activeClassName } = this.getClassNames(EXIT)
+            const { exit } = this.getTimeouts()
+            const exitParams = {
+                animateStatus: EXIT,
+                animateCss: className,
+            }
+            const exitingParams = {
+                animateStatus: EXITING,
+                animateCss: `${className} ${activeClassName}`,
+            }
+
+            // 若已禁用离开过渡,则更新状态至 EXITED
+            if (!this.data.exit) {
+                return this.performExited()
+            }
+
+            // 第一阶段:设置离开过渡的开始状态,并触发 EXIT 事件
+            // 第二阶段:延迟一帧后,设置离开过渡的结束状态,并触发 EXITING 事件
+            // 第三阶段:若已设置过渡的持续时间,则延迟指定时间后触发离开过渡完成 performExited,否则等待触发 onTransitionEnd 或 onAnimationEnd
+            this.safeSetData(exitParams, () => {
+                this.triggerEvent('change', { animateStatus: EXIT })
+                this.triggerEvent(EXIT)
+
+                this.delayHandler(TIMEOUT, () => {
+                    this.safeSetData(exitingParams, () => {
+                        this.triggerEvent('change', { animateStatus: EXITING })
+                        this.triggerEvent(EXITING)
+
+                        if (exit) {
+                            this.delayHandler(exit, this.performExited)
+                        }
+                    })
+                })
+            })
+        },
+        /**
+         * 离开过渡完成
+         */
+        performExited() {
+            const { doneClassName } = this.getClassNames(EXIT)
+            const exitedParams = {
+                animateStatus: EXITED,
+                animateCss: doneClassName,
+            }
+
+            // 第三阶段:设置离开过渡的完成状态,并触发 EXITED 事件
+            this.safeSetData(exitedParams, () => {
+                this.triggerEvent('change', { animateStatus: EXITED })
+                this.triggerEvent(EXITED)
+
+                // 判断离开过渡完成时是否卸载组件
+                if (this.data.unmountOnExit) {
+                    this.setData({ animateStatus: UNMOUNTED }, () => {
+                        this.triggerEvent('change', { animateStatus: UNMOUNTED })
+                    })
+                }
+            })
+        },
+        /**
+         * 获取指定状态下的类名
+         * @param {String} type 过渡类型,enter 或 exit
+         */
+        getClassNames(type) {
+            const { classNames } = this.data
+            const className = typeof classNames !== 'string' ? classNames[type] : `${classNames}-${type}`
+            const activeClassName = typeof classNames !== 'string' ? classNames[`${type}Active`] : `${classNames}-${type}-active`
+            const doneClassName = typeof classNames !== 'string' ? classNames[`${type}Done`] : `${classNames}-${type}-done`
+
+            return {
+                className,
+                activeClassName,
+                doneClassName,
+            }
+        },
+        /**
+         * 获取过渡持续时间
+         */
+        getTimeouts() {
+            const { duration } = this.data
+
+            if (duration !== null && typeof duration === 'object') {
+                return {
+                    enter: duration.enter,
+                    exit: duration.exit,
+                }
+            } else if (typeof duration === 'number') {
+                return {
+                    enter: duration,
+                    exit: duration,
+                }
+            }
+
+            return {}
+        },
+        /**
+         * 属性值 in 被更改时的响应函数
+         * @param {Boolean} newVal 触发组件进入或离开过渡的状态
+         */
+        updated(newVal) {
+            let { animateStatus } = this.pendingData || this.data
+            let nextStatus = null
+
+            if (newVal) {
+                if (animateStatus === UNMOUNTED) {
+                    animateStatus = EXITED
+                    this.setData({ animateStatus: EXITED }, () => {
+                        this.triggerEvent('change', { animateStatus: EXITED })
+                    })
+                }
+                if (animateStatus !== ENTER && animateStatus !== ENTERING && animateStatus !== ENTERED) {
+                    nextStatus = ENTERING
+                }
+            } else {
+                if (animateStatus === ENTER || animateStatus === ENTERING || animateStatus === ENTERED) {
+                    nextStatus = EXITING
+                }
+            }
+
+            this.updateStatus(nextStatus)
+        },
+        /**
+         * safeSetData
+         * @param {Object} nextData 数据对象
+         * @param {Function} callback 回调函数
+         */
+        safeSetData(nextData, callback) {
+            this.pendingData = Object.assign({}, this.data, nextData)
+            callback = this.setNextCallback(callback)
+
+            this.setData(nextData, () => {
+                this.pendingData = null
+                callback()
+            })
+        },
+        /**
+         * 设置下一回调函数
+         * @param {Function} callback 回调函数
+         */
+        setNextCallback(callback) {
+            let active = true
+
+            this.nextCallback = (event) => {
+                if (active) {
+                    active = false
+                    this.nextCallback = null
+
+                    callback.call(this, event)
+                }
+            }
+
+            this.nextCallback.cancel = () => {
+                active = false
+            }
+
+            return this.nextCallback
+        },
+        /**
+         * 取消下一回调函数
+         */
+        cancelNextCallback() {
+            if (this.nextCallback !== null) {
+                this.nextCallback.cancel()
+                this.nextCallback = null
+            }
+        },
+        /**
+         * 延迟一段时间触发回调
+         * @param {Number} timeout 延迟时间
+         * @param {Function} handler 回调函数
+         */
+        delayHandler(timeout, handler) {
+            if (timeout) {
+                this.setNextCallback(handler)
+                setTimeout(this.nextCallback, timeout)
+            }
+        },
+        /**
+         * 点击事件
+         */
+        onTap() {
+            this.triggerEvent('click')
+        },
+    },
+    created() {
+        this.nextCallback = null
+    },
+    attached() {
+        let animateStatus = null
+        let appearStatus = null
+
+        if (this.data.in) {
+            if (this.data.appear) {
+                animateStatus = EXITED
+                appearStatus = ENTERING
+            } else {
+                animateStatus = ENTERED
+            }
+        } else {
+            if (this.data.unmountOnExit || this.data.mountOnEnter) {
+                animateStatus = UNMOUNTED
+            } else {
+                animateStatus = EXITED
+            }
+        }
+
+        // 由于小程序组件首次挂载时 observer 事件总是优先于 attached 事件
+        // 所以使用 isMounting 来强制优先触发 attached 事件
+        this.safeSetData({ animateStatus, isMounting: true }, () => {
+            this.triggerEvent('change', { animateStatus })
+            this.updateStatus(appearStatus, true)
+        })
+    },
+    detached() {
+        this.cancelNextCallback()
+    },
+})

+ 3 - 0
dist/animation-group/index.json

@@ -0,0 +1,3 @@
+{
+    "component": true
+}

+ 3 - 0
dist/animation-group/index.wxml

@@ -0,0 +1,3 @@
+<view class="wux-class {{ animateCss }}" bindtap="onTap" bindtransitionend="onTransitionEnd" bindanimationend="onAnimationEnd" wx:if="{{ animateStatus !== 'unmounted' }}">
+    <slot></slot>
+</view>

+ 250 - 0
dist/animation-group/index.wxss

@@ -0,0 +1,250 @@
+.wux-animate--fadeIn-enter {
+  -webkit-transition: opacity .3s;
+  transition: opacity .3s;
+  opacity: 0;
+}
+.wux-animate--fadeIn-enter-active,
+.wux-animate--fadeIn-enter-done {
+  opacity: 1;
+}
+.wux-animate--fadeIn-exit {
+  -webkit-transition: opacity .3s;
+  transition: opacity .3s;
+  opacity: 1;
+}
+.wux-animate--fadeIn-exit-active,
+.wux-animate--fadeIn-exit-done {
+  opacity: 0;
+}
+.wux-animate--fadeInDown-enter {
+  -webkit-transition: opacity .3s, -webkit-transform .3s;
+  transition: opacity .3s, -webkit-transform .3s;
+  transition: opacity .3s, transform .3s;
+  transition: opacity .3s, transform .3s, -webkit-transform .3s;
+  opacity: 0;
+  -webkit-transform: translate3d(0, -100%, 0);
+          transform: translate3d(0, -100%, 0);
+}
+.wux-animate--fadeInDown-enter-active,
+.wux-animate--fadeInDown-enter-done {
+  opacity: 1;
+  -webkit-transform: none;
+          transform: none;
+}
+.wux-animate--fadeInDown-exit {
+  -webkit-transition: opacity .3s, -webkit-transform .3s;
+  transition: opacity .3s, -webkit-transform .3s;
+  transition: opacity .3s, transform .3s;
+  transition: opacity .3s, transform .3s, -webkit-transform .3s;
+  opacity: 1;
+  -webkit-transform: none;
+          transform: none;
+}
+.wux-animate--fadeInDown-exit-active,
+.wux-animate--fadeInDown-exit-done {
+  opacity: 0;
+  -webkit-transform: translate3d(0, -100%, 0);
+          transform: translate3d(0, -100%, 0);
+}
+.wux-animate--fadeInLeft-enter {
+  -webkit-transition: opacity .3s, -webkit-transform .3s;
+  transition: opacity .3s, -webkit-transform .3s;
+  transition: opacity .3s, transform .3s;
+  transition: opacity .3s, transform .3s, -webkit-transform .3s;
+  opacity: 0;
+  -webkit-transform: translate3d(-100%, 0, 0);
+          transform: translate3d(-100%, 0, 0);
+}
+.wux-animate--fadeInLeft-enter-active,
+.wux-animate--fadeInLeft-enter-done {
+  opacity: 1;
+  -webkit-transform: none;
+          transform: none;
+}
+.wux-animate--fadeInLeft-exit {
+  -webkit-transition: opacity .3s, -webkit-transform .3s;
+  transition: opacity .3s, -webkit-transform .3s;
+  transition: opacity .3s, transform .3s;
+  transition: opacity .3s, transform .3s, -webkit-transform .3s;
+  opacity: 1;
+  -webkit-transform: none;
+          transform: none;
+}
+.wux-animate--fadeInLeft-exit-active,
+.wux-animate--fadeInLeft-exit-done {
+  opacity: 0;
+  -webkit-transform: translate3d(-100%, 0, 0);
+          transform: translate3d(-100%, 0, 0);
+}
+.wux-animate--fadeInRight-enter {
+  -webkit-transition: opacity .3s, -webkit-transform .3s;
+  transition: opacity .3s, -webkit-transform .3s;
+  transition: opacity .3s, transform .3s;
+  transition: opacity .3s, transform .3s, -webkit-transform .3s;
+  opacity: 0;
+  -webkit-transform: translate3d(100%, 0, 0);
+          transform: translate3d(100%, 0, 0);
+}
+.wux-animate--fadeInRight-enter-active,
+.wux-animate--fadeInRight-enter-done {
+  opacity: 1;
+  -webkit-transform: none;
+          transform: none;
+}
+.wux-animate--fadeInRight-exit {
+  -webkit-transition: opacity .3s, -webkit-transform .3s;
+  transition: opacity .3s, -webkit-transform .3s;
+  transition: opacity .3s, transform .3s;
+  transition: opacity .3s, transform .3s, -webkit-transform .3s;
+  opacity: 1;
+  -webkit-transform: none;
+          transform: none;
+}
+.wux-animate--fadeInRight-exit-active,
+.wux-animate--fadeInRight-exit-done {
+  opacity: 0;
+  -webkit-transform: translate3d(100%, 0, 0);
+          transform: translate3d(100%, 0, 0);
+}
+.wux-animate--fadeInUp-enter {
+  -webkit-transition: opacity .3s, -webkit-transform .3s;
+  transition: opacity .3s, -webkit-transform .3s;
+  transition: opacity .3s, transform .3s;
+  transition: opacity .3s, transform .3s, -webkit-transform .3s;
+  opacity: 0;
+  -webkit-transform: translate3d(0, 100%, 0);
+          transform: translate3d(0, 100%, 0);
+}
+.wux-animate--fadeInUp-enter-active,
+.wux-animate--fadeInUp-enter-done {
+  opacity: 1;
+  -webkit-transform: none;
+          transform: none;
+}
+.wux-animate--fadeInUp-exit {
+  -webkit-transition: opacity .3s, -webkit-transform .3s;
+  transition: opacity .3s, -webkit-transform .3s;
+  transition: opacity .3s, transform .3s;
+  transition: opacity .3s, transform .3s, -webkit-transform .3s;
+  opacity: 1;
+  -webkit-transform: none;
+          transform: none;
+}
+.wux-animate--fadeInUp-exit-active,
+.wux-animate--fadeInUp-exit-done {
+  opacity: 0;
+  -webkit-transform: translate3d(0, 100%, 0);
+          transform: translate3d(0, 100%, 0);
+}
+.wux-animate--slideInUp-enter {
+  -webkit-transition: -webkit-transform .3s;
+  transition: -webkit-transform .3s;
+  transition: transform .3s;
+  transition: transform .3s, -webkit-transform .3s;
+  -webkit-transform: translate3d(0, 100%, 0);
+          transform: translate3d(0, 100%, 0);
+  visibility: visible;
+}
+.wux-animate--slideInUp-enter-active,
+.wux-animate--slideInUp-enter-done {
+  -webkit-transform: translateZ(0);
+          transform: translateZ(0);
+}
+.wux-animate--slideInUp-exit {
+  -webkit-transition: -webkit-transform .3s;
+  transition: -webkit-transform .3s;
+  transition: transform .3s;
+  transition: transform .3s, -webkit-transform .3s;
+  -webkit-transform: translateZ(0);
+          transform: translateZ(0);
+}
+.wux-animate--slideInUp-exit-active,
+.wux-animate--slideInUp-exit-done {
+  -webkit-transform: translate3d(0, 100%, 0);
+          transform: translate3d(0, 100%, 0);
+  visibility: visible;
+}
+.wux-animate--slideInDown-enter {
+  -webkit-transition: -webkit-transform .3s;
+  transition: -webkit-transform .3s;
+  transition: transform .3s;
+  transition: transform .3s, -webkit-transform .3s;
+  -webkit-transform: translate3d(0, -100%, 0);
+          transform: translate3d(0, -100%, 0);
+  visibility: visible;
+}
+.wux-animate--slideInDown-enter-active,
+.wux-animate--slideInDown-enter-done {
+  -webkit-transform: translateZ(0);
+          transform: translateZ(0);
+}
+.wux-animate--slideInDown-exit {
+  -webkit-transition: -webkit-transform .3s;
+  transition: -webkit-transform .3s;
+  transition: transform .3s;
+  transition: transform .3s, -webkit-transform .3s;
+  -webkit-transform: translateZ(0);
+          transform: translateZ(0);
+}
+.wux-animate--slideInDown-exit-active,
+.wux-animate--slideInDown-exit-done {
+  -webkit-transform: translate3d(0, -100%, 0);
+          transform: translate3d(0, -100%, 0);
+  visibility: visible;
+}
+.wux-animate--slideInLeft-enter {
+  -webkit-transition: -webkit-transform .3s;
+  transition: -webkit-transform .3s;
+  transition: transform .3s;
+  transition: transform .3s, -webkit-transform .3s;
+  -webkit-transform: translate3d(-100%, 0, 0);
+          transform: translate3d(-100%, 0, 0);
+  visibility: visible;
+}
+.wux-animate--slideInLeft-enter-active,
+.wux-animate--slideInLeft-enter-done {
+  -webkit-transform: translateZ(0);
+          transform: translateZ(0);
+}
+.wux-animate--slideInLeft-exit {
+  -webkit-transition: -webkit-transform .3s;
+  transition: -webkit-transform .3s;
+  transition: transform .3s;
+  transition: transform .3s, -webkit-transform .3s;
+  -webkit-transform: translateZ(0);
+          transform: translateZ(0);
+}
+.wux-animate--slideInLeft-exit-active,
+.wux-animate--slideInLeft-exit-done {
+  -webkit-transform: translate3d(-100%, 0, 0);
+          transform: translate3d(-100%, 0, 0);
+  visibility: visible;
+}
+.wux-animate--slideInRight-enter {
+  -webkit-transition: -webkit-transform .3s;
+  transition: -webkit-transform .3s;
+  transition: transform .3s;
+  transition: transform .3s, -webkit-transform .3s;
+  -webkit-transform: translate3d(100%, 0, 0);
+          transform: translate3d(100%, 0, 0);
+  visibility: visible;
+}
+.wux-animate--slideInRight-enter-active,
+.wux-animate--slideInRight-enter-done {
+  -webkit-transform: translateZ(0);
+          transform: translateZ(0);
+}
+.wux-animate--slideInRight-exit {
+  -webkit-transition: -webkit-transform .3s;
+  transition: -webkit-transform .3s;
+  transition: transform .3s;
+  transition: transform .3s, -webkit-transform .3s;
+  -webkit-transform: translateZ(0);
+          transform: translateZ(0);
+}
+.wux-animate--slideInRight-exit-active,
+.wux-animate--slideInRight-exit-done {
+  -webkit-transform: translate3d(100%, 0, 0);
+          transform: translate3d(100%, 0, 0);
+  visibility: visible;
+}

+ 54 - 0
dist/avatar/index.js

@@ -0,0 +1,54 @@
+Component({
+    externalClasses: ['wux-class'],
+    properties: {
+        shape: {
+            type: String,
+            value: 'circle',
+        },
+        size: {
+            type: String,
+            value: 'default',
+        },
+        src: {
+            type: String,
+            value: '',
+        },
+        bodyStyle: {
+            type: String,
+            value: '',
+        },
+        scale: {
+            type: Boolean,
+            value: false,
+        },
+    },
+    data: {
+        childrenStyle: '',
+    },
+    methods: {
+        setScale() {
+            const query = wx.createSelectorQuery().in(this)
+            query.select('.wux-avatar').boundingClientRect()
+            query.select('.wux-avatar__string').boundingClientRect()
+            query.exec((rects) => {
+                if (rects.filter((n) => !n).length) {
+                    return false
+                }
+
+                const [parent, child] = rects
+                const offset = parent.width - 8 < child.width
+                const childrenScale = offset ? (parent.width - 8) / child.width : 1
+                const childrenStyle = childrenScale !== 1 ? `position: absolute; display: inline-block; transform: scale(${childrenScale}); left: calc(50% - ${Math.round(child.width / 2)}px)` : ''
+
+                this.setData({
+                    childrenStyle,
+                })
+            })
+        },
+    },
+    ready() {
+        if (!this.data.src && this.data.scale) {
+            this.setScale()
+        }
+    },
+})

+ 3 - 0
dist/avatar/index.json

@@ -0,0 +1,3 @@
+{
+    "component": true
+}

+ 6 - 0
dist/avatar/index.wxml

@@ -0,0 +1,6 @@
+<view class="wux-class wux-avatar {{ shape ? 'wux-avatar--' + shape : '' }} {{ size ? 'wux-avatar--' + size : '' }} {{ src ? 'wux-avatar--thumb' : '' }}" style="{{ bodyStyle }}">
+    <image src="{{ src }}" wx:if="{{ src }}" />
+    <text class="wux-avatar__string" style="{{ childrenStyle }}" wx:else>
+        <slot></slot>
+    </text>
+</view>

+ 53 - 0
dist/avatar/index.wxss

@@ -0,0 +1,53 @@
+.wux-avatar {
+  font-family: Monospaced Number, Chinese Quote, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Helvetica Neue, Helvetica, Arial, sans-serif;
+  font-size: 28rpx;
+  line-height: 1.5;
+  color: rgba(0, 0, 0, 0.65);
+  box-sizing: border-box;
+  display: inline-block;
+  text-align: center;
+  background: #ccc;
+  color: #fff;
+  white-space: nowrap;
+  position: relative;
+  overflow: hidden;
+  vertical-align: middle;
+  width: 64rpx;
+  height: 64rpx;
+  line-height: 64rpx;
+  border-radius: 32rpx;
+  font-size: 36rpx;
+}
+.wux-avatar .wux-avatar__string {
+  line-height: 64rpx;
+}
+.wux-avatar--small {
+  width: 48rpx;
+  height: 48rpx;
+  line-height: 48rpx;
+  border-radius: 24rpx;
+  font-size: 28rpx;
+}
+.wux-avatar--small .wux-avatar__string {
+  line-height: 48rpx;
+}
+.wux-avatar--large {
+  width: 80rpx;
+  height: 80rpx;
+  line-height: 80rpx;
+  border-radius: 40rpx;
+  font-size: 48rpx;
+}
+.wux-avatar--large .wux-avatar__string {
+  line-height: 80rpx;
+}
+.wux-avatar--square {
+  border-radius: 8rpx;
+}
+.wux-avatar--thumb {
+  background: transparent;
+}
+.wux-avatar > image {
+  width: 100%;
+  height: 100%;
+}

+ 43 - 0
dist/backdrop/index.js

@@ -0,0 +1,43 @@
+import baseBehavior from '../helpers/baseBehavior'
+
+Component({
+    behaviors: [baseBehavior],
+    externalClasses: ['wux-class'],
+    properties: {
+        transparent: {
+            type: Boolean,
+            value: false,
+        },
+    },
+    methods: {
+        /**
+         * 保持锁定
+         */
+        retain() {
+            if (typeof this.backdropHolds !== 'number' || !this.backdropHolds) {
+                this.backdropHolds = 0
+            }
+
+            this.backdropHolds = this.backdropHolds + 1
+
+            if (this.backdropHolds === 1) {
+                this.$$setData({ in: true })
+            }
+        },
+        /**
+         * 释放锁定
+         */
+        release() {
+            if (this.backdropHolds === 1) {
+                this.$$setData({ in: false })
+            }
+            this.backdropHolds = Math.max(0, this.backdropHolds - 1)
+        },
+        /**
+         * 点击事件
+         */
+        onClick() {
+            this.triggerEvent('click')
+        },
+    },
+})

+ 6 - 0
dist/backdrop/index.json

@@ -0,0 +1,6 @@
+{
+    "component": true,
+    "usingComponents": {
+        "wux-animation-group": "../animation-group/index"
+    }
+}

+ 1 - 0
dist/backdrop/index.wxml

@@ -0,0 +1 @@
+<wux-animation-group wux-class="{{ transparent ? 'wux-backdrop--transparent' : 'wux-backdrop' }}" in="{{ in }}" class-names="wux-animate--fadeIn" bind:click="onClick"></wux-animation-group>

+ 15 - 0
dist/backdrop/index.wxss

@@ -0,0 +1,15 @@
+.wux-backdrop {
+  background: rgba(0, 0, 0, 0.4);
+}
+.wux-backdrop,
+.wux-backdrop--transparent {
+  position: fixed;
+  z-index: 1000;
+  top: 0;
+  right: 0;
+  left: 0;
+  bottom: 0;
+}
+.wux-backdrop--transparent {
+  background: transparent;
+}

+ 40 - 0
dist/badge/index.js

@@ -0,0 +1,40 @@
+Component({
+    externalClasses: ['wux-class', 'wux-class-badge'],
+    properties: {
+        count: {
+            type: Number,
+            value: 0,
+            observer(newVal) {
+                const { overflowCount } = this.data
+                const finalCount = newVal >= overflowCount ? `${overflowCount}+` : newVal
+
+                this.setData({
+                    finalCount,
+                })
+            },
+        },
+        overflowCount: {
+            type: Number,
+            value: 99,
+        },
+        dot: {
+            type: Boolean,
+            value: false,
+        },
+        showZero: {
+            type: Boolean,
+            value: false,
+        },
+        status: {
+            type: String,
+            value: '',
+        },
+        text: {
+            type: String,
+            value: '',
+        },
+    },
+    data: {
+        finalCount: 0,
+    },
+})

+ 3 - 0
dist/badge/index.json

@@ -0,0 +1,3 @@
+{
+    "component": true
+}

+ 10 - 0
dist/badge/index.wxml

@@ -0,0 +1,10 @@
+<view class="wux-class wux-badge">
+    <slot></slot>
+    <view class="wux-badge__status" wx:if="{{ status }}">
+        <view class="wux-badge__status-dot {{ status ? 'wux-badge__status-dot--' + status : '' }}"></view>
+        <view class="wux-badge__status-text" wx:if="{{ text }}">{{ text }}</view>
+    </view>
+    <view class="wux-badge__dot" wx:elif="{{ dot }}"></view>
+    <view class="wux-badge__count wux-class-badge" wx:elif="{{ showZero && count === 0 }}">{{ finalCount }}</view>
+    <view class="wux-badge__count wux-class-badge" wx:elif="{{ count !== 0 }}">{{ finalCount }}</view>
+</view>

+ 116 - 0
dist/badge/index.wxss

@@ -0,0 +1,116 @@
+.wux-badge {
+  position: relative;
+  display: inline-block;
+  line-height: 1;
+  vertical-align: middle;
+}
+.wux-badge__count {
+  position: absolute;
+  -webkit-transform: translateX(50%);
+          transform: translateX(50%);
+  top: -12rpx;
+  right: 0;
+  height: 36rpx;
+  border-radius: 18rpx;
+  min-width: 36rpx;
+  background: #ed3f14;
+  border: 2rpx solid transparent;
+  color: #fff;
+  line-height: 36rpx;
+  text-align: center;
+  padding: 0 10rpx;
+  font-size: 24rpx;
+  white-space: nowrap;
+  -webkit-transform-origin: -10% center;
+          transform-origin: -10% center;
+  z-index: 10;
+  box-shadow: 0 0 0 2rpx #fff;
+  box-sizing: border-box;
+  text-rendering: optimizeLegibility;
+}
+.wux-badge__dot {
+  position: absolute;
+  -webkit-transform: translateX(-50%);
+          transform: translateX(-50%);
+  -webkit-transform-origin: 0 center;
+          transform-origin: 0 center;
+  top: -8rpx;
+  right: -16rpx;
+  height: 16rpx;
+  width: 16rpx;
+  border-radius: 100%;
+  background: #ed3f14;
+  z-index: 10;
+  box-shadow: 0 0 0 2rpx #fff;
+}
+.wux-badge__status {
+  line-height: inherit;
+  vertical-align: baseline;
+}
+.wux-badge__status-dot {
+  width: 12rpx;
+  height: 12rpx;
+  display: inline-block;
+  border-radius: 50%;
+  vertical-align: middle;
+  position: relative;
+  top: -2rpx;
+}
+.wux-badge__status-dot--success {
+  background-color: #52c41a;
+}
+.wux-badge__status-dot--processing {
+  background-color: #1890ff;
+  position: relative;
+}
+.wux-badge__status-dot--processing:after {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  border-radius: 50%;
+  border: 2rpx solid #1890ff;
+  content: "";
+  -webkit-animation: statusProcessing 1.2s infinite ease-in-out;
+          animation: statusProcessing 1.2s infinite ease-in-out;
+}
+.wux-badge__status-dot--default {
+  background-color: #d9d9d9;
+}
+.wux-badge__status-dot--error {
+  background-color: #f5222d;
+}
+.wux-badge__status-dot--warning {
+  background-color: #faad14;
+}
+.wux-badge__status-text {
+  display: inline-block;
+  color: rgba(0, 0, 0, 0.65);
+  font-size: 28rpx;
+  margin-left: 16rpx;
+}
+@-webkit-keyframes statusProcessing {
+  0% {
+    -webkit-transform: scale(0.8);
+            transform: scale(0.8);
+    opacity: 0.5;
+  }
+  to {
+    -webkit-transform: scale(2.4);
+            transform: scale(2.4);
+    opacity: 0;
+  }
+}
+@keyframes statusProcessing {
+  0% {
+    -webkit-transform: scale(0.8);
+            transform: scale(0.8);
+    opacity: 0.5;
+  }
+  to {
+    -webkit-transform: scale(2.4);
+            transform: scale(2.4);
+    opacity: 0;
+  }
+}

+ 207 - 0
dist/barcode/barcode.js

@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2014 Johannes Mittendorfer (http://johannes-mittendorfer.com)
+ * Licensed under the MIT License (LICENSE.txt).
+ *
+ * Version 2.1.1
+ * Build 2014-10-07
+ */
+
+var EAN13, pluginName;
+
+pluginName = null;
+
+"use strict";
+
+EAN13 = (function() {
+    EAN13.prototype.settings = {};
+
+    EAN13.prototype.init = function() {
+        var checkDigit, code;
+        if (this.number.length === 12) {
+            checkDigit = this.generateCheckDigit(this.number);
+            this.number += checkDigit;
+        }
+        if (this.number.length === 13) {
+            if (this.validate()) {
+                this.settings.onValid.call();
+            } else {
+                this.settings.onInvalid.call();
+            }
+            code = this.getCode();
+            return this.draw(code);
+        } else {
+            return this.settings.onError.call();
+        }
+    };
+
+    EAN13.prototype.getCode = function() {
+        var c_encoding, code, countries, i, parts, raw_number, x, y, z;
+        x = ["0001101", "0011001", "0010011", "0111101", "0100011", "0110001", "0101111", "0111011", "0110111", "0001011"];
+        y = ["0100111", "0110011", "0011011", "0100001", "0011101", "0111001", "0000101", "0010001", "0001001", "0010111"];
+        z = ["1110010", "1100110", "1101100", "1000010", "1011100", "1001110", "1010000", "1000100", "1001000", "1110100"];
+        countries = ["xxxxxx", "xxyxyy", "xxyyxy", "xxyyyx", "xyxxyy", "xyyxxy", "xyyyxx", "xyxyxy", "xyxyyx", "xyyxyx"];
+        code = "";
+        c_encoding = countries[parseInt(this.number.substr(0, 1), 10)].split("");
+        raw_number = this.number.substr(1);
+        parts = raw_number.split("");
+        i = 0;
+        while (i < 6) {
+            if (c_encoding[i] === "x") {
+                code += x[parts[i]];
+            } else {
+                code += y[parts[i]];
+            }
+            i++;
+        }
+        i = 6;
+        while (i < 12) {
+            code += z[parts[i]];
+            i++;
+        }
+        return code;
+    };
+
+    EAN13.prototype.clear = function(context) {
+        return context.clearRect(0, 0, this.settings.width, this.settings.height);
+    };
+
+    EAN13.prototype.draw = function(code) {
+        var border_height, chars, context, height, i, item_width, layout, left, lines, offset, prefix, width, x, _i, _ref;
+        layout = {
+            prefix_offset: 0.06,
+            font_stretch: 0.073,
+            border_line_height_number: 0.9,
+            border_line_height: 1,
+            line_height: 0.9,
+            font_size: 0.15,
+            font_y: 1.03,
+            text_offset: 4.5
+        };
+        width = (this.settings.prefix ? this.settings.width - (this.settings.width * layout.prefix_offset) : this.settings.width);
+        if (this.settings.number) {
+            border_height = layout.border_line_height_number * this.settings.height;
+            height = layout.line_height * border_height;
+        } else {
+            border_height = layout.border_line_height * this.settings.height;
+            height = border_height;
+        }
+        item_width = width / 95;
+        if (this.id) {
+            context = wx.createCanvasContext(this.id, this.ctx);
+            this.clear(context);
+            context.setFillStyle(this.settings.color);
+            left = this.settings.number && this.settings.prefix ? this.settings.width * layout.prefix_offset : 0;
+            lines = code.split("");
+            context.fillRect(left, 0, item_width, border_height);
+            left = left + item_width * 2;
+            context.fillRect(left, 0, item_width, border_height);
+            left = left + item_width;
+            i = 0;
+            while (i < 42) {
+                if (lines[i] === "1") {
+                    context.fillRect(left, 0, Math.floor(item_width) + 1, height);
+                }
+                left = left + item_width;
+                i++;
+            }
+            left = left + item_width;
+            context.fillRect(left, 0, item_width, border_height);
+            left = left + item_width * 2;
+            context.fillRect(left, 0, item_width, border_height);
+            left = left + item_width * 2;
+            i = 42;
+            while (i < 84) {
+                if (lines[i] === "1") {
+                    context.fillRect(left, 0, Math.floor(item_width) + 1, height);
+                }
+                left = left + item_width;
+                i++;
+            }
+            context.fillRect(left, 0, item_width, border_height);
+            left = left + item_width * 2;
+            context.fillRect(left, 0, item_width, border_height);
+            if (this.settings.number) {
+                context.setFontSize(layout.font_size * height + "px monospace");
+                prefix = this.number.substr(0, 1);
+                if (this.settings.prefix) {
+                    context.fillText(prefix, 0, border_height * layout.font_y);
+                }
+                offset = item_width * layout.text_offset + (this.settings.prefix ? layout.prefix_offset * this.settings.width : 0);
+                chars = this.number.substr(1, 6).split("");
+                chars.forEach(function(value, key) {
+                    context.fillText(value, offset, border_height * layout.font_y);
+                    return offset += layout.font_stretch * width;
+                });
+                offset = 49 * item_width + (this.settings.prefix ? layout.prefix_offset * this.settings.width : 0) + layout.text_offset;
+                chars = this.number.substr(7).split("")
+                chars.forEach(function(value, key) {
+                    context.fillText(value, offset, border_height * layout.font_y);
+                    return offset += layout.font_stretch * width;
+                });
+            }
+            if (this.settings.debug) {
+                for (x = _i = 0, _ref = item_width * 2; _ref > 0 ? _i <= width : _i >= width; x = _i += _ref) {
+                    context.beginPath();
+                    context.rect(x, height * 0.4, item_width, height * 0.1);
+                    context.setFillStyle('red');
+                    context.fill();
+                }
+            }
+            context.draw()
+            return this.settings.onSuccess.call();
+        } else {
+            return this.settings.onError.call();
+        }
+    };
+
+    EAN13.prototype.generateCheckDigit = function(number) {
+        var chars, counter;
+        counter = 0;
+        chars = number.split("");
+        chars.forEach(function(value, key) {
+            if (key % 2 === 0) {
+                return counter += parseInt(value, 10);
+            } else {
+                return counter += 3 * parseInt(value, 10);
+            }
+        });
+        return 10 - (counter % 10) % 10;
+    };
+
+    EAN13.prototype.validate = function() {
+        return parseInt(this.number.slice(-1), 10) === this.generateCheckDigit(this.number.slice(0, -1));
+    };
+
+    function EAN13(id, number, options, ctx) {
+        var option;
+        this.id = id;
+        this.number = number;
+        this.ctx = ctx
+        this.settings = {
+            width: 200,
+            height: 100,
+            number: true,
+            prefix: true,
+            color: "black",
+            debug: false,
+            onValid: function() {},
+            onInvalid: function() {},
+            onSuccess: function() {},
+            onError: function() {}
+        };
+        if (options) {
+            for (option in options) {
+                this.settings[option] = options[option];
+            }
+        }
+        this._name = pluginName;
+        this.init();
+    }
+
+    return EAN13;
+
+})();
+
+if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
+    module.exports = EAN13;
+}

+ 51 - 0
dist/barcode/index.js

@@ -0,0 +1,51 @@
+import baseBehavior from '../helpers/baseBehavior'
+import barcode from './barcode'
+
+const defalutOptions = {
+    number: true,
+    prefix: true,
+    color: 'black',
+    debug: false,
+    onValid() {},
+    onInvalid() {},
+    onSuccess() {},
+    onError() {},
+}
+
+Component({
+    behaviors: [baseBehavior],
+    externalClasses: ['wux-class'],
+    properties: {
+        width: {
+            type: Number,
+            value: 200,
+        },
+        height: {
+            type: Number,
+            value: 100,
+        },
+        number: {
+            type: String,
+            value: '',
+            observer(newVal) {
+                this.draw({
+                    number: newVal,
+                })
+            },
+        },
+        options: {
+            type: Object,
+            value: defalutOptions,
+        },
+        canvasId: {
+            type: String,
+            value: 'wux-barcode',
+        },
+    },
+    methods: {
+        draw(opts = {}) {
+            const { canvasId, number, width, height, options } = Object.assign({}, this.data, opts)
+            new barcode(canvasId, number, Object.assign({ width, height }, options), this)
+        },
+    },
+})

+ 3 - 0
dist/barcode/index.json

@@ -0,0 +1,3 @@
+{
+    "component": true
+}

+ 1 - 0
dist/barcode/index.wxml

@@ -0,0 +1 @@
+<canvas class="wux-class" canvas-id="{{ canvasId }}" style="width: {{ width + 'px' }}; height: {{ height + 'px' }};"></canvas>

+ 0 - 0
dist/barcode/index.wxss


+ 98 - 0
dist/button/index.js

@@ -0,0 +1,98 @@
+Component({
+    externalClasses: ['wux-class', 'wux-hover-class'],
+    properties: {
+        type: {
+            type: String,
+            value: 'stable',
+        },
+        clear: {
+            type: Boolean,
+            value: false,
+        },
+        block: {
+            type: Boolean,
+            value: false,
+        },
+        full: {
+            type: Boolean,
+            value: false,
+        },
+        outline: {
+            type: Boolean,
+            value: false,
+        },
+        size: {
+            type: String,
+            value: 'default',
+        },
+        disabled: {
+            type: Boolean,
+            value: false,
+        },
+        loading: {
+            type: Boolean,
+            value: false,
+        },
+        formType: {
+            type: String,
+            value: '',
+        },
+        openType: {
+            type: String,
+            value: '',
+        },
+        hoverStopPropagation: {
+            type: Boolean,
+            value: false,
+        },
+        hoverStartTime: {
+            type: Number,
+            value: 20,
+        },
+        hoverStayTime: {
+            type: Number,
+            value: 70,
+        },
+        lang: {
+            type: String,
+            value: 'en',
+        },
+        sessionFrom: {
+            type: String,
+            value: '',
+        },
+        sendMessageTitle: {
+            type: String,
+            value: '',
+        },
+        sendMessagePath: {
+            type: String,
+            value: '',
+        },
+        sendMessageImg: {
+            type: String,
+            value: '',
+        },
+        showMessageCard: {
+            type: Boolean,
+            value: false,
+        },
+    },
+
+    methods: {
+        onTap() {
+            if (!this.data.disabled) {
+                this.triggerEvent('click')
+            }
+        },
+        bindgetuserinfo(e) {
+            this.triggerEvent('getuserinfo', e.detail)
+        },
+        bindcontact(e) {
+            this.triggerEvent('contact', e.detail)
+        },
+        bindgetphonenumber(e) {
+            this.triggerEvent('getphonenumber', e.detail)
+        },
+    },
+})

+ 3 - 0
dist/button/index.json

@@ -0,0 +1,3 @@
+{
+    "component": true
+}

+ 22 - 0
dist/button/index.wxml

@@ -0,0 +1,22 @@
+<button
+    class="wux-class wux-button {{ type ? 'wux-button--' + type : '' }} {{ size ? 'wux-button--' + size : '' }} {{ block ? 'wux-button--block' : '' }} {{ full ? 'wux-button--full' : '' }} {{ clear ? 'wux-button--clear' : '' }} {{ outline ? 'wux-button--outline' : '' }} {{ disabled ? 'wux-button--disabled' : '' }}"
+    loading="{{ loading }}"
+    form-type="{{ formType }}"
+    open-type="{{ openType }}"
+    hover-class="wux-hover-class {{ !disabled ? 'wux-button--hover' : 'none' }}"
+    hover-stop-propagation="{{ hoverStopPropagation }}"
+    hover-start-time="{{ hoverStartTime }}"
+    hover-stay-time="{{ hoverStayTime }}"
+    lang="{{ lang }}"
+    bindgetuserinfo="bindgetuserinfo"
+    session-from="{{ sessionFrom }}"
+    send-message-title="{{ sendMessageTitle }}"
+    send-message-path="{{ sendMessagePath }}"
+    send-message-img="{{ sendMessageImg }}"
+    show-message-card="{{ showMessageCard }}"
+    bindcontact="bindcontact"
+    bindgetphonenumber="bindgetphonenumber"
+    bindtap="onTap"
+>
+    <slot></slot>
+</button>

+ 309 - 0
dist/button/index.wxss

@@ -0,0 +1,309 @@
+.wux-button {
+  position: relative;
+  display: inline-block;
+  box-sizing: border-box;
+  margin: 0;
+  padding: 0 24rpx;
+  min-width: 104rpx;
+  min-height: 88rpx;
+  border: 2rpx solid transparent;
+  border-radius: 8rpx;
+  vertical-align: middle;
+  text-align: center;
+  text-overflow: ellipsis;
+  font-size: 32rpx;
+  line-height: 84rpx;
+  cursor: pointer;
+}
+.wux-button:after {
+  content: " ";
+  width: 100%;
+  height: 100%;
+  position: absolute;
+  top: -12rpx;
+  right: -12rpx;
+  bottom: -12rpx;
+  left: -12rpx;
+  border: none;
+  -webkit-transform: none;
+          transform: none;
+  -webkit-transform-origin: 0 0;
+          transform-origin: 0 0;
+  box-sizing: border-box;
+  border-radius: 0;
+}
+.wux-button--disabled {
+  opacity: .4;
+}
+.wux-button--small {
+  padding: 4rpx 8rpx 2rpx;
+  min-width: 56rpx;
+  min-height: 60rpx;
+  font-size: 24rpx;
+  line-height: 52rpx;
+}
+.wux-button--large {
+  padding: 0 32rpx;
+  min-width: 136rpx;
+  min-height: 118rpx;
+  font-size: 40rpx;
+  line-height: 106rpx;
+}
+.wux-button--block,
+.wux-button--full {
+  width: 100%;
+  margin-top: 20rpx;
+  margin-bottom: 20rpx;
+}
+.wux-button--block {
+  display: block;
+  clear: both;
+}
+.wux-button--block:after {
+  clear: both;
+}
+.wux-button--full {
+  display: block;
+  margin-right: 0;
+  margin-left: 0;
+  border-right-width: 0;
+  border-left-width: 0;
+  border-radius: 0;
+}
+.wux-button--outline.wux-button--hover {
+  color: #fff !important;
+}
+.wux-button--light {
+  border-color: transparent;
+  background-color: #fff;
+  color: #fff;
+}
+.wux-button--light.wux-button--outline {
+  border-color: #fff;
+  background-color: transparent;
+  color: #fff;
+}
+.wux-button--light.wux-button--clear {
+  background-color: transparent;
+  color: #e6e6e6;
+}
+.wux-button--light.wux-button--clear.wux-button--hover {
+  background-color: rgba(0, 0, 0, 0);
+  color: #fff;
+}
+.wux-button--light.wux-button--hover {
+  background-color: #e6e6e6;
+  color: #fff;
+}
+.wux-button--stable {
+  border-color: transparent;
+  background-color: #f8f8f8;
+  color: #fff;
+}
+.wux-button--stable.wux-button--outline {
+  border-color: #f8f8f8;
+  background-color: transparent;
+  color: #f8f8f8;
+}
+.wux-button--stable.wux-button--clear {
+  background-color: transparent;
+  color: #dfdfdf;
+}
+.wux-button--stable.wux-button--clear.wux-button--hover {
+  background-color: rgba(0, 0, 0, 0);
+  color: #f8f8f8;
+}
+.wux-button--stable.wux-button--hover {
+  background-color: #dfdfdf;
+  color: #fff;
+}
+.wux-button--positive {
+  border-color: transparent;
+  background-color: #387ef5;
+  color: #fff;
+}
+.wux-button--positive.wux-button--outline {
+  border-color: #387ef5;
+  background-color: transparent;
+  color: #387ef5;
+}
+.wux-button--positive.wux-button--clear {
+  background-color: transparent;
+  color: #0c60ee;
+}
+.wux-button--positive.wux-button--clear.wux-button--hover {
+  background-color: rgba(0, 0, 0, 0);
+  color: #387ef5;
+}
+.wux-button--positive.wux-button--hover {
+  background-color: #0c60ee;
+  color: #fff;
+}
+.wux-button--calm {
+  border-color: transparent;
+  background-color: #11c1f3;
+  color: #fff;
+}
+.wux-button--calm.wux-button--outline {
+  border-color: #11c1f3;
+  background-color: transparent;
+  color: #11c1f3;
+}
+.wux-button--calm.wux-button--clear {
+  background-color: transparent;
+  color: #0a9dc7;
+}
+.wux-button--calm.wux-button--clear.wux-button--hover {
+  background-color: rgba(0, 0, 0, 0);
+  color: #11c1f3;
+}
+.wux-button--calm.wux-button--hover {
+  background-color: #0a9dc7;
+  color: #fff;
+}
+.wux-button--assertive {
+  border-color: transparent;
+  background-color: #ef473a;
+  color: #fff;
+}
+.wux-button--assertive.wux-button--outline {
+  border-color: #ef473a;
+  background-color: transparent;
+  color: #ef473a;
+}
+.wux-button--assertive.wux-button--clear {
+  background-color: transparent;
+  color: #e42112;
+}
+.wux-button--assertive.wux-button--clear.wux-button--hover {
+  background-color: rgba(0, 0, 0, 0);
+  color: #ef473a;
+}
+.wux-button--assertive.wux-button--hover {
+  background-color: #e42112;
+  color: #fff;
+}
+.wux-button--balanced {
+  border-color: transparent;
+  background-color: #33cd5f;
+  color: #fff;
+}
+.wux-button--balanced.wux-button--outline {
+  border-color: #33cd5f;
+  background-color: transparent;
+  color: #33cd5f;
+}
+.wux-button--balanced.wux-button--clear {
+  background-color: transparent;
+  color: #28a54c;
+}
+.wux-button--balanced.wux-button--clear.wux-button--hover {
+  background-color: rgba(0, 0, 0, 0);
+  color: #33cd5f;
+}
+.wux-button--balanced.wux-button--hover {
+  background-color: #28a54c;
+  color: #fff;
+}
+.wux-button--energized {
+  border-color: transparent;
+  background-color: #ffc900;
+  color: #fff;
+}
+.wux-button--energized.wux-button--outline {
+  border-color: #ffc900;
+  background-color: transparent;
+  color: #ffc900;
+}
+.wux-button--energized.wux-button--clear {
+  background-color: transparent;
+  color: #cca100;
+}
+.wux-button--energized.wux-button--clear.wux-button--hover {
+  background-color: rgba(0, 0, 0, 0);
+  color: #ffc900;
+}
+.wux-button--energized.wux-button--hover {
+  background-color: #cca100;
+  color: #fff;
+}
+.wux-button--royal {
+  border-color: transparent;
+  background-color: #886aea;
+  color: #fff;
+}
+.wux-button--royal.wux-button--outline {
+  border-color: #886aea;
+  background-color: transparent;
+  color: #886aea;
+}
+.wux-button--royal.wux-button--clear {
+  background-color: transparent;
+  color: #643de4;
+}
+.wux-button--royal.wux-button--clear.wux-button--hover {
+  background-color: rgba(0, 0, 0, 0);
+  color: #886aea;
+}
+.wux-button--royal.wux-button--hover {
+  background-color: #643de4;
+  color: #fff;
+}
+.wux-button--dark {
+  border-color: transparent;
+  background-color: #444;
+  color: #fff;
+}
+.wux-button--dark.wux-button--outline {
+  border-color: #444;
+  background-color: transparent;
+  color: #444;
+}
+.wux-button--dark.wux-button--clear {
+  background-color: transparent;
+  color: #2b2b2b;
+}
+.wux-button--dark.wux-button--clear.wux-button--hover {
+  background-color: rgba(0, 0, 0, 0);
+  color: #444;
+}
+.wux-button--dark.wux-button--hover {
+  background-color: #2b2b2b;
+  color: #fff;
+}
+.wux-button--light {
+  border-color: transparent;
+  background-color: #fff;
+  color: #444;
+}
+.wux-button--light.wux-button--outline {
+  border-color: #ddd;
+  background-color: transparent;
+  color: #ddd;
+}
+.wux-button--light.wux-button--clear.wux-button--hover {
+  background-color: rgba(0, 0, 0, 0);
+  color: #ddd;
+}
+.wux-button--light.wux-button--hover {
+  background-color: #e6e6e6;
+  color: #fff;
+}
+.wux-button--stable {
+  border-color: transparent;
+  background-color: #f8f8f8;
+  color: #444;
+}
+.wux-button--stable.wux-button--outline {
+  border-color: #b2b2b2;
+  background-color: transparent;
+  color: #b2b2b2;
+}
+.wux-button--stable.wux-button--clear.wux-button--hover {
+  background-color: rgba(0, 0, 0, 0);
+  color: #b2b2b2;
+}
+.wux-button--stable.wux-button--hover {
+  background-color: #dfdfdf;
+  color: #fff;
+}

+ 717 - 0
dist/calendar/index.js

@@ -0,0 +1,717 @@
+import baseBehavior from '../helpers/baseBehavior'
+import mergeOptionsToData from '../helpers/mergeOptionsToData'
+import { $wuxBackdrop } from '../index'
+
+const defaults = {
+    monthNames: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
+    monthNamesShort: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
+    dayNames: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
+    dayNamesShort: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
+    firstDay: 1, // First day of the week, Monday
+    weekendDays: [0, 6], // Sunday and Saturday
+    multiple: false,
+    dateFormat: 'yyyy-mm-dd',
+    direction: 'horizontal', // or 'vertical'
+    minDate: null,
+    maxDate: null,