y595705120 3 vuotta sitten
commit
4c477df7b7
100 muutettua tiedostoa jossa 1604 lisäystä ja 0 poistoa
  1. 182 0
      app.js
  2. 73 0
      app.json
  3. 223 0
      app.wxss
  4. BIN
      assets/card.png
  5. BIN
      assets/cardback.png
  6. BIN
      assets/carousel/1.png
  7. BIN
      assets/carousel/2.png
  8. BIN
      assets/carousel/3.png
  9. BIN
      assets/carousel/4.png
  10. 16 0
      assets/css/select.wxss
  11. 48 0
      assets/css/style.wxss
  12. BIN
      assets/h1.png
  13. BIN
      assets/img_close.png
  14. BIN
      assets/img_gallery.png
  15. BIN
      assets/img_info.png
  16. BIN
      assets/img_share.png
  17. BIN
      assets/loading.gif
  18. BIN
      assets/nav/1.png
  19. BIN
      assets/nav/2.png
  20. BIN
      assets/nav/3.png
  21. BIN
      assets/nav/4.png
  22. BIN
      assets/nav/n1.png
  23. BIN
      assets/nav/n2.png
  24. BIN
      assets/nav/n3.png
  25. BIN
      assets/tabBar/exam-select.png
  26. BIN
      assets/tabBar/exam.png
  27. BIN
      assets/tabBar/index-select.png
  28. BIN
      assets/tabBar/index.png
  29. BIN
      assets/tabBar/my-select.png
  30. BIN
      assets/tabBar/my.png
  31. BIN
      assets/tabBar/record-select.png
  32. BIN
      assets/tabBar/record.png
  33. BIN
      assets/tabBar/study-select.png
  34. BIN
      assets/tabBar/study.png
  35. 47 0
      component/iView/action-sheet/index.js
  36. 8 0
      component/iView/action-sheet/index.json
  37. 23 0
      component/iView/action-sheet/index.wxml
  38. 1 0
      component/iView/action-sheet/index.wxss
  39. 37 0
      component/iView/alert/index.js
  40. 7 0
      component/iView/alert/index.json
  41. 15 0
      component/iView/alert/index.wxml
  42. 1 0
      component/iView/alert/index.wxss
  43. 20 0
      component/iView/avatar/index.js
  44. 3 0
      component/iView/avatar/index.json
  45. 4 0
      component/iView/avatar/index.wxml
  46. 1 0
      component/iView/avatar/index.wxss
  47. 29 0
      component/iView/badge/index.js
  48. 3 0
      component/iView/badge/index.json
  49. 5 0
      component/iView/badge/index.wxml
  50. 1 0
      component/iView/badge/index.wxss
  51. 37 0
      component/iView/base/index.js
  52. 80 0
      component/iView/button/index.js
  53. 3 0
      component/iView/button/index.json
  54. 20 0
      component/iView/button/index.wxml
  55. 1 0
      component/iView/button/index.wxss
  56. 26 0
      component/iView/card/index.js
  57. 3 0
      component/iView/card/index.json
  58. 11 0
      component/iView/card/index.wxml
  59. 84 0
      component/iView/card/index.wxss
  60. 33 0
      component/iView/cell-group/index.js
  61. 3 0
      component/iView/cell-group/index.json
  62. 3 0
      component/iView/cell-group/index.wxml
  63. 86 0
      component/iView/cell/index.js
  64. 3 0
      component/iView/cell/index.json
  65. 16 0
      component/iView/cell/index.wxml
  66. 1 0
      component/iView/cell/index.wxss
  67. 38 0
      component/iView/checkbox-group/index.js
  68. 7 0
      component/iView/checkbox-group/index.json
  69. 3 0
      component/iView/checkbox-group/index.wxml
  70. 0 0
      component/iView/checkbox-group/index.wxss
  71. 56 0
      component/iView/checkbox/index.js
  72. 7 0
      component/iView/checkbox/index.json
  73. 8 0
      component/iView/checkbox/index.wxml
  74. 1 0
      component/iView/checkbox/index.wxss
  75. 20 0
      component/iView/col/index.js
  76. 3 0
      component/iView/col/index.json
  77. 1 0
      component/iView/col/index.wxml
  78. 0 0
      component/iView/col/index.wxss
  79. 46 0
      component/iView/collapse-item/index.js
  80. 7 0
      component/iView/collapse-item/index.json
  81. 9 0
      component/iView/collapse-item/index.wxml
  82. 1 0
      component/iView/collapse-item/index.wxss
  83. 31 0
      component/iView/collapse/index.js
  84. 3 0
      component/iView/collapse/index.json
  85. 4 0
      component/iView/collapse/index.wxml
  86. 0 0
      component/iView/collapse/index.wxss
  87. 90 0
      component/iView/count-down/index.js
  88. 4 0
      component/iView/count-down/index.json
  89. 4 0
      component/iView/count-down/index.wxml
  90. 0 0
      component/iView/count-down/index.wxss
  91. 25 0
      component/iView/divider/index.js
  92. 3 0
      component/iView/divider/index.json
  93. 19 0
      component/iView/divider/index.wxml
  94. 1 0
      component/iView/divider/index.wxss
  95. 33 0
      component/iView/drawer/index.js
  96. 3 0
      component/iView/drawer/index.json
  97. 6 0
      component/iView/drawer/index.wxml
  98. 1 0
      component/iView/drawer/index.wxss
  99. 10 0
      component/iView/grid-icon/index.js
  100. 3 0
      component/iView/grid-icon/index.json

+ 182 - 0
app.js

@@ -0,0 +1,182 @@
+const { $Message} = require('/component/iView/base/index');
+const md5 = require('./utils/md5.js');
+const secret = "117c0743819088468e590246464cc75e"
+const {baseUrl} = require("./utils/util.js");
+const util = require('./utils/util.js');
+
+App({
+  globalData: {
+    pageSize: 10,
+    userInfo: {},
+    studyInfo: {},
+  },
+  onLaunch: function () {
+    this.autoUpgrade()
+  },
+  autoUpgrade: function () {
+    if (wx.canIUse('getUpdateManager')) {
+      const updateManager = wx.getUpdateManager()
+      updateManager.onCheckForUpdate(function (res) {
+        // 请求完新版本信息的回调
+        if (res.hasUpdate) {
+          console.log('res.hasUpdate====')
+          updateManager.onUpdateReady(function () {
+            wx.showModal({
+              title: '更新提示',
+              content: '新版本已经准备好,是否重启应用?',
+              success: function (res) {
+                console.log('success====', res)
+                if (res.confirm) {
+                  updateManager.applyUpdate()
+                }
+              }
+            })
+          })
+          updateManager.onUpdateFailed(function () {
+            // 新的版本下载失败
+            wx.showModal({
+              title: '已经有新版本了哟~',
+              content: '新版本已经上线啦~,请您删除当前小程序,重新搜索打开哟~'
+            })
+          })
+        }
+      })
+    }
+  },
+  gotoLogin: function(){
+    wx.navigateTo({
+      url: `/pages/user/identify/index`,
+    })
+  },
+  checkLogin: function (cb) {
+    let userInfo = this.globalData.userInfo
+    if( userInfo && userInfo.uid ){
+      cb && cb( userInfo)
+      return;
+    }
+    let _this = this
+    let openid = wx.getStorageSync('@openid');
+    if( !openid ) {
+      return
+    }
+    let param = {"openid": openid};
+    _this.formPost('Auth.wxLogin', param).then( res =>{
+      if (res.code == 200) {
+        _this.setUserInfo(res.data);
+        cb && cb(res.data);
+      }
+    })
+  },
+  // 
+  message: function (content, type="info") {
+    $Message({
+      content: content,
+      type: type
+    });
+  },
+  formPost: function (action, data) {
+    let _this = this
+    let userInfo = this.globalData.userInfo||{}
+    let user_id = userInfo.uid||0;
+    let token = userInfo.token||'';
+    let timestamp = Date.now()
+    action = action.toLowerCase()
+    let signstr = `weixin_${token}_${action}_${timestamp}_${secret}`
+    let signsure = md5.md5(signstr).toLowerCase()
+    let headers = {
+      'Content-Type': 'application/json',
+      'x-signsure': signsure,
+      'x-timestamp': timestamp,
+      'x-userId': user_id
+    }
+    return new Promise(function (resolve, reject) {
+      wx.showNavigationBarLoading();
+      wx.request({
+        url: `${baseUrl}weixin/${action}`,
+        header: headers,
+        method: 'POST',
+        data,
+        success(res) {
+          if (res.statusCode !== 200 || typeof res.data !== 'object') {
+            reject('网络出错')
+            return false;
+          }
+          if(res.data.code != 200 && res.data.code != 401){
+            util.showMsg(res.data.msg )
+          }
+          if(  res.data.code == 401  &&  action.indexOf( "auth.") == -1  ){
+            _this.gotoLogin()
+            return
+          }
+          resolve(res.data);
+          return true;
+        },
+        fail(res) {
+          reject(res.msg)
+          return false;
+        },
+        complete(res) {
+          wx.hideNavigationBarLoading();
+        }
+      })
+    })
+  },
+  studyPost: function (action, data) {
+    let {token, uid } = this.globalData.userInfo.studyUser;
+    let version = "1.0"
+    let _this = this
+    let mtime = parseInt(Date.now() / 1000)
+    action = action.toLowerCase()
+    let body = JSON.stringify(data);
+    let signstr = `hall_${version}${token}${body}${action}${mtime}${secret}`
+    let sign = md5.md5(signstr).toLowerCase()
+    let headers = {
+      'Content-Type': 'application/json'
+    }
+    let studyUrl = `${baseUrl}rental/${method}?t=${mtime}&u=${uid}&v=${version}&s=${sign}`
+    return new Promise(function (resolve, reject) {
+      wx.showNavigationBarLoading();
+      wx.request({
+        url: studyUrl,
+        header: headers,
+        method: 'POST',
+        data,
+        success(res) {
+          if (res.statusCode !== 200 || typeof res.data !== 'object') {
+            reject('网络出错')
+            return false;
+          }
+          resolve(res.data);
+          return true;
+        },
+        fail(res) {
+          reject(res.errMsg)
+          return false;
+        },
+        complete(res) {
+          wx.hideNavigationBarLoading();
+        }
+      })
+    })
+  },
+  getSystemInfo(  cb ){
+    wx.getSystemInfo({
+      success: function(res) {
+        cb &&cb( res.system )
+      }
+    })
+  },
+  checkNavigateTo: function(url){
+    let openid = wx.getStorageSync('@openid');
+    if( !openid ) return this.gotoLogin()
+    wx.navigateTo({url})
+  },
+  setUserInfo: function (userInfo) {
+    this.globalData.userInfo = userInfo;
+    if( userInfo.openid ){
+      console.log("@openid", userInfo.openid)
+      wx.setStorageSync('@openid', userInfo.openid )
+    }
+    wx.setStorageSync('@user', userInfo )
+  }
+})

+ 73 - 0
app.json

@@ -0,0 +1,73 @@
+{
+  "pages": [
+    "pages/index/index",
+    "pages/exam/index/index",
+    "pages/exam/answerIndex/index",
+    
+    "pages/exam/answer/answer",
+    "pages/exam/group/group",
+    "pages/exam/paper/paper",
+    "pages/exam/do/index",
+    
+    "pages/study/exam/index",
+    "pages/user/identify/index",
+    "pages/study/course/index",
+    "pages/my/index/index",
+    "pages/study/index/index",
+    "pages/study/sign/index",
+    "pages/study/market/index",
+    "pages/user/bind/index",
+    "pages/user/register/index",
+    "pages/my/message/info/index",
+    "pages/my/message/list/index",
+    "pages/exam/read/index",
+    "pages/exam/error/index",
+    "pages/exam/record/index",
+    "pages/train/index/index"
+  ],
+  "tabBar": {
+    "color": "#6e6d6b",
+    "selectedColor": "#ff9966",
+    "borderStyle": "black",
+    "backgroundColor": "#ffffff",
+    "list": [
+      {
+        "pagePath": "pages/index/index",
+        "text": "首页",
+        "iconPath": "/assets/tabBar/index.png",
+        "selectedIconPath": "/assets/tabBar/index-select.png"
+      },
+      {
+        "pagePath": "pages/exam/index/index",
+        "text": "在线练习",
+        "iconPath": "/assets/tabBar/exam.png",
+        "selectedIconPath": "/assets/tabBar/exam-select.png"
+      },
+      {
+        "pagePath": "pages/train/index/index",
+        "text": "岗前培训",
+        "iconPath": "/assets/tabBar/record.png",
+        "selectedIconPath": "/assets/tabBar/record-select.png"
+      },
+      {
+        "pagePath": "pages/study/index/index",
+        "text": "继续教育",
+        "iconPath": "/assets/tabBar/study.png",
+        "selectedIconPath": "/assets/tabBar/study-select.png"
+      },
+      {
+        "pagePath": "pages/my/index/index",
+        "text": "我的",
+        "iconPath": "/assets/tabBar/my.png",
+        "selectedIconPath": "/assets/tabBar/my-select.png"
+      }
+    ]
+  },
+  "window": {
+    "navigationBarBackgroundColor": "#ffffff",
+    "navigationBarTitleText": "鸿锵在线教育",
+    "navigationBarTextStyle": "black",
+    "backgroundTextStyle": "dark"
+  },
+  "sitemapLocation": "sitemap.json"
+}

+ 223 - 0
app.wxss

@@ -0,0 +1,223 @@
+/**app.wxss**/
+@import '/component/iView/button/index.wxss';
+@import '/component/iView/radio/index.wxss';
+@import '/component/iView/input/index.wxss';
+@import '/assets/css/style.wxss';
+@import '/assets/css/select.wxss';
+page {
+  /* Color 可以自定义相关配色 *//* 标准色 */
+  --red: #e54d42;
+  --orange: #f37b1d;
+  --yellow: #fbbd08;
+  --olive: #8dc63f;
+  --green: #39b54a;
+  --cyan: #1cbbb4;
+  --blue: #0081ff;
+  --purple: #6739b6;
+  --mauve: #9c26b0;
+  --pink: #e03997;
+  --brown: #a5673f;
+  --grey: #8799a3;
+  --black: #333;
+  --darkGray: #666;
+  --gray: #aaa;
+  --ghostWhite: #f1f1f1;
+  --white: #fff;
+  /* 浅色 */
+  --redLight: #fadbd9;
+  --orangeLight: #fde6d2;
+  --yellowLight: #fef2ce;
+  --oliveLight: #e8f4d9;
+  --greenLight: #d7f0db;
+  --cyanLight: #d2f1f0;
+  --blueLight: #cce6ff;
+  --purpleLight: #e1d7f0;
+  --mauveLight: #ebd4ef;
+  --pinkLight: #f9d7ea;
+  --brownLight: #ede1d9;
+  --greyLight: #e7ebed;
+  /* 渐变色 */
+  --gradualRed: linear-gradient(45deg, #f43f3b, #ec008c);
+  --gradualOrange: linear-gradient(45deg, #ff9700, #ed1c24);
+  --gradualGreen: linear-gradient(45deg, #39b54a, #8dc63f);
+  --gradualPurple: linear-gradient(45deg, #9000ff, #5e00ff);
+  --gradualPink: linear-gradient(45deg, #ec008c, #6739b6);
+  --gradualBlue: linear-gradient(45deg, #0081ff, #1cbbb4);
+  /* 阴影透明色 */
+  --ShadowSize: 6rpx 6rpx 8rpx;
+  --redShadow: rgba(204, 69, 59, 0.2);
+  --orangeShadow: rgba(217, 109, 26, 0.2);
+  --yellowShadow: rgba(224, 170, 7, 0.2);
+  --oliveShadow: rgba(124, 173, 55, 0.2);
+  --greenShadow: rgba(48, 156, 63, 0.2);
+  --cyanShadow: rgba(28, 187, 180, 0.2);
+  --blueShadow: rgba(0, 102, 204, 0.2);
+  --purpleShadow: rgba(88, 48, 156, 0.2);
+  --mauveShadow: rgba(133, 33, 150, 0.2);
+  --pinkShadow: rgba(199, 50, 134, 0.2);
+  --brownShadow: rgba(140, 88, 53, 0.2);
+  --greyShadow: rgba(114, 130, 138, 0.2);
+  --grayShadow: rgba(114, 130, 138, 0.2);
+  --blackShadow: rgba(26, 26, 26, 0.2);
+  background-color: var(--ghostWhite);
+  font-size: 28rpx;
+  color: var(--black);
+  font-family: Helvetica Neue, Helvetica, sans-serif;
+}
+
+.container {
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: space-between;
+  padding: 200rpx 0;
+  box-sizing: border-box;
+}
+
+.student-page {
+  background: white;
+}
+
+.student-page button {
+  height: 30px;
+  line-height: 30px;
+  margin-top: 7px;
+}
+
+.gapfilling-span {
+  color: red;
+  padding: 0px 30px;
+  margin: 0px 5px;
+  border-bottom: 3px double red;
+}
+
+.ueditor-p {
+  display: inline !important;
+}
+
+.exam-hidden {
+  display: none;
+}
+
+.exam-pick-input{
+  height: 30px;
+}
+.radio-answer {
+  line-height: 60rpx;
+  margin-top:16rpx;
+}
+.checkbox-answer{
+  margin-top:16rpx;
+  line-height: 60rpx;
+}
+.fs30{font-size: 30rpx;}
+.fs40{font-size: 40rpx;}
+.fs50{font-size: 50rpx;}
+.fs60{font-size: 60rpx;}
+
+
+.ml20{margin-left: 20rpx;}
+.ml40{margin-left: 40rpx;}
+.ml50{margin-left: 50rpx;}
+
+.mt5{margin-top: 5rpx;}
+.mt10{margin-top: 10rpx;}
+.mt20{margin-top: 20rpx;}
+.mt30{margin-top: 30rpx;}
+.mt40{margin-top: 40rpx;}
+.mt50{margin-top: 50rpx;}
+.tc{text-align: center;}
+.tl{text-align: left;}
+.tr{text-align: right;}
+
+.fl{float: left;}
+.fr{float: right;}
+.pt20{ padding-top: 20rpx;}
+.pt30{ padding-top: 30rpx;}
+
+.p10{ padding:10rpx;}
+.p20{ padding:20rpx;}
+.p30{ padding:30rpx;}
+
+.m10{ margin:10rpx;}
+.m20{ margin:20rpx;}
+.m30{ margin:30rpx;}
+
+
+.cu-tabbar-height {
+  min-height: 100rpx;
+  height: calc(100rpx + env(safe-area-inset-bottom) / 2);
+}
+
+.bg-white{ background:var(--white); }
+
+
+
+.cate-section {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-justify-content: space-around;
+      -ms-flex-pack: distribute;
+          justify-content: space-around;
+  -webkit-box-align: center;
+  -webkit-align-items: center;
+      -ms-flex-align: center;
+          align-items: center;
+  -webkit-flex-wrap: wrap;
+      -ms-flex-wrap: wrap;
+          flex-wrap: wrap;
+  padding: 30rpx 22rpx;
+  background: #fff;
+  /* 原图标颜色太深,不想改图了,所以加了透明度 */
+}
+.cate-section .cate-item {
+    display: -webkit-box;
+    display: -webkit-flex;
+    display: -ms-flexbox;
+    display: flex;
+    -webkit-box-orient: vertical;
+    -webkit-box-direction: normal;
+    -webkit-flex-direction: column;
+        -ms-flex-direction: column;
+            flex-direction: column;
+    -webkit-box-align: center;
+    -webkit-align-items: center;
+        -ms-flex-align: center;
+            align-items: center;
+    font-size: 26rpx;
+    background: #fff;
+    color: #5d626b;
+}
+.cate-section image {
+  width: 60rpx;
+  height: 60rpx;
+  margin-bottom: 14rpx;
+  border-radius: 10%;
+  opacity: .7;
+  -webkit-box-shadow: 4rpx 4rpx 20rpx rgba(250, 67, 106, 0.3);
+          box-shadow: 4rpx 4rpx 20rpx rgba(250, 67, 106, 0.3);
+}
+
+button::after {
+  border: none
+}
+.cate-item-3{
+  width:33.33%;
+  height:160rpx;
+  margin-top:40rpx
+}
+
+.cate-item-4{
+  width:25%;
+  height:160rpx;
+  margin-top:40rpx
+}
+
+
+.slide-image {
+  width: 100%;
+  height: 150px;
+}

BIN
assets/card.png


BIN
assets/cardback.png


BIN
assets/carousel/1.png


BIN
assets/carousel/2.png


BIN
assets/carousel/3.png


BIN
assets/carousel/4.png


+ 16 - 0
assets/css/select.wxss

@@ -0,0 +1,16 @@
+checkbox {
+  margin:10rpx;
+  height: auto;
+  /* font-size:16rpx; */
+}
+/*checkbox 选项框大小  */
+checkbox .wx-checkbox-input {
+  width: 40rpx;
+  height: 40rpx;
+  flex: none;
+}
+.radio .wx-radio-input{
+  width: 40rpx;
+  height: 40rpx;
+  flex: none;
+}

+ 48 - 0
assets/css/style.wxss

@@ -0,0 +1,48 @@
+.f-header {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-align: center;
+  -webkit-align-items: center;
+      -ms-flex-align: center;
+          align-items: center;
+  height: 120rpx;
+  padding: 6rpx 30rpx 8rpx;
+  background: #fff;
+}
+.f-header image {
+    -webkit-flex-shrink: 0;
+        -ms-flex-negative: 0;
+            flex-shrink: 0;
+    width: 80rpx;
+    height: 80rpx;
+    margin-right: 20rpx;
+}
+.f-header .tit-box {
+    -webkit-box-flex: 1;
+    -webkit-flex: 1;
+        -ms-flex: 1;
+            flex: 1;
+    display: -webkit-box;
+    display: -webkit-flex;
+    display: -ms-flexbox;
+    display: flex;
+    -webkit-box-orient: vertical;
+    -webkit-box-direction: normal;
+    -webkit-flex-direction: column;
+        -ms-flex-direction: column;
+            flex-direction: column;
+}
+.f-header .tit {
+    font-size: 34rpx;
+    line-height: 1.3;
+}
+.f-header .tit2 {
+    font-size: 24rpx;
+    color: #909399;
+}
+.f-header .icon-you {
+    font-size: 34rpx;
+    color: #909399;
+}

BIN
assets/h1.png


BIN
assets/img_close.png


BIN
assets/img_gallery.png


BIN
assets/img_info.png


BIN
assets/img_share.png


BIN
assets/loading.gif


BIN
assets/nav/1.png


BIN
assets/nav/2.png


BIN
assets/nav/3.png


BIN
assets/nav/4.png


BIN
assets/nav/n1.png


BIN
assets/nav/n2.png


BIN
assets/nav/n3.png


BIN
assets/tabBar/exam-select.png


BIN
assets/tabBar/exam.png


BIN
assets/tabBar/index-select.png


BIN
assets/tabBar/index.png


BIN
assets/tabBar/my-select.png


BIN
assets/tabBar/my.png


BIN
assets/tabBar/record-select.png


BIN
assets/tabBar/record.png


BIN
assets/tabBar/study-select.png


BIN
assets/tabBar/study.png


+ 47 - 0
component/iView/action-sheet/index.js

@@ -0,0 +1,47 @@
+Component({
+    externalClasses: ['i-class', 'i-class-mask', 'i-class-header'],
+
+    options: {
+        multipleSlots: true
+    },
+
+    properties: {
+        visible: {
+            type: Boolean,
+            value: false
+        },
+        maskClosable: {
+            type: Boolean,
+            value: true
+        },
+        showCancel: {
+            type: Boolean,
+            value: false
+        },
+        cancelText: {
+            type: String,
+            value: '取消'
+        },
+        actions: {
+            type: Array,
+            value: []
+        }
+    },
+
+    methods: {
+        handleClickMask () {
+            if (!this.data.maskClosable) return;
+            this.handleClickCancel();
+        },
+
+        handleClickItem ({ currentTarget = {} }) {
+            const dataset = currentTarget.dataset || {};
+            const { index } = dataset;
+            this.triggerEvent('click', { index });
+        },
+
+        handleClickCancel () {
+            this.triggerEvent('cancel');
+        }
+    }
+});

+ 8 - 0
component/iView/action-sheet/index.json

@@ -0,0 +1,8 @@
+{
+  "component": true,
+  "usingComponents":
+  {
+    "i-button": "../button/index",
+    "i-icon": "../icon/index"
+  }
+}

+ 23 - 0
component/iView/action-sheet/index.wxml

@@ -0,0 +1,23 @@
+<view class="i-as-mask i-class-mask {{ visible ? 'i-as-mask-show' : '' }}" bindtap="handleClickMask"></view>
+<view class="i-class i-as {{ visible ? 'i-as-show' : '' }}">
+    <view class="i-as-header i-class-header"><slot name="header"></slot></view>
+    <view class="i-as-actions">
+        <view class="i-as-action-item" wx:for="{{ actions }}" wx:key="name">
+            <i-button
+                bind:click="handleClickItem"
+                data-index="{{ index }}"
+                open-type="{{ item.openType }}"
+                type="ghost"
+                size="large"
+                long
+            >
+                <view class="i-as-btn-loading" wx:if="{{ item.loading }}"></view>
+                <i-icon wx:if="{{ item.icon }}" type="{{ item.icon }}" i-class="i-as-btn-icon"></i-icon>
+                <view class="i-as-btn-text" style="{{ item.color ? 'color: ' + item.color : '' }}">{{ item.name }}</view>
+            </i-button>
+        </view>
+    </view>
+    <view class="i-as-cancel" wx:if="{{ showCancel }}">
+        <i-button i-class="i-as-cancel-btn" type="ghost" size="large" long="true" bind:click="handleClickCancel">{{ cancelText }}</i-button>
+    </view>
+</view>

+ 1 - 0
component/iView/action-sheet/index.wxss

@@ -0,0 +1 @@
+.i-as{position:fixed;width:100%;box-sizing:border-box;left:0;right:0;bottom:0;background:#f7f7f7;transform:translate3d(0,100%,0);transform-origin:center;transition:all .2s ease-in-out;z-index:900;visibility:hidden}.i-as-show{transform:translate3d(0,0,0);visibility:visible}.i-as-mask{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.7);z-index:900;transition:all .2s ease-in-out;opacity:0;visibility:hidden}.i-as-mask-show{opacity:1;visibility:visible}.i-as-action-item{position:relative}.i-as-action-item::after{content:'';position:absolute;top:0;left:0;width:200%;height:200%;transform:scale(.5);transform-origin:0 0;pointer-events:none;box-sizing:border-box;border:0 solid #e9eaec;border-bottom-width:1px}.i-as-header{background:#fff;text-align:center;position:relative;font-size:12px;color:#80848f}.i-as-header::after{content:'';position:absolute;top:0;left:0;width:200%;height:200%;transform:scale(.5);transform-origin:0 0;pointer-events:none;box-sizing:border-box;border:0 solid #e9eaec;border-bottom-width:1px}.i-as-cancel{margin-top:6px}.i-as-btn-loading{display:inline-block;vertical-align:middle;margin-right:10px;width:12px;height:12px;background:0 0;border-radius:50%;border:2px solid #e5e5e5;border-color:#666 #e5e5e5 #e5e5e5 #e5e5e5;animation:btn-spin .6s linear;animation-iteration-count:infinite}.i-as-btn-text{display:inline-block;vertical-align:middle}.i-as-btn-icon{font-size:14px!important;margin-right:4px}@keyframes btn-spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}

+ 37 - 0
component/iView/alert/index.js

@@ -0,0 +1,37 @@
+Component({
+    externalClasses: ['i-class'],
+    options: {
+        multipleSlots: true
+    },
+    properties: {
+        //info, success, warning, error
+        type: {
+            type: String,
+            value: 'info'
+        },
+        closable: {
+            type: Boolean,
+            value: false
+        },
+        showIcon: {
+            type: Boolean,
+            default: false
+        },
+        desc: {
+            type: Boolean,
+            default: false
+        },
+    },
+    data: {
+        closed: false
+    },
+    methods: {
+        handleTap() {
+            this.setData({
+                closed: !this.data.closed,
+            });
+            this.triggerEvent('close');
+        },
+
+    }
+});

+ 7 - 0
component/iView/alert/index.json

@@ -0,0 +1,7 @@
+{
+    "component": true,
+    "usingComponents":
+    {
+        "i-icon": "../icon/index"
+    }
+}

+ 15 - 0
component/iView/alert/index.wxml

@@ -0,0 +1,15 @@
+<view class="i-class i-alert {{'i-alert-'+type}} {{showIcon?'i-alert-with-icon':''}} {{desc?'i-alert-with-desc':''}}" wx:if="{{!closed}}">
+    <view wx:if="{{ showIcon }}" class="i-alert-icon">
+        <i-icon type="prompt" wx:if="{{ type === 'info' }}" size="{{desc?24:16}}"></i-icon>
+        <i-icon type="success" wx:if="{{ type === 'success' }}" size="{{desc?24:16}}"></i-icon>
+        <i-icon type="warning" wx:if="{{ type === 'warning' }}" size="{{desc?24:16}}"></i-icon>
+        <i-icon type="delete" wx:if="{{ type === 'error' }}" size="{{desc?24:16}}"></i-icon>
+    </view>
+    <slot></slot>
+    <view class="i-alert-desc">
+        <slot name="desc"></slot>
+    </view>
+    <view class="i-alert-close" wx:if="{{ closable }}" bindtap="handleTap">
+        <i-icon type="close"></i-icon>
+    </view>
+</view>

+ 1 - 0
component/iView/alert/index.wxss

@@ -0,0 +1 @@
+.i-alert{position:relative;margin:10px;padding:8px 48px 8px 16px;font-size:14px;border-radius:2px;color:#fff;background:#f7f7f7;color:#495060}.i-alert.i-alert-with-icon{padding:8px 48px 8px 38px}.i-alert-info{color:#fff;background:#2db7f5}.i-alert-success{color:#fff;background:#19be6b}.i-alert-warning{color:#fff;background:#f90}.i-alert-error{color:#fff;background:#ed3f14}.i-alert-icon{position:absolute;top:9px;left:16px;font-size:14px}.i-alert-desc{font-size:12px}.i-alert-with-desc{padding:16px;position:relative}.i-alert-with-desc.i-alert-with-icon{padding:16px 16px 16px 69px}.i-alert-with-desc .i-alert-icon{top:50%;left:24px;margin-top:-21px;font-size:28px}.i-alert-close{font-size:12px;position:absolute;right:16px;top:8px;overflow:hidden;cursor:pointer}

+ 20 - 0
component/iView/avatar/index.js

@@ -0,0 +1,20 @@
+Component({
+    externalClasses: ['i-class'],
+
+    properties: {
+        // circle || square
+        shape: {
+            type: String,
+            value: 'circle'
+        },
+        // small || large || default
+        size: {
+            type: String,
+            value: 'default'
+        },
+        src: {
+            type: String,
+            value: ''
+        }
+    }
+});

+ 3 - 0
component/iView/avatar/index.json

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

+ 4 - 0
component/iView/avatar/index.wxml

@@ -0,0 +1,4 @@
+<view class="i-class i-avatar i-avatar-{{ shape }} i-avatar-{{ size }} {{ src ? 'i-avatar-image' : '' }}">
+    <image src="{{ src }}" wx:if="{{ src !== '' }}"></image>
+    <view class="i-avatar-string" wx:else><slot></slot></view>
+</view>

+ 1 - 0
component/iView/avatar/index.wxss

@@ -0,0 +1 @@
+.i-avatar{display:inline-block;text-align:center;background:#ccc;color:#fff;white-space:nowrap;position:relative;overflow:hidden;vertical-align:middle;width:32px;height:32px;line-height:32px;border-radius:16px;font-size:18px}.i-avatar .ivu-avatar-string{line-height:32px}.i-avatar-large{width:40px;height:40px;line-height:40px;border-radius:20px;font-size:24px}.i-avatar-large .ivu-avatar-string{line-height:40px}.i-avatar-small{width:24px;height:24px;line-height:24px;border-radius:12px;font-size:14px}.i-avatar-small .ivu-avatar-string{line-height:24px}.i-avatar-image{background:0 0}.i-avatar-square{border-radius:4px}.i-avatar>image{width:100%;height:100%}

+ 29 - 0
component/iView/badge/index.js

@@ -0,0 +1,29 @@
+Component({
+    externalClasses: ['i-class', 'i-class-alone'],
+
+    properties: {
+        count: {
+            type: Number,
+            value: 0,
+            observer: 'finalCount'
+        },
+        overflowCount: {
+            type: Number,
+            value: 99
+        },
+        dot: {
+            type: Boolean,
+            value: false
+        },
+    },
+    data: {
+        finalCount: 0
+    },
+    methods: {
+        finalCount() {
+            this.setData({
+                finalCount: parseInt(this.data.count) >= parseInt(this.data.overflowCount) ? `${this.data.overflowCount}+` : this.data.count
+            });
+        },
+    }
+});

+ 3 - 0
component/iView/badge/index.json

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

+ 5 - 0
component/iView/badge/index.wxml

@@ -0,0 +1,5 @@
+<view class="i-class i-badge">
+    <slot></slot>
+    <view class="i-badge-dot" wx:if="{{ dot }}"></view>
+    <view class="i-badge-count i-class-alone" wx:elif="{{ count !== 0 }}">{{ finalCount }}</view>
+</view>

+ 1 - 0
component/iView/badge/index.wxss

@@ -0,0 +1 @@
+.i-badge{position:relative;display:inline-block;line-height:1;vertical-align:middle}.i-badge-count{position:absolute;transform:translateX(50%);top:-6px;right:0;height:18px;border-radius:9px;min-width:18px;background:#ed3f14;border:1px solid transparent;color:#fff;line-height:18px;text-align:center;padding:0 5px;font-size:12px;white-space:nowrap;transform-origin:-10% center;z-index:10;box-shadow:0 0 0 1px #fff;box-sizing:border-box;text-rendering:optimizeLegibility}.i-badge-count-alone{top:auto;display:block;position:relative;transform:translateX(0)}.i-badge-dot{position:absolute;transform:translateX(-50%);transform-origin:0 center;top:-4px;right:-8px;height:8px;width:8px;border-radius:100%;background:#ed3f14;z-index:10;box-shadow:0 0 0 1px #fff}

+ 37 - 0
component/iView/base/index.js

@@ -0,0 +1,37 @@
+function getCtx (selector) {
+    const pages = getCurrentPages();
+    const ctx = pages[pages.length - 1];
+
+    const componentCtx = ctx.selectComponent(selector);
+
+    if (!componentCtx) {
+        console.error('无法找到对应的组件,请按文档说明使用组件');
+        return null;
+    }
+    return componentCtx;
+}
+
+function Toast(options) {
+    const { selector = '#toast' } = options;
+    const ctx = getCtx(selector);
+
+    ctx.handleShow(options);
+}
+
+Toast.hide = function (selector = '#toast') {
+    const ctx = getCtx(selector);
+
+    ctx.handleHide();
+};
+
+function Message(options) {
+    const { selector = '#message' } = options;
+    const ctx = getCtx(selector);
+
+    ctx.handleShow(options);
+}
+
+module.exports = {
+    $Toast: Toast,
+    $Message: Message
+};

+ 80 - 0
component/iView/button/index.js

@@ -0,0 +1,80 @@
+Component({
+    externalClasses: ['i-class'],
+
+    properties: {
+        // default, primary, ghost, info, success, warning, error
+        type: {
+            type: String,
+            value: '',
+        },
+        inline: {
+            type: Boolean,
+            value: false
+        },
+        // default, large, small
+        size: {
+            type: String,
+            value: '',
+        },
+        // circle, square
+        shape: {
+            type: String,
+            value: 'square'
+        },
+        disabled: {
+            type: Boolean,
+            value: false,
+        },
+        loading: {
+            type: Boolean,
+            value: false,
+        },
+        long: {
+            type: Boolean,
+            value: false
+        },
+        openType: String,
+        appParameter: String,
+        hoverStopPropagation: Boolean,
+        hoverStartTime: {
+            type: Number,
+            value: 20
+        },
+        hoverStayTime: {
+            type: Number,
+            value: 70
+        },
+        lang: {
+            type: String,
+            value: 'en'
+        },
+        sessionFrom: {
+            type: String,
+            value: ''
+        },
+        sendMessageTitle: String,
+        sendMessagePath: String,
+        sendMessageImg: String,
+        showMessageCard: Boolean
+    },
+
+    methods: {
+        handleTap () {
+            if (this.data.disabled) return false;
+
+            this.triggerEvent('click');
+        },
+        bindgetuserinfo({ detail = {} } = {}) {
+            this.triggerEvent('getuserinfo', detail);
+        },
+        bindcontact({ detail = {} } = {}) {
+            this.triggerEvent('contact', detail);
+        },
+        bindgetphonenumber({ detail = {} } = {}) {
+            this.triggerEvent('getphonenumber', detail);
+        },
+        binderror({ detail = {} } = {}) {
+            this.triggerEvent('error', detail);
+        }
+    }
+});

+ 3 - 0
component/iView/button/index.json

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

+ 20 - 0
component/iView/button/index.wxml

@@ -0,0 +1,20 @@
+<button
+    class="i-class i-btn {{ long ? 'i-btn-long' : '' }} {{ 'i-btn-' + size }} {{ 'i-btn-' + type }} {{ 'i-btn-' + shape }} {{ loading ? 'i-btn-loading' : '' }} {{ disabled ? 'i-btn-disabled' : ''}} {{ inline ? 'i-btn-inline' : '' }}"
+    hover-class="i-btn-hover"
+    bindtap="handleTap"
+    open-type="{{ openType }}"
+    app-parameter="{{ appParameter }}"
+    hover-stop-propagation="{{ hoverStopPropagation }}"
+    hover-start-time="{{ hoverStartTime }}"
+    hover-stay-time="{{ hoverStayTime }}"
+    session-from="{{ sessionFrom }}"
+    send-message-title="{{ sendMessageTitle }}"
+    send-message-path="{{ sendMessagePath }}"
+    send-message-img="{{ sendMessageImg }}"
+    show-message-card="{{ showMessageCard }}"
+    bindcontact="bindcontact"
+    bindgetuserinfo="bindgetuserinfo"
+    bindgetphonenumber="bindgetphonenumber"
+    binderror="binderror"
+    plain="true"
+><view class="i-btn-loading-inner" wx:if="{{loading}}"></view><slot></slot></button>

+ 1 - 0
component/iView/button/index.wxss

@@ -0,0 +1 @@
+.i-btn{text-align:center;vertical-align:middle;touch-action:manipulation;cursor:pointer;background-image:none;white-space:nowrap;user-select:none;font-size:14px;border-radius:2px;border:0!important;position:relative;text-decoration:none;height:44px;line-height:44px;box-shadow:inset 0 0 0 1px rgba(0,0,0,.1);color:#fff!important;background:#f7f7f7!important;color:#495060!important;margin:10px}.i-btn-hover{opacity:.9}.i-btn-long{border-radius:0;margin:0;box-shadow:none}.i-btn-large{height:48px;line-height:48px}.i-btn-small{height:40px;line-height:40px}.i-btn-primary{color:#fff!important;background:#2d8cf0!important}.i-btn-ghost{color:#fff!important;background:#fff!important;color:#495060!important}.i-btn-success{color:#fff!important;background:#19be6b!important}.i-btn-warning{color:#fff!important;background:#f90!important}.i-btn-error{color:#fff!important;background:#ed3f14!important}.i-btn-info{color:#fff!important;background:#2db7f5!important}.i-btn-circle{border-radius:44px}.i-btn-large.i-btn-circle{border-radius:48px}.i-btn-small.i-btn-circle{border-radius:40px}.i-btn-loading{opacity:.6}.i-btn-loading-inner{display:inline-block;margin-right:12px;vertical-align:middle;width:14px;height:14px;background:0 0;border-radius:50%;border:2px solid #fff;border-color:#fff #fff #fff transparent;animation:btn-spin .6s linear;animation-iteration-count:infinite}.i-btn-disabled{color:#bbbec4!important;background:#f7f7f7!important}.i-btn-inline{display:inline-block}@keyframes btn-spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}

+ 26 - 0
component/iView/card/index.js

@@ -0,0 +1,26 @@
+Component({
+    externalClasses: ['i-class'],
+
+    options: {
+        multipleSlots: true
+    },
+
+    properties: {
+        full: {
+            type: Boolean,
+            value: false
+        },
+        thumb: {
+            type: String,
+            value: ''
+        },
+        title: {
+            type: String,
+            value: ''
+        },
+        extra: {
+            type: String,
+            value: ''
+        }
+    }
+});

+ 3 - 0
component/iView/card/index.json

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

+ 11 - 0
component/iView/card/index.wxml

@@ -0,0 +1,11 @@
+<view class="i-class i-card {{ full ? 'i-card-full' : '' }}">
+    <view class="i-class i-card-header">
+        <view class="i-card-header-content">
+            <image class="i-card-header-thumb" src="{{ thumb }}" mode="aspectFit" wx:if="{{ thumb }}" />
+            {{ title }}
+        </view>
+        <view class="i-card-header-extra" wx:if="{{ extra }}">{{ extra }}</view>
+    </view>
+    <view class="i-class i-card-body"><slot name="content"></slot></view>
+    <view class="i-class i-card-footer"><slot name="footer"></slot></view>
+</view>

+ 84 - 0
component/iView/card/index.wxss

@@ -0,0 +1,84 @@
+.i-card {
+  margin: 0 16px;
+  font-size: 14px;
+  overflow: hidden;
+  position: relative;
+  background: #fff;
+  border: 1rpx solid #dddee1;
+  border-radius: 5px
+}
+
+.i-card-full {
+  margin: 0;
+  border-left: none;
+  border-right: none;
+  border-radius: 0
+}
+
+.i-card-header {
+  display: flex;
+  padding: 6px 16px;
+  align-items: center
+}
+
+.i-card-header-content {
+  flex: 1;
+  color: #0081ff;
+  font-size: 32rpx;
+  text-align: left
+}
+
+.i-card-header-thumb {
+  display: inline-block;
+  width: 64px;
+  height: 64px;
+  position: relative;
+  margin-left: auto;
+  margin-right: auto;
+  overflow: hidden;
+  background-size: cover;
+  vertical-align: middle
+}
+
+.i-card-header-title {
+  display: inline-block;
+  vertical-align: middle;
+  font-size: 14px;
+  color: #1c2438
+}
+
+.i-card-header-extra {
+  flex: 1;
+  text-align: right;
+  font-size: 14px;
+  color: #80848f
+}
+
+.i-card-body {
+  position: relative;
+  padding: 6px 16px;
+  color: #495060;
+  font-size: 14px
+}
+
+.i-card-body::before {
+  content: '';
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 200%;
+  height: 200%;
+  transform: scale(.5);
+  transform-origin: 0 0;
+  pointer-events: none;
+  box-sizing: border-box;
+  border: 0 solid #e9eaec;
+  border-top-width: 1px
+}
+
+.i-card-footer {
+  position: relative;
+  padding: 6px 16px;
+  color: #80848f;
+  font-size: 12px
+}

+ 33 - 0
component/iView/cell-group/index.js

@@ -0,0 +1,33 @@
+Component({
+    externalClasses: ['i-class'],
+
+    relations: {
+        '../cell/index': {
+            type: 'child',
+            linked () {
+                this._updateIsLastCell();
+            },
+            linkChanged () {
+                this._updateIsLastCell();
+            },
+            unlinked () {
+                this._updateIsLastCell();
+            }
+        }
+    },
+
+    methods: {
+        _updateIsLastCell() {
+            let cells = this.getRelationNodes('../cell/index');
+            const len = cells.length;
+
+            if (len > 0) {
+                let lastIndex = len - 1;
+
+                cells.forEach((cell, index) => {
+                    cell.updateIsLastCell(index === lastIndex);
+                });
+            }
+        }
+    }
+});

+ 3 - 0
component/iView/cell-group/index.json

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

+ 3 - 0
component/iView/cell-group/index.wxml

@@ -0,0 +1,3 @@
+<view class="i-class i-cell-group">
+    <slot></slot>
+</view>

+ 86 - 0
component/iView/cell/index.js

@@ -0,0 +1,86 @@
+const warn = (msg, getValue) => {
+    console.warn(msg);
+    console.log('接受到的值为:', getValue);
+};
+
+Component({
+    externalClasses: ['i-class'],
+
+    options: {
+        multipleSlots: true
+    },
+
+    relations: {
+        '../cell-group/index': {
+            type: 'parent'
+        }
+    },
+
+    properties: {
+        // 左侧标题
+        title: {
+            type: String
+        },
+        // 标题下方的描述信息
+        label: {
+            type: String
+        },
+        // 右侧内容
+        value: {
+            type: String
+        },
+        // 只有点击 footer 区域才触发 tab 事件
+        onlyTapFooter: {
+            type: Boolean
+        },
+        // 是否展示右侧箭头并开启尝试以 url 跳转
+        isLink: {
+            type: null,
+            value: ''
+        },
+        // 链接类型,可选值为 navigateTo,redirectTo,switchTab,reLaunch
+        linkType: {
+            type: String,
+            value: 'navigateTo'
+        },
+        url: {
+            type: String,
+            value: ''
+        }
+    },
+
+    data: {
+        isLastCell: true
+    },
+
+    methods: {
+        navigateTo () {
+            const { url } = this.data;
+            const type = typeof this.data.isLink;
+
+            this.triggerEvent('click', {});
+
+            if (!this.data.isLink || !url || url === 'true' || url === 'false') return;
+
+            if (type !== 'boolean' && type !== 'string') {
+                warn('isLink 属性值必须是一个字符串或布尔值', this.data.isLink);
+                return;
+            }
+
+            if (['navigateTo', 'redirectTo', 'switchTab', 'reLaunch'].indexOf(this.data.linkType) === -1) {
+                warn('linkType 属性可选值为 navigateTo,redirectTo,switchTab,reLaunch', this.data.linkType);
+                return;
+            }
+            wx[this.data.linkType].call(wx, {url});
+        },
+        handleTap () {
+            if (!this.data.onlyTapFooter) {
+                this.navigateTo();
+            }
+        },
+
+        updateIsLastCell (isLastCell) {
+            this.setData({ isLastCell });
+        }
+    }
+});

+ 3 - 0
component/iView/cell/index.json

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

+ 16 - 0
component/iView/cell/index.wxml

@@ -0,0 +1,16 @@
+<view bindtap="handleTap" class="i-class i-cell {{ isLastCell ? 'i-cell-last' : '' }} {{ isLink ? 'i-cell-access' : '' }}">
+    <view class="i-cell-icon">
+        <slot name="icon"></slot>
+    </view>
+    <view class="i-cell-bd">
+        <view wx:if="{{ title }}" class="i-cell-text">{{ title }}</view>
+        <view wx:if="{{ label }}" class="i-cell-desc">{{ label }}</view>
+        <slot></slot>
+    </view>
+    <view catchtap="navigateTo" class="i-cell-ft">
+        <block wx:if="{{value}}">{{ value }}</block>
+        <block wx:else>
+            <slot name="footer"></slot>
+        </block>
+    </view>
+</view>

+ 1 - 0
component/iView/cell/index.wxss

@@ -0,0 +1 @@
+.i-cell{position:relative;padding:12px 15px;display:flex;background:#fff;align-items:center;line-height:1.4;font-size:14px;overflow:hidden}.i-cell::after{content:'';position:absolute;top:0;left:0;width:200%;height:200%;transform:scale(.5);transform-origin:0 0;pointer-events:none;box-sizing:border-box;border:0 solid #e9eaec;border-bottom-width:1px;left:15px;right:0}.i-cell-last::after{display:none}.i-cell-icon{margin-right:5px}.i-cell-icon:empty{display:none}.i-cell-bd{flex:1}.i-cell-text{line-height:24px;font-size:14px}.i-cell-desc{line-height:1.2;font-size:12px;color:#80848f}.i-cell-ft{position:relative;text-align:right;color:#495060}.i-cell-access .i-cell-ft{padding-right:13px}.i-cell-access .i-cell-ft::after{content:" ";display:inline-block;width:6px;height:6px;position:absolute;top:50%;right:2px;border-width:2px 2px 0 0;border-color:#dddee1;border-style:solid;transform:translateY(-50%) matrix(.71,.71,-.71,.71,0,0)}

+ 38 - 0
component/iView/checkbox-group/index.js

@@ -0,0 +1,38 @@
+Component({
+    externalClasses: ['i-class'],
+    relations: {
+        '../checkbox/index': {
+            type: 'child',
+            linked() {
+                this.changeCurrent();
+            },
+            linkChanged() {
+                this.changeCurrent();
+            },
+            unlinked() {
+                this.changeCurrent();
+            }
+        }
+    },
+    properties: {
+        current: {
+            type: Array,
+            value: [],
+            observer: 'changeCurrent'
+        },
+    },
+    methods: {
+        changeCurrent(val = this.data.current) {
+            let items = this.getRelationNodes('../checkbox/index');
+            const len = items.length;
+            if (len > 0) {
+                items.forEach(item => {
+                    item.changeCurrent(val.indexOf(item.data.value) !== -1);
+                });
+            }
+        },
+        emitEvent(current) {
+            this.triggerEvent('change', current);
+        }
+    }
+});

+ 7 - 0
component/iView/checkbox-group/index.json

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

+ 3 - 0
component/iView/checkbox-group/index.wxml

@@ -0,0 +1,3 @@
+<i-cell-group class="i-class">
+    <slot></slot>
+</i-cell-group>

+ 0 - 0
component/iView/checkbox-group/index.wxss


+ 56 - 0
component/iView/checkbox/index.js

@@ -0,0 +1,56 @@
+const prefixCls = 'i-checkbox';
+
+Component({
+    externalClasses: ['i-class'],
+    relations: {
+        '../checkbox-group/index': {
+            type: 'parent'
+        }
+    },
+    properties: {
+        value: {
+            type: String,
+            value: ''
+        },
+        checked: {
+            type: Boolean,
+            value: false
+        },
+        disabled: {
+            type: Boolean,
+            value: false
+        },
+        color: {
+            type: String,
+            value: '#2d8cf0'
+        },
+        position: {
+            type: String,
+            value: 'left', //left right
+            observer: 'setPosition'
+        }
+    },
+    data: {
+        checked: true,
+        positionCls: `${prefixCls}-checkbox-left`,
+    },
+    attached() {
+        this.setPosition();
+    },
+    methods: {
+        changeCurrent(current) {
+            this.setData({ checked: current });
+        },
+        checkboxChange() {
+            if (this.data.disabled) return;
+            const item = { current: !this.data.checked, value: this.data.value };
+            const parent = this.getRelationNodes('../checkbox-group/index')[0];
+            parent ? parent.emitEvent(item) : this.triggerEvent('change', item);
+        },
+        setPosition() {
+            this.setData({
+                positionCls: this.data.position.indexOf('left') !== -1 ? `${prefixCls}-checkbox-left` : `${prefixCls}-checkbox-right`,
+            });
+        }
+    }
+});

+ 7 - 0
component/iView/checkbox/index.json

@@ -0,0 +1,7 @@
+{
+    "component": true,
+    "usingComponents":
+    {
+        "i-cell": "../cell/index"
+    }
+}

+ 8 - 0
component/iView/checkbox/index.wxml

@@ -0,0 +1,8 @@
+<view class="i-class i-checkbox" catchtap="checkboxChange">
+    <i-cell i-class="i-checkbox-cell">
+        <label>
+            <radio value="{{value}}" checked="{{checked}}" color="{{checked?color:''}}" disabled="{{disabled}}" class="i-checkbox-radio {{positionCls}}" />
+            <view class="i-checkbox-title">{{value}}</view>
+        </label>
+    </i-cell>
+</view>

+ 1 - 0
component/iView/checkbox/index.wxss

@@ -0,0 +1 @@
+.i-checkbox-cell::after{display:block}.i-checkbox-checkbox-left{float:left}.i-checkbox-checkbox-right{float:right}.i-checkbox-radio{vertical-align:middle}.i-checkbox-title{display:inline-block;vertical-align:middle}

+ 20 - 0
component/iView/col/index.js

@@ -0,0 +1,20 @@
+Component({
+    externalClasses: ['i-class'],
+
+    relations: {
+        '../row/index': {
+            type: 'parent'
+        }
+    },
+
+    properties: {
+        span: {
+            value: 0,
+            type: Number
+        },
+        offset: {
+            value: 0,
+            type: Number
+        }
+    }
+});

+ 3 - 0
component/iView/col/index.json

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

+ 1 - 0
component/iView/col/index.wxml

@@ -0,0 +1 @@
+<view class="i-class i-col {{ span ? 'i-col-span-' + span : '' }} {{ offset ? 'i-col-offset-' + offset : '' }}"><slot></slot></view>

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
component/iView/col/index.wxss


+ 46 - 0
component/iView/collapse-item/index.js

@@ -0,0 +1,46 @@
+Component({
+    externalClasses: ['i-class-content', 'i-class-title', 'i-class'],
+
+    relations: {
+        '../collapse/index': {
+            type: 'parent',
+            linked: function (target) {
+                const options = {
+                    accordion: target.data.accordion
+                }
+                if (target.data.name === this.data.name) {
+                    options.showContent = 'i-collapse-item-show-content';
+                }
+                this.setData(options);
+            }
+        }
+    },
+
+    properties: {
+        title: String,
+        name: String
+    },
+
+    data: {
+        showContent: '',
+        accordion: false
+    },
+
+    options: {
+        multipleSlots: true
+    },
+
+    methods: {
+        trigger(e) {
+            const data = this.data;
+            if (data.accordion) {
+                this.triggerEvent('collapse', {name: data.name}, {composed: true, bubbles: true});
+            } else {
+                this.setData({
+                    showContent: data.showContent ? '' : 'i-collapse-item-show-content'
+                });
+            }
+        },
+    }
+});
+

+ 7 - 0
component/iView/collapse-item/index.json

@@ -0,0 +1,7 @@
+
+{
+  "component": true,
+  "usingComponents": {
+    "i-icon": "../icon/index"
+  }
+}

+ 9 - 0
component/iView/collapse-item/index.wxml

@@ -0,0 +1,9 @@
+<view id="{{name}}" class="i-class i-collapse-item ">
+    <view class="i-collapse-item-title-wrap" bindtap="trigger">
+        <i-icon size="16" type="enter" i-class="{{ showContent ? 'i-collapse-item-arrow-show' : 'i-collapse-item-arrow' }}"/>
+        <text class="i-collapse-item-title i-class-title">{{title}}</text>
+    </view>
+    <view class="i-collapse-item-content {{showContent}}  i-class-content">
+        <slot name="content"></slot>
+    </view>
+</view>

+ 1 - 0
component/iView/collapse-item/index.wxss

@@ -0,0 +1 @@
+.i-collapse-item{padding:2px 8px;border-top:1px solid #dddee1}.i-collapse-item-title{vertical-align:middle}.i-collapse-item-title-wrap{padding:2px 0 0}.i-collapse-item-content{padding:6px;display:none}.i-collapse-item-show-content{display:block}.i-collapse-item-arrow{transition:transform .2s ease-in-out}.i-collapse-item-arrow-show{transition:transform .2s ease-in-out;transform:rotate(90deg)}

+ 31 - 0
component/iView/collapse/index.js

@@ -0,0 +1,31 @@
+Component({
+    externalClasses: ['i-class'],
+
+    relations: {
+        '../collapse-item/index': {
+            type: 'child'
+        }
+    },
+    properties: {
+        name: String,
+        accordion: Boolean
+    },
+    methods: {
+        clickfn(e) {
+            const params = e.detail;
+            const allList = this.getRelationNodes('../collapse-item/index');
+            allList.forEach((item) => {
+                if (params.name === item.data.name) {
+                    item.setData({
+                        showContent: 'i-collapse-item-show-content'
+                    });
+                } else {
+                    item.setData({
+                        showContent: ''
+                    });
+                }
+            });
+        },
+    }
+});
+

+ 3 - 0
component/iView/collapse/index.json

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

+ 4 - 0
component/iView/collapse/index.wxml

@@ -0,0 +1,4 @@
+<view class="i-class i-collapse" bindcollapse="clickfn">
+  <slot></slot>
+</view>
+

+ 0 - 0
component/iView/collapse/index.wxss


+ 90 - 0
component/iView/count-down/index.js

@@ -0,0 +1,90 @@
+Component({
+    properties: {
+        target: Number,
+        showDay: Boolean,
+        callback: String,
+        format: Array,
+        clearTimer: Boolean
+    },
+    externalClasses: ['countdown-class'],
+    data: {
+        time: '',
+        resultFormat: [],
+        changeFormat: false
+    },
+    ready() {
+        this.getFormat();
+
+    },
+    methods: {
+        getFormat() {
+            const data = this.data;
+            const len = data.format.length;
+
+            if (!data.showDay) data.resultFormat.push('');
+
+            if (len >= 3) {
+                for (let i = 0; i < len; i++) {
+                    if (data.resultFormat.length >= 4) break;
+                    if (data.format[i]) {
+                        data.resultFormat.push(data.format[i].toString());
+                    }
+                }
+
+                if (data.resultFormat.length >= 4) data.changeFormat = true;
+            }
+
+            this.getLastTime();
+        },
+        init() {
+            const self = this;
+            setTimeout(function () {
+                self.getLastTime.call(self);
+            }, 1000);
+        },
+        getLastTime() {
+            const data = this.data;
+            const gapTime = Math.ceil((data.target - new Date().getTime()) / 1000);
+            let result = '';
+            let time = '00:00:00';
+            let day = '00';
+            const format = data.resultFormat;
+
+            if (gapTime > 0) {
+                day = this.formatNum(parseInt(gapTime / 86400));
+                let lastTime = gapTime % 86400;
+                const hour = this.formatNum(parseInt(lastTime / 3600));
+                lastTime = lastTime % 3600;
+                const minute = this.formatNum(parseInt(lastTime / 60));
+                const second = this.formatNum(lastTime % 60);
+
+                if (data.changeFormat) time = `${hour}${format[1]}${minute}${format[2]}${second}${format[3]}`;
+                else time = `${hour}:${minute}:${second}`;
+
+                if (!data.clearTimer) this.init.call(this);
+            } else {
+                this.endfn();
+            }
+
+            if (data.showDay) {
+                if (data.changeFormat) {
+                    result = `${day}${format[0]} ${time}`;
+                } else {
+                    result = `${day}d ${time}`;
+                }
+            } else {
+                result = time;
+            }
+            this.setData({
+                time: result
+            });
+
+        },
+        formatNum(num) {
+            return num > 9 ? num : `0${num}`;
+        },
+        endfn() {
+            this.triggerEvent('callback', {});
+        }
+    }
+});

+ 4 - 0
component/iView/count-down/index.json

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

+ 4 - 0
component/iView/count-down/index.wxml

@@ -0,0 +1,4 @@
+<span class="countdown-class">
+  {{time}}
+</span>
+

+ 0 - 0
component/iView/count-down/index.wxss


+ 25 - 0
component/iView/divider/index.js

@@ -0,0 +1,25 @@
+Component({
+    externalClasses: ['i-class'],
+    properties: {
+        content: {
+            type: String,
+            value: ''
+        },
+        height : {
+            type: Number,
+            value: 48
+        },
+        color : {
+            type : String,
+            value : '#80848f'
+        },
+        lineColor : {
+            type : String,
+            value : '#e9eaec'
+        },
+        size : {
+            type: String,
+            value: 12
+        }
+    }
+});

+ 3 - 0
component/iView/divider/index.json

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

+ 19 - 0
component/iView/divider/index.wxml

@@ -0,0 +1,19 @@
+<view class="i-divider i-class" style="{{parse.getStyle(color,size,height)}}">
+    <view class="i-divider-content" wx:if="{{content !== ''}}">
+        {{content}}
+    </view>
+    <view class="i-divider-content" wx:else>
+        <slot></slot>
+    </view>
+    <view class="i-divider-line" style="background:{{lineColor}}"></view>
+</view>
+<wxs module="parse">
+    module.exports = {
+        getStyle : function(color,size,height){
+            var color = 'color:' + color +';';
+            var size = 'font-size:' + size + 'px;';
+            var height = 'height:' + height+'px;'      
+            return color + size + height;
+        }
+    }
+</wxs>

+ 1 - 0
component/iView/divider/index.wxss

@@ -0,0 +1 @@
+.i-divider{width:100%;text-align:center;font-size:12px;position:relative;display:flex;align-items:center;justify-content:center}.i-divider-line{position:absolute;left:0;width:100%;height:1rpx;background-color:#f7f7f7;top:50%}.i-divider-content{background:#fff;position:relative;z-index:1;display:inline-block;padding:0 10px}

+ 33 - 0
component/iView/drawer/index.js

@@ -0,0 +1,33 @@
+Component({
+    externalClasses: ['i-class'],
+    properties: {
+        visible: {
+            type: Boolean,
+            value: false
+        },
+
+        mask: {
+            type: Boolean,
+            value: true
+        },
+
+        maskClosable: {
+            type: Boolean,
+            value: true
+        },
+
+        mode: {
+            type: String,
+            value: 'left' // left right
+        }
+    },
+    data: {},
+    methods: {
+        handleMaskClick() {
+            if (!this.data.maskClosable) {
+                return;
+            }
+            this.triggerEvent('close', {});
+        }
+    }
+});

+ 3 - 0
component/iView/drawer/index.json

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

+ 6 - 0
component/iView/drawer/index.wxml

@@ -0,0 +1,6 @@
+<view class="i-class i-drawer {{ visible ? 'i-drawer-show' : '' }} {{ 'i-drawer-' + mode }}">
+    <view wx:if="{{ mask }}" class="i-drawer-mask" bindtap="handleMaskClick"></view>
+    <view class="i-drawer-container">
+        <slot></slot>
+    </view>
+</view>

+ 1 - 0
component/iView/drawer/index.wxss

@@ -0,0 +1 @@
+.i-drawer{visibility:hidden}.i-drawer-show{visibility:visible}.i-drawer-show .i-drawer-mask{display:block;opacity:1}.i-drawer-show .i-drawer-container{opacity:1}.i-drawer-show.i-drawer-left .i-drawer-container,.i-drawer-show.i-drawer-right .i-drawer-container{transform:translate3d(0,-50%,0)}.i-drawer-mask{opacity:0;position:fixed;top:0;left:0;right:0;bottom:0;z-index:6;background:rgba(0,0,0,.6);transition:all .3s ease-in-out}.i-drawer-container{position:fixed;left:50%;top:50%;transform:translate3d(-50%,-50%,0);transform-origin:center;transition:all .3s ease-in-out;z-index:7;opacity:0}.i-drawer-left .i-drawer-container{left:0;top:50%;transform:translate3d(-100%,-50%,0)}.i-drawer-right .i-drawer-container{right:0;top:50%;left:auto;transform:translate3d(100%,-50%,0)}

+ 10 - 0
component/iView/grid-icon/index.js

@@ -0,0 +1,10 @@
+Component({
+    externalClasses: ['i-class'],
+
+    relations: {
+        '../grid-item/index': {
+            type: 'parent'
+        }
+    },
+
+});

+ 3 - 0
component/iView/grid-icon/index.json

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

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä