y595705120 3 years ago
parent
commit
10f95cd35f
82 changed files with 3149 additions and 589 deletions
  1. 109 55
      app.js
  2. 55 9
      app.json
  3. 147 4
      app.wxss
  4. BIN
      assets/card.png
  5. BIN
      assets/cardback.png
  6. BIN
      assets/h1.png
  7. BIN
      assets/img_close.png
  8. BIN
      assets/img_gallery.png
  9. BIN
      assets/img_info.png
  10. BIN
      assets/img_share.png
  11. BIN
      assets/loading.gif
  12. BIN
      assets/nav/1.png
  13. BIN
      assets/nav/2.png
  14. BIN
      assets/nav/3.png
  15. BIN
      assets/nav/4.png
  16. BIN
      assets/nav/n1.png
  17. BIN
      assets/nav/n2.png
  18. BIN
      assets/nav/n3.png
  19. BIN
      assets/tabBar/study-select.png
  20. BIN
      assets/tabBar/study.png
  21. 84 1
      component/iView/card/index.wxss
  22. 0 2
      pages/exam/buy/index.wxml
  23. 0 1
      pages/exam/buy/index.wxss
  24. 67 0
      pages/exam/collection/index.js
  25. 17 0
      pages/exam/collection/index.json
  26. 94 0
      pages/exam/collection/index.wxml
  27. 31 0
      pages/exam/collection/index.wxss
  28. 5 1
      pages/exam/do/index.js
  29. 0 1
      pages/exam/do/index.json
  30. 109 54
      pages/exam/index/index.js
  31. 6 10
      pages/exam/index/index.json
  32. 62 85
      pages/exam/index/index.wxml
  33. 23 19
      pages/exam/index/index.wxss
  34. 0 0
      pages/exam/record/index.js
  35. 0 0
      pages/exam/record/index.json
  36. 0 0
      pages/exam/record/index.wxml
  37. 0 0
      pages/exam/record/index.wxss
  38. 15 148
      pages/index/index.js
  39. 34 73
      pages/index/index.wxml
  40. 73 61
      pages/index/index.wxss
  41. 1 1
      pages/my/collection/index.js
  42. 0 0
      pages/my/collection/index.json
  43. 2 0
      pages/my/collection/index.wxml
  44. 1 0
      pages/my/collection/index.wxss
  45. 50 29
      pages/my/index/index.js
  46. 23 16
      pages/my/index/index.wxml
  47. 10 17
      pages/my/index/index.wxss
  48. 159 0
      pages/study/course/index.js
  49. 17 0
      pages/study/course/index.json
  50. 58 0
      pages/study/course/index.wxml
  51. 5 0
      pages/study/course/index.wxss
  52. 141 0
      pages/study/exam/index.js
  53. 16 0
      pages/study/exam/index.json
  54. 96 0
      pages/study/exam/index.wxml
  55. 62 0
      pages/study/exam/index.wxss
  56. 115 0
      pages/study/index/index.js
  57. 16 0
      pages/study/index/index.json
  58. 81 0
      pages/study/index/index.wxml
  59. 145 0
      pages/study/index/index.wxss
  60. 127 0
      pages/study/market/index.js
  61. 16 0
      pages/study/market/index.json
  62. 58 0
      pages/study/market/index.wxml
  63. 143 0
      pages/study/market/index.wxss
  64. 0 0
      pages/study/play/index.js
  65. 0 0
      pages/study/play/index.json
  66. 0 0
      pages/study/play/index.wxml
  67. 0 0
      pages/study/play/index.wxss
  68. 65 0
      pages/study/sign/index.js
  69. 10 0
      pages/study/sign/index.json
  70. 33 0
      pages/study/sign/index.wxml
  71. 1 0
      pages/study/sign/index.wxss
  72. 104 0
      pages/train/index/index.js
  73. 16 0
      pages/train/index/index.json
  74. 81 0
      pages/train/index/index.wxml
  75. 145 0
      pages/train/index/index.wxss
  76. 160 0
      pages/user/identify/index.js
  77. 7 0
      pages/user/identify/index.json
  78. 62 0
      pages/user/identify/index.wxml
  79. 65 0
      pages/user/identify/index.wxss
  80. 110 2
      utils/util.js
  81. 8 0
      wxs/exam-fun.wxs
  82. 9 0
      wxs/util-fun.wxs

+ 109 - 55
app.js

@@ -1,18 +1,18 @@
-const {  $Message} = require('/component/iView/base/index');
+const { $Message} = require('/component/iView/base/index');
 const md5 = require('./utils/md5.js');
-const secret= "117c0743819088468e590246464cc75e"
+const secret = "117c0743819088468e590246464cc75e"
+const {baseUrl} = require("./utils/util.js")
 
 App({
   globalData: {
-    baseAPI: "https://edu.ndjsxh.cn:8443/weixin/",
-    // baseAPI:"http://localhost:8000/weixin/",
     pageSize: 10,
     userInfo: {},
+    studyInfo: {},
   },
-  onLaunch: function() {
+  onLaunch: function () {
     this.autoUpgrade()
   },
-  autoUpgrade: function(){
+  autoUpgrade: function () {
     if (wx.canIUse('getUpdateManager')) {
       const updateManager = wx.getUpdateManager()
       updateManager.onCheckForUpdate(function (res) {
@@ -42,70 +42,90 @@ App({
       })
     }
   },
-  doLogin: function(cb){
+  gotoLogin: function(){
+    wx.navigateTo({
+      url: `/pages/user/identify/index`,
+    })
+  },
+  checkLogin: function (cb) {
     let _this = this
-    wx.login({
-      success(wxres) {
-        if (wxres.code) {
-          _this.formPost('Auth.wxLogin', {
-            "code": wxres.code
-          }).then(res => {
-            if (res.code == 200) {
-              _this.setUserInfo( res.data )
-              cb && cb( res.data );
-            } else if (res.code == 401) {
-              wx.reLaunch({
-                url: '/pages/user/register/index',
-              });
-            } else {
-              _this.message(res.message, 'error')
-            }
-          }).catch(e => {
-            _this.message(e, 'error')
-          })
-        } else {
-          _this.message(res.errMsg, 'error')
-        }
+    let openid = wx.getStorageSync('@openid');
+    if( !openid ) {
+      cb&&cb({})
+      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) {
+  message: function (content, type="info") {
     $Message({
       content: content,
       type: type
     });
   },
-  reLogin( cb ){
-    this.globalData.userInfo = {};
-    this.checkLogin( cb )
-  },
-  checkLogin: function(cb){
-    let userInfo = this.globalData.userInfo;
-    if (!userInfo || !userInfo.token) {
-      this.doLogin( cb  )
-    }else{
-      cb&&cb( userInfo )
-    }
-  },
-  formPost: function(action, data) {
+  formPost: function (action, data) {
     let _this = this
-    const token = wx.getStorageSync('token')
-    const user_id = wx.getStorageSync('userId')||""
-		let timestamp = Date.now()
-		action = action.toLowerCase()
-    let signstr=`weixin_${token}_${action}_${timestamp}_${secret}`
-    let signsure = md5.md5( signstr ).toLowerCase()
+    let userInfo = this.globalData.userInfo||{}
+    let user_id = userInfo.uid||0;
+    let token = userInfo.token||'';
+    console.log( userInfo );
+    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) {
+    return new Promise(function (resolve, reject) {
       wx.showNavigationBarLoading();
       wx.request({
-        url: _this.globalData.baseAPI + action,
+        url: `${baseUrl}weixin/${action}`,
+        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.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,
@@ -127,9 +147,43 @@ App({
       })
     })
   },
-  setUserInfo:function(userInfo){
+  getUserInfo: function ( cb ) {
+    let userInfo = this.globalData.userInfo
+    if( userInfo && userInfo.token ){
+      cb && cb( userInfo);
+      return
+    }
+    let openid = wx.getStorageSync('@openid');
+    // let openid="oG3Fi5ait37qL-3edzAkzysH5apU"
+    if( !openid ) {
+      cb && cb({});
+      return
+    }
+    let param = {"openid": openid};
+    this.formPost('Auth.wxLogin', param).then( res =>{
+      if (res.code == 200) {
+        this.setUserInfo(res.data);
+      }
+      cb && cb(res.data||{});
+    })
+  },
+  getStudyInfo: function () {
+    return this.globalData.studyInfo;
+  },
+  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;
-    wx.setStorageSync('token', userInfo.token )
-    wx.setStorageSync('userId', userInfo.userId)
+    wx.setStorageSync('@openid', userInfo.openid)
   }
 })

+ 55 - 9
app.json

@@ -1,22 +1,68 @@
 {
   "pages": [
-    
     "pages/index/index",
+    "pages/study/exam/index",
+    "pages/study/course/index",
     "pages/my/index/index",
+    "pages/study/index/index",
+    
+    "pages/study/sign/index",
+    
+    "pages/study/market/index",
+    
     "pages/exam/index/index",
-    "pages/record/index",
-    "pages/exam/read/index",
-    "pages/exam/do/index",
+    "pages/user/identify/index",
     "pages/user/bind/index",
-    "pages/exam/error/index",
+    "pages/user/register/index",
+    
     "pages/my/message/info/index",
     "pages/my/message/list/index",
-    "pages/my/log/index",
-    "pages/user/register/index",
-    "pages/exam/buy/index",
-    "pages/course/play/index"
+    "pages/exam/read/index",
+    "pages/exam/do/index",
+    "pages/exam/error/index",
+    "pages/exam/record/index",
+    "pages/study/play/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": "八大员在线练习",

+ 147 - 4
app.wxss

@@ -4,7 +4,64 @@
 @import '/component/iView/input/index.wxss';
 
 page {
-  background: #f7f7f7;
+  /* 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 {
@@ -53,13 +110,17 @@ page {
   margin-top:16rpx;
   line-height: 60rpx;
 }
-.p20{ padding: 20rpx;}
-.p10{padding: 10rpx;}
+.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;}
@@ -67,7 +128,89 @@ page {
 .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;}
+.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
+}

BIN
assets/card.png


BIN
assets/cardback.png


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/study-select.png


BIN
assets/tabBar/study.png


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

@@ -1 +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;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}
+.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
+}

+ 0 - 2
pages/exam/buy/index.wxml

@@ -1,2 +0,0 @@
-<!--pages/exam/buy/index.wxml-->
-<text>pages/exam/buy/index.wxml</text>

+ 0 - 1
pages/exam/buy/index.wxss

@@ -1 +0,0 @@
-/* pages/exam/buy/index.wxss */

+ 67 - 0
pages/exam/collection/index.js

@@ -0,0 +1,67 @@
+let app = getApp()
+Page({
+  data: {
+    preList:["A","B","C", "D", "E", "F"],
+    from:0,
+    size:10,
+    item: {},
+    next: false,
+    list: [],
+  },
+  onLoad: function(options) {
+    this.loadData(  true )
+  },
+  loadData( firstAnswer ){
+    let {size,from} = this.data
+    app.formPost('Exam.GetErrorAnswerList', {from,size}).then(res => {
+      if (res.code ==200) {
+        let list = res.data.list||[];
+        list.reverse()
+        if( firstAnswer){
+          let item = list.pop() ||{};
+          this.setData({list, item})
+        }else{
+          this.setData({list})
+        }
+      }
+    })
+  },
+  checkAnswer( e ){
+    let item = this.data.item;
+    if( !item.select ){
+      app.message("还未作答", 'error')
+      return;
+    }
+    let param = {answerId: item.answerId}
+    // 判断是否正确
+    if( item.type == 2){
+      item.correct = item.select.join("") == item.result;
+    }else{
+      item.correct = item.select == item.result;
+    }
+    param.correct = item.correct?1:0
+    // 打开下一题
+    app.formPost('Exam.EditErrorAnswer', param).then(res => {
+      this.setData({item, next:true})
+    }) 
+  },
+  radioChange( e ){
+    let item = this.data.item
+    item.select = +e.detail.value;
+    this.setData({item})
+  },
+  checkboxChange( e ){
+    let item = this.data.item
+    item.select = e.detail.value.sort()
+    this.setData( {item} );
+  },
+  nextAnswer( ){
+    let {list} = this.data;
+    let item = list.pop()||{};
+    delete( item.select )
+    this.setData({item, list, next:false})
+    if( list.length < 1){
+      this.loadData( )
+    }
+  }
+})

+ 17 - 0
pages/exam/collection/index.json

@@ -0,0 +1,17 @@
+{
+  "usingComponents": {
+    "i-panel": "/component/iView/panel/index",
+    "i-cell-group": "/component/iView/cell-group/index",
+    "i-cell": "/component/iView/cell/index",
+    "i-radio-group": "/component/iView/radio-group/index",
+    "i-radio": "/component/iView/radio/index",
+    "i-input": "/component/iView/input/index",
+    "i-action-sheet": "/component/iView/action-sheet/index",
+    "i-modal": "/component/iView/modal/index",
+    "i-message": "/component/iView/message/index",
+    "i-spin": "/component/iView/spin/index",
+    "i-rate": "/component/iView/rate/index"
+  },
+  "enablePullDownRefresh": false,
+  "navigationBarTitleText": "收藏题库"
+}

+ 94 - 0
pages/exam/collection/index.wxml

@@ -0,0 +1,94 @@
+<wxs module="filter" src="../../../wxs/exam-fun.wxs"></wxs>
+
+<view class="exam-page p10" wx:if="{{item&& item.answerId>0}}">
+	<view class="view-wrap-hidden"> </view>
+	<view class="exam-name-title">
+      <h1></h1>
+  </view>
+	<i-panel   i-class="exam-panel-title">   
+		<i-cell-group i-class="exam-cell" >
+			<!-- 单选题 -->
+			<i-cell wx:if="{{item.type==1}}">
+				<view>
+					<rich-text nodes="[单]{{item.title}}" />
+					<radio-group class="radio-answer" bindchange="radioChange" data-index="{{index}}">
+						<label class="radio" wx:for="{{preList}}" wx:for-item="answer" wx:key="anserIndex" 
+						wx:if="{{item['answer'+(index+1)]}}">
+							<view class="radio-answer">
+								<radio color="#2d8cf0" value="{{index+1}}" checked="{{item.select==index+1}}">
+									{{answer}}. {{item['answer'+(index+1)]}}
+								</radio>
+							</view>
+						</label>
+					</radio-group>
+				</view>
+			</i-cell>
+			<!-- 多选题 -->
+			<i-cell wx:if="{{item.type==2}}">
+				<view>
+					<text> [多]{{item.title}} </text>
+					<checkbox-group class="checkbox-answer" style="margin-top:30rpx" bindchange="checkboxChange"  >
+						<label class="checkbox" wx:for="{{preList}}" wx:key="index" wx:for-item="answer" 
+							wx:if="{{item['answer'+(index+1)]}}">
+							<view class="checkbox-answer">
+								<checkbox color="#2d8cf0" value="{{index+1}}" checked="{{filter.isSelect( index+1, item.select)}}">
+									{{answer}}. {{item['answer'+(index+1)]}}
+								</checkbox>
+							</view>
+						</label>
+					</checkbox-group>
+				</view>
+			</i-cell>
+			<!-- 判断 -->
+			<i-cell wx:if="{{item.type==3}}">
+				<view>
+					<rich-text nodes="[判]{{item.title}}" />
+					<radio-group class="radio-answer" bindchange="radioChange" data-index="{{index}}">
+						<label class="radio" wx:for="{{2}}" wx:for-item="answer">
+							<view class="radio-answer">
+								<radio color="#2d8cf0" value="{{index+1}}" checked="{{item.select==index+1}}">
+									{{preList[index]}}. {{item['answer'+(index+1)]}}
+								</radio>
+							</view>
+						</label>
+					</radio-group>
+				</view>
+			</i-cell>
+		</i-cell-group>
+
+		<!-- 答案解答 -->
+		<view class="exam-clear mt20 " wx:if="{{next}}">
+			<view class="exam-extend-item" style="padding-left:0px">
+				结果:
+				<text class="question-answer-right question-answer-result" wx:if="{{item.correct}}">正确
+				</text>
+				<text class="question-answer-error question-answer-result" wx:else>错误</text>
+			</view>
+
+			<view class="exam-extend-item" style="padding-left:0px" wx:if="{{item.star}}">
+				难度:
+				<i-rate value="{{item.star}}" i-class="exam-item-rate" />
+			</view>
+
+			<view class="exam-extend-item" wx:if="{{item.content}}">
+				<rich-text nodes="解析: {{item.content}}" />
+			</view>
+
+			<view class="exam-extend-item">
+				<text wx:if="{{item.type==1}}"> 正确答案: {{preList[item.result-1]}}</text>
+				<text wx:elif="{{item.type==2}}"> 正确答案: {{filter.getMultResult(item.result)}}</text>
+				<text wx:else> 正确答案: {{item.result==1?'正确':'错误'}}</text>
+			</view>
+		</view>
+
+
+		<view class="mt50">
+			<button class="i-btn  i-btn-primary i-btn-square" bindtap='nextAnswer' wx:if="{{next}}">下一题</button>
+			<button class="i-btn  i-btn-primary i-btn-square" bindtap='checkAnswer' wx:else>提交</button>
+		</view>
+	</i-panel>
+</view>
+
+<view wx:else style="text-align:center;margin-top:40rpx">
+	<view class="padding">没有更多错题</view>
+</view>

+ 31 - 0
pages/exam/collection/index.wxss

@@ -0,0 +1,31 @@
+.exam-tab-view {
+  margin-top: 42px;
+}
+
+.xzs-load-more {
+  margin-top: 60px !important;
+}
+
+.exam-page {
+  background: white;
+}
+
+.question-answer-error {
+  background-color: #fef0f0;
+  border-color: #fde2e2;
+  color: #f56c6c;
+}
+
+.question-answer-right {
+  background-color: #f0f9eb;
+  border-color: #e1f3d8;
+  color: #67c23a;
+}
+
+.exam-clear {
+  clear: both;
+  margin-left: 20rpx;
+}
+.exam-extend-item {
+  padding: 4px;
+}

+ 5 - 1
pages/exam/do/index.js

@@ -34,6 +34,10 @@ Page({
         }).sort( (i,j) =>{
           return i.type > j.type?1:-1;
         })
+        wx.setNavigationBarTitle({
+          title: info.title+'-模拟考试'
+        })
+
         _this.setData({
           list: list,
           info: info,
@@ -72,7 +76,7 @@ Page({
       });
     }else{
       wx.reLaunch({
-        url: '/pages/record/index',
+        url: '/pages/exam/record/index',
       });
     }
   },

+ 0 - 1
pages/exam/do/index.json

@@ -14,5 +14,4 @@
     "i-spin": "/component/iView/spin/index"
   },
   "navigationBarTitleText": "在线模拟考试"
-
 }

+ 109 - 54
pages/exam/index/index.js

@@ -1,67 +1,122 @@
-let app = getApp()
+//index.js
+
+const util = require("../../../utils/util")
+
+//获取应用实例
+const app = getApp()
+
 Page({
   data: {
-    preList:["A","B","C", "D", "E", "F"],
-    from:0,
-    size:10,
-    item: {},
-    next: false,
-    list: [],
+    spinShow: false,
+    buyModel:false,
+    code_url:'',
+    info:{},
+    system: "",
+    groups: [],
+    pushPaper: [],
+    timeLimitPaper: [],
+    userInfo:{},
+    taskList: []
   },
-  onLoad: function(options) {
-    this.loadData(  true )
+  onLoad: function(){
+    let that = this
+    wx.getSystemInfo({
+      success: function(res) {
+        that.setData({system: res.system})
+      }
+    })
   },
-  loadData( firstAnswer ){
-    let {size,from} = this.data
-    app.formPost('Exam.GetErrorAnswerList', {from,size}).then(res => {
-      if (res.code ==200) {
-        let list = res.data.list||[];
-        list.reverse()
-        if( firstAnswer){
-          let item = list.pop() ||{};
-          this.setData({list, item})
-        }else{
-          this.setData({list})
-        }
+  onShow: function(){
+    app.getUserInfo( userInfo =>{
+      this.setData({userInfo})
+      // 已经实名认证
+      if( userInfo.identify ){
+        this.indexLoad()
       }
     })
   },
-  checkAnswer( e ){
-    let item = this.data.item;
-    if( !item.select ){
-      app.message("还未作答", 'error')
-      return;
+  onPullDownRefresh() {
+    if (!this.loading) {
+      this.indexLoad( this.stopPullDownRefresh )
     }
-    let param = {answerId: item.answerId}
-    // 判断是否正确
-    if( item.type == 2){
-      item.correct = item.select.join("") == item.result;
-    }else{
-      item.correct = item.select == item.result;
-    }
-    param.correct = item.correct?1:0
-    // 打开下一题
-    app.formPost('Exam.EditErrorAnswer', param).then(res => {
-      this.setData({item, next:true})
-    }) 
   },
-  radioChange( e ){
-    let item = this.data.item
-    item.select = +e.detail.value;
-    this.setData({item})
+  stopPullDownRefresh(){
+    wx.stopPullDownRefresh()
   },
-  checkboxChange( e ){
-    let item = this.data.item
-    item.select = e.detail.value.sort()
-    this.setData( {item} );
+  indexLoad: function( cb ) {
+    let _this = this
+    app.formPost('Exam.index', {}).then(res => {
+      if (res.code === 200) {
+        _this.setData({
+          groups: res.data.groups
+        });
+       cb&&cb() 
+      }
+    })
   },
-  nextAnswer( ){
-    let {list} = this.data;
-    let item = list.pop()||{};
-    delete( item.select )
-    this.setData({item, list, next:false})
-    if( list.length < 1){
-      this.loadData( )
-    }
+  downloadFile: function(){
+    let url = this.data.info.code_url
+    util.downloadFile( url, res=>{
+      this.setData({buyModel:false, code_url:''})
+    } )
+  },
+  gotoHistory: function(){
+    wx.navigateTo({
+      url: '/pages/exam/record/index',
+    })
+  },
+  gotoExam:function( e ){
+    let groupId = e.currentTarget.dataset.id
+    wx.navigateTo({
+      url: `/pages/exam/do/index?id=${groupId}`
+    })
+  },
+  gotoCollection(){
+    wx.navigateTo({
+      url: '/pages/exam/collection/index',
+    })
+  },
+  doWxPay( data ){
+    let that = this
+    wx.requestPayment({
+      timeStamp: data.timeStamp,
+      nonceStr: data.nonceStr,
+      package: data.package, 
+      signType: data.signType,
+      paySign: data.paySign,
+      success: function (event) {
+        wx.showModal({
+          title: '支付成功',
+          showCancel: false,
+          content: '本次共支付费用¥'+(data.fee/100)+'元'+ `\n\n试卷更新可能延迟,请耐心等待`,
+          success(res) {
+            that.indexLoad()
+          }
+        })
+      }
+    })
+  },
+  startWxpay(e){
+    let groupId = +e.currentTarget.dataset.id
+    let system = this.data.system
+    app.formPost('User.PayExam', {groupId, system}).then(res => {
+      if (res.code === 200) {
+        if( res.data.payType=="free" ){
+          this.indexLoad()
+        }else if (res.data.payType=="qrcode"){
+          this.setData({info: res.data, buyModel:true})
+        }else{
+          this.doWxPay( res.data )
+        }
+      }
+    })
+  },
+  onShareAppMessage: function(){
+
+  },
+  gotoError: function(){
+    wx.navigateTo({
+      url: '/pages/exam/error/index',
+    })
   }
 })

+ 6 - 10
pages/exam/index/index.json

@@ -3,17 +3,13 @@
     "i-panel": "/component/iView/panel/index",
     "i-cell-group": "/component/iView/cell-group/index",
     "i-cell": "/component/iView/cell/index",
-    "i-radio-group": "/component/iView/radio-group/index",
-    "i-radio": "/component/iView/radio/index",
-    "i-row": "/component/iView/row/index",
-    "i-col": "/component/iView/col/index",
-    "i-input": "/component/iView/input/index",
-    "i-action-sheet": "/component/iView/action-sheet/index",
-    "i-modal": "/component/iView/modal/index",
+    "i-collapse": "/component/iView/collapse/index",
+    "i-collapse-item": "/component/iView/collapse-item/index",
     "i-message": "/component/iView/message/index",
     "i-spin": "/component/iView/spin/index",
-    "i-rate": "/component/iView/rate/index"
+    "i-icon": "/component/iView/icon/index",
+    "i-badge": "/component/iView/badge/index"
   },
-  "enablePullDownRefresh": false,
-  "navigationBarTitleText": "收藏题库"
+  "enablePullDownRefresh": true,
+  "navigationBarTitleText": "鸿鹄在线练习系统"
 }

+ 62 - 85
pages/exam/index/index.wxml

@@ -1,94 +1,71 @@
-<wxs module="filter" src="../../../wxs/exam-fun.wxs"></wxs>
-
-<view class="exam-page p10" wx:if="{{item&& item.answerId>0}}">
-	<view class="view-wrap-hidden"> </view>
-	<view class="exam-name-title">
-      <h1></h1>
+<wxs module="enumItem" src="../../../wxs/enumItem.wxs"></wxs>
+<view>
+  <view>
+    <swiper indicator-dots="false" autoplay="true" interval="5000" duration="1000">
+      <swiper-item>
+        <image src="/assets/carousel/1.png" class="slide-image" />
+      </swiper-item>
+      <swiper-item>
+        <image src="/assets/carousel/2.png" class="slide-image" />
+      </swiper-item>
+      <swiper-item>
+        <image src="/assets/carousel/3.png" class="slide-image" />
+      </swiper-item>
+    </swiper>
   </view>
-	<i-panel   i-class="exam-panel-title">   
-		<i-cell-group i-class="exam-cell" >
-			<!-- 单选题 -->
-			<i-cell wx:if="{{item.type==1}}">
-				<view>
-					<rich-text nodes="[单]{{item.title}}" />
-					<radio-group class="radio-answer" bindchange="radioChange" data-index="{{index}}">
-						<label class="radio" wx:for="{{preList}}" wx:for-item="answer" wx:key="anserIndex" 
-						wx:if="{{item['answer'+(index+1)]}}">
-							<view class="radio-answer">
-								<radio color="#2d8cf0" value="{{index+1}}" checked="{{item.select==index+1}}">
-									{{answer}}. {{item['answer'+(index+1)]}}
-								</radio>
-							</view>
-						</label>
-					</radio-group>
-				</view>
-			</i-cell>
-			<!-- 多选题 -->
-			<i-cell wx:if="{{item.type==2}}">
-				<view>
-					<text> [多]{{item.title}} </text>
-					<checkbox-group class="checkbox-answer" style="margin-top:30rpx" bindchange="checkboxChange"  >
-						<label class="checkbox" wx:for="{{preList}}" wx:key="index" wx:for-item="answer" 
-							wx:if="{{item['answer'+(index+1)]}}">
-							<view class="checkbox-answer">
-								<checkbox color="#2d8cf0" value="{{index+1}}" checked="{{filter.isSelect( index+1, item.select)}}">
-									{{answer}}. {{item['answer'+(index+1)]}}
-								</checkbox>
-							</view>
-						</label>
-					</checkbox-group>
-				</view>
-			</i-cell>
-			<!-- 判断 -->
-			<i-cell wx:if="{{item.type==3}}">
-				<view>
-					<rich-text nodes="[判]{{item.title}}" />
-					<radio-group class="radio-answer" bindchange="radioChange" data-index="{{index}}">
-						<label class="radio" wx:for="{{2}}" wx:for-item="answer">
-							<view class="radio-answer">
-								<radio color="#2d8cf0" value="{{index+1}}" checked="{{item.select==index+1}}">
-									{{preList[index]}}. {{item['answer'+(index+1)]}}
-								</radio>
-							</view>
-						</label>
-					</radio-group>
-				</view>
-			</i-cell>
-		</i-cell-group>
 
-		<!-- 答案解答 -->
-		<view class="exam-clear mt20 " wx:if="{{next}}">
-			<view class="exam-extend-item" style="padding-left:0px">
-				结果:
-				<text class="question-answer-right question-answer-result" wx:if="{{item.correct}}">正确
-				</text>
-				<text class="question-answer-error question-answer-result" wx:else>错误</text>
-			</view>
+  <view wx:if="{{!userInfo.identify}}" >
+    <view style="text-align:center;margin:50rpx"> 
+      <text> 您未开通在线练习业务 </text>
+    </view>
+    <view style="text-align:center;margin:50rpx"> 
+      <text> 实名认证后,可获得试卷 </text>
+    </view>
+  
+    <navigator class="mt50" url="/pages/user/identify/index" hover-class="navigator-hover" open-type="navigate" >
+      <button class="i-btn  i-btn-primary i-btn-square" > 实名认证 </button>
+    </navigator>
+  </view>
 
-			<view class="exam-extend-item" style="padding-left:0px" wx:if="{{item.star}}">
-				难度:
-				<i-rate value="{{item.star}}" i-class="exam-item-rate" />
-			</view>
+  <view wx:else>
+    <view class="cate-section">
+      <button class="cate-item" bindtap="gotoCollection">
+        <i-icon type="collection" size="40" color="#e96900a0" />
+        <text>收藏题库</text>
+      </button>
 
-			<view class="exam-extend-item" wx:if="{{item.content}}">
-				<rich-text nodes="解析: {{item.content}}" />
-			</view>
+      <button class="cate-item" bindtap="gotoError">
+        <i-icon type="flag" size="40" color="#e96900a0" />
+        <text>错题重做</text>
+      </button>
 
-			<view class="exam-extend-item">
-				<text wx:if="{{item.type==1}}"> 正确答案: {{preList[item.result-1]}}</text>
-				<text wx:elif="{{item.type==2}}"> 正确答案: {{filter.getMultResult(item.result)}}</text>
-				<text wx:else> 正确答案: {{item.result==1?'正确':'错误'}}</text>
-			</view>
-		</view>
+      <button class="cate-item" bindtap="gotoHistory">
+        <i-icon type="createtask" size="40" color="#e96900a0" />
+        <text>考试记录</text>
+      </button>
+    </view>
 
+    <i-panel title="练习科目">
+      <view class="cate-section">
+        <view wx:for="{{groups}}" wx:key="groupId" class="cate-item cate-item-3">
+          <button class="cate-item" wx:if="{{item.isBuy}}" bindtap="gotoExam" data-id="{{item.groupId}}">
+            <i-icon type="browse" size="40" color="#7595f1a0" />
+            <text>{{item.title}}</text>
+          </button>
 
-		<view class="mt50">
-			<button class="i-btn  i-btn-primary i-btn-square" bindtap='nextAnswer' wx:if="{{next}}">下一题</button>
-			<button class="i-btn  i-btn-primary i-btn-square" bindtap='checkAnswer' wx:else>提交</button>
-		</view>
-	</i-panel>
-</view>
+          <button class="cate-item" wx:else bindtap="startWxpay" data-id="{{item.groupId}}">
+            <i-icon type="lock" size="40" color="#e96900a0" />
+            <text>{{item.title}}</text>
+          </button>
+        </view>
+      </view>
+    </i-panel>
+  </view>
 
-<view wx:else style="text-align:center;margin-top:40rpx">
-	<view class="padding">没有更多错题</view>
+  <modal title="iOS端暂不支持虚拟支付业务" confirm-text="保存图片" hidden="{{!buyModel}}" no-cancel="true" bindconfirm="downloadFile">
+    <image src="{{info.code_url}}" mode="widthFix" style="width:100%"></image>
+    <view style="color:red;text-align:center;">
+      <text> IOS端暂不支持虚拟支付业务</text>
+    </view>
+  </modal>
 </view>

+ 23 - 19
pages/exam/index/index.wxss

@@ -1,31 +1,35 @@
-.exam-tab-view {
-  margin-top: 42px;
+/**index.wxss**/
+
+.caption-wrap {
+  background-color: white;
+  margin-top: 15px;
 }
 
-.xzs-load-more {
-  margin-top: 60px !important;
+.caption-title {
+  background-color: #f7f7f7;
+  display: block;
+  margin-left: 5px;
 }
 
-.exam-page {
-  background: white;
+.index-collapse {
+  font-size: 14px;
+  line-height: 24px;
 }
 
-.question-answer-error {
-  background-color: #fef0f0;
-  border-color: #fde2e2;
-  color: #f56c6c;
+.index-collapse-item {
+  padding: 8px 15px !important;
+  border: 0px !important;
 }
 
-.question-answer-right {
-  background-color: #f0f9eb;
-  border-color: #e1f3d8;
-  color: #67c23a;
+.slide-image {
+  width: 100%;
+  height: 150px;
 }
 
-.exam-clear {
-  clear: both;
-  margin-left: 20rpx;
+.index-cell {
+  padding: 5px 15px !important;
 }
-.exam-extend-item {
-  padding: 4px;
+
+p{
+  display: none;
 }

+ 0 - 0
pages/record/index.js → pages/exam/record/index.js


+ 0 - 0
pages/record/index.json → pages/exam/record/index.json


+ 0 - 0
pages/record/index.wxml → pages/exam/record/index.wxml


+ 0 - 0
pages/record/index.wxss → pages/exam/record/index.wxss


+ 15 - 148
pages/index/index.js

@@ -4,157 +4,24 @@ const app = getApp()
 
 Page({
   data: {
-    spinShow: false,
-    buyModel:false,
-    code_url:'',
-    info:{},
-    system: "",
-    groups: [],
-    pushPaper: [],
-    timeLimitPaper: [],
-    userInfo:{},
-    taskList: []
-  },
-  onLoad: function(){
-    app.checkLogin( userInfo =>{
-      this.setData({userInfo})
-      this.indexLoad()
+    imgUrls:[
+      "/assets/carousel/1.png",
+      "/assets/carousel/2.png",
+      "/assets/carousel/3.png"
+    ],
+    indicatorDots: false,
+    autoplay: true,
+    interval: 4000,
+    duration: 800,
+  },
+  swiperChange(e) {
+    const that = this;
+    that.setData({
+      swiperIndex: e.detail.current,
     })
-    let that = this
-    wx.getSystemInfo({
-      success: function(res) {
-        that.setData({system: res.system})
-      }
-    })
-  },
-  modalConfirm(){
-    var imgSrc= this.data.code_url;
-    var save = wx.getFileSystemManager();
-    var number = Math.random();
-    let that = this
-    save.writeFile({
-      filePath: wx.env.USER_DATA_PATH + '/pic' + number + '.png',
-      data: imgSrc,
-      encoding: 'base64',
-      success: res => {
-        wx.saveImageToPhotosAlbum({
-          filePath: wx.env.USER_DATA_PATH + '/pic' + number + '.png',
-          success: function (res) {
-            wx.showToast({
-              title: '保存成功',
-            })
-            that.setData({buyModel:false})
-          },
-          fail: function (err) {
-            that.setData({buyModel:false})
-          }
-        })
-      }, fail: err => {
-        that.setData({buyModel:false})
-      }
-    })
-    
-  },
-  onPullDownRefresh() {
-    if (!this.loading) {
-      this.indexLoad( this.stopPullDownRefresh )
-    }
-  },
-  stopPullDownRefresh(){
-    wx.stopPullDownRefresh()
   },
-  showPhone(){
-    wx.showToast({
-      title: "手机"+this.data.userInfo.phone,
-      type:'success',
-      duration:2*1000
-    })
-  },
-  indexLoad: function( cb ) {
-    let _this = this
-    app.formPost('Exam.index', {}).then(res => {
-      if (res.code === 200) {
-        _this.setData({
-          groups: res.data.groups
-        });
-       cb&&cb() 
-      }
-    })
-  },
-  getPhoneNumber (e) {
-    if( e.detail.errMsg =="getPhoneNumber:ok"){
-      let param = {
-        "iv": e.detail.iv,
-        "encryptedData":e.detail.encryptedData,
-      }
-      app.formPost( "User.bindphone", param).then( (res)=>{
-        if( res.code == 200){
-          this.setData( {userInfo: res.data})
-          app.setUserInfo( res.data )
-          this.indexLoad()
-        }
-      })
-    }else{
-      app.message("绑定失败", 'error')
-    }
-  },
-  gotoHistory: function(){
-    wx.navigateTo({
-      url: '/pages/record/index',
-    })
-  },
-  gotoExam:function( e ){
-    let groupId = e.currentTarget.dataset.id
-    wx.navigateTo({
-      url: `/pages/exam/do/index?id=${groupId}`
-    })
-  },
-  gotoCollectin(){
-    wx.navigateTo({
-      url: '/pages/exam/index/index',
-    })
-  },
-  doWxPay( data ){
-    let that = this
-    wx.requestPayment({
-      timeStamp: data.timeStamp,
-      nonceStr: data.nonceStr,
-      package: data.package, 
-      signType: data.signType,
-      paySign: data.paySign,
-      success: function (event) {
-        wx.showModal({
-          title: '支付成功',
-          showCancel: false,
-          content: '本次共支付费用¥'+(data.fee/100)+'元'+ `\n\n试卷更新可能延迟,请耐心等待`,
-          success(res) {
-            that.indexLoad()
-          }
-        })
-      }
-    })
-  },
-  startWxpay(e){
-    let groupId = +e.currentTarget.dataset.id
-    let system = this.data.system
-    app.formPost('User.PayExam', {groupId, system}).then(res => {
-      if (res.code === 200) {
-        if( res.data.payType=="free" ){
-          this.indexLoad()
-        }else if (res.data.payType=="qrcode"){
-          this.setData({info: res.data, buyModel:true})
-        }else{
-          this.doWxPay( res.data )
-        }
-      }
-    })
+  onLoad: function(){
   },
   onShareAppMessage: function(){
-
-  },
-  gotoError: function(){
-    wx.navigateTo({
-      url: '/pages/exam/error/index',
-    })
   }
 })

+ 34 - 73
pages/index/index.wxml

@@ -1,83 +1,44 @@
-<wxs module="enumItem" src="../../wxs/enumItem.wxs"></wxs>
-<view>
-  <view>
-    <swiper indicator-dots="false" autoplay="true" interval="5000" duration="1000">
-      <swiper-item>
-        <image src="/assets/carousel/1.png" class="slide-image" />
-      </swiper-item>
-      <swiper-item>
-        <image src="/assets/carousel/2.png" class="slide-image" />
-      </swiper-item>
-      <swiper-item>
-        <image src="/assets/carousel/3.png" class="slide-image" />
-      </swiper-item>
+<view class="nav-blue">
+
+</view>
+<view class="coursel">
+  <swiper class='indexSwiper' indicator-dots="{{indicatorDots}}" autoplay="{{autoplay}}" interval="{{interval}}"
+    duration="{{duration}}" bindchange="swiperChange" circular='true'>
+    <block wx:for="{{imgUrls}}" wx:key='index'>
       <swiper-item>
-        <image src="/assets/carousel/4.png" class="slide-image" />
+        <image src="{{item}}" class="slide-image" />
       </swiper-item>
-    </swiper>
+    </block>
+  </swiper>
+  <view class="dots">
+    <block wx:for="{{imgUrls}}" wx:key="unique">
+      <view class="dot{{index == swiperCurrent ? ' active' : ''}}"></view>
+    </block>
   </view>
+</view>
 
-  <view class="cate-section">
-    <button class="cate-item" bindtap="gotoCollectin">
-      <i-icon type="collection" size="40" color="#e96900a0" />
-      <text>收藏题库</text>
-    </button>
+<view class="f-header m-t">
+  <image src="/assets/h1.png"></image>
+  <view class="tit-box">
+    <text class="tit">业务选择</text>
+    <text class="tit2">items</text>
+  </view>
+</view>
 
-    <button class="cate-item" bindtap="gotoError">
-      <i-icon type="flag" size="40" color="#e96900a0" />
-      <text>错题重做</text>
-    </button>
-    
-    <button class="cate-item" bindtap="gotoHistory">
-      <i-icon type="createtask" size="40" color="#e96900a0" />
-      <text>考试记录</text>
-    </button>
+<view class="m-t">
 
-    <button wx:if="{{userInfo.phone}}" class="cate-item" bindtap="showPhone">
-      <i-icon type="mine" size="40" color="#e96900a0" />
-      <text>登入</text>
-    </button>
+  <navigator url="/pages/exam/index/index" hover-class="navigator-hover" open-type="switchTab">
+    <image src="/assets/nav/4.png" mode="aspectFill" class="nav-item"></image>    
+  </navigator>
 
-    <button wx:else class="cate-item" bindgetphonenumber="getPhoneNumber" open-type="getPhoneNumber">
-      <image src="/assets/tabBar/my-select.png"></image>
-      <text>绑定手机</text>
-    </button>
-  </view>
+  <navigator url="/pages/train/index/index" hover-class="navigator-hover" open-type="switchTab">
+    <image src="/assets/nav/1.png" mode="aspectFill" class="nav-item"></image>
+  </navigator>
 
-  <i-panel title="题库">
-    <view class="cate-section" >
-      <view wx:for="{{groups}}"  wx:key="groupId" class="cate-item cate-item-3">
-        <button class="cate-item"
-          wx:if="{{item.isBuy}}"
-          bindtap="gotoExam"
-          data-id="{{item.groupId}}" 
-        >
-            <i-icon  type="browse" size="40" color="#7595f1a0" />
-            <text>{{item.title}}</text>
-        </button>
-      
-        <button class="cate-item"
-          wx:else
-          bindtap="startWxpay"
-          data-id="{{item.groupId}}" >
-          <i-icon type="lock" size="40" color="#e96900a0" />
-          <text>{{item.title}}</text>
-        </button>
-      </view>
-    </view>
+  <navigator url="/pages/study/index/index" hover-class="navigator-hover" open-type="switchTab">
+    <image src="/assets/nav/3.png" mode="aspectFill" class="nav-item"></image>
+  </navigator>
 
-    <!-- /pages/exam/do/index?id={{item.groupId}} -->
-  </i-panel>
+</view>
 
-
-  <modal title="iOS端暂不支持虚拟支付业务" 
-    confirm-text="保存图片" 
-    hidden="{{!buyModel}}" 
-    no-cancel="true"
-    bindconfirm="modalConfirm" >
-  <image src="{{info.code_url}}" mode="widthFix" style="width:100%"></image>
-  <view style="color:red;text-align:center;">
-    <text > IOS端暂不支持虚拟支付业务</text>
-  </view>
-</modal>
-</view>
+<view class="cu-tabbar-height"> </view>

+ 73 - 61
pages/index/index.wxss

@@ -1,60 +1,76 @@
-/**index.wxss**/
-
-.caption-wrap {
-  background-color: white;
-  margin-top: 15px;
-}
-
-.caption-title {
-  background-color: #f7f7f7;
-  display: block;
-  margin-left: 5px;
+.slide-image {
+  width: 90%;
+  height: 150px;
+  margin:5%;
 }
-
-.index-collapse {
-  font-size: 14px;
-  line-height: 24px;
+.indexSwiper{
+  width: 100%;
+  height:370rpx;
 }
-
-.index-collapse-item {
-  padding: 8px 15px !important;
-  border: 0px !important;
+.nav-blue{
+  height: 320rpx;
+  background-image: var(--gradualBlue);
 }
-
-.slide-image {
+.coursel{
+  position: relative;
   width: 100%;
-  height: 150px;
+  margin-top:-280rpx;
+  height:370rpx;
 }
-
-.index-cell {
-  padding: 5px 15px !important;
+.dots{ 
+  position: absolute; 
+  left: 0; 
+  right: 0; 
+  bottom: 20rpx; 
+  display: flex; 
+  justify-content: center; 
+} 
+.dots .dot{ 
+  margin: 0 8rpx; 
+  width:15rpx;
+  height:6rpx;
+  background:rgba(255,255,255,1);
+  opacity:0.5;
+  border-radius:1rpx;
+  transition: all .6s; 
+} 
+.dots .dot.active{ 
+  width:24rpx;
+  height:6rpx;
+  background:rgba(255,255,255,1);
+  border-radius:1rpx;
 }
-
-p{
-  display: none;
+ 
+swiper image {
+  width: 100%;
 }
 
-
-.cate-section {
+.f-header {
   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;
+  height: 120rpx;
+  padding: 6rpx 30rpx 8rpx;
   background: #fff;
-  /* 原图标颜色太深,不想改图了,所以加了透明度 */
 }
-.cate-section .cate-item {
+.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;
@@ -64,29 +80,25 @@ p{
     -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);
+.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;
 }
 
-button::after {
-  border: none
+.nav-item{
+  width: 670rpx;
+  margin-left: 40rpx;
+  text-align: center;
+  margin-top: 40rpx;
+  border-radius: 2%;
+  height: 232rpx;
 }
-.cate-item-3{
-  width:33.33%;
-  height:160rpx;
-  margin-top:40rpx
-}

+ 1 - 1
pages/exam/buy/index.js → pages/my/collection/index.js

@@ -1,4 +1,4 @@
-// pages/exam/buy/index.js
+// pages/my/collection/index.js
 Page({
 
   /**

+ 0 - 0
pages/course/play/index.json → pages/my/collection/index.json


+ 2 - 0
pages/my/collection/index.wxml

@@ -0,0 +1,2 @@
+<!--pages/my/collection/index.wxml-->
+<text>pages/my/collection/index.wxml</text>

+ 1 - 0
pages/my/collection/index.wxss

@@ -0,0 +1 @@
+/* pages/my/collection/index.wxss */

+ 50 - 29
pages/my/index/index.js

@@ -1,51 +1,72 @@
+const util = require("../../../utils/util")
+
 const app = getApp()
 Page({
   data: {
     spinShow: false,
     userInfo:{},
-    info: {}
   },
-  onLoad: function(options) {
-    app.checkLogin( this.loadUserInfo )
+  onShow: function () {
+    app.getUserInfo( userInfo =>{
+      this.setData({userInfo})
+    })
   },
-  loadUserInfo( userInfo ) {
-    this.setData( {userInfo} )
+  wxLogin( ){
+    let that = this
+    wx.login({
+      success(wxres) {
+        if( !wxres.code){
+          util.showMsg("登入失败")
+        }else{
+          that.doLoginByCode( wxres.code )
+        }
+      }
+    })
   },
-  userInfoHandler(e){
-    console.log( e.detail.userInfo )
-    let param = {
-      "displayName": e.detail.userInfo.nickName,
-      "avatarUrl":e.detail.userInfo.avatarUrl,
+  getPhoneNumber (e) {
+    if( e.detail.errMsg !="getPhoneNumber:ok"){
+      util.showMsg("获取手机失败")
+      return
     }
-    app.formPost('User.updateInfo', param ).then(res => {
+    let {iv, encryptedData} = e.detail;
+    let that = this
+    wx.login({
+      success(wxres) {
+        that.doGetPhoneNumber( wxres.code, iv, encryptedData )
+      }
+    })
+  },
+  doLoginByCode( code ){
+    app.formPost( "Auth.WxLoginByCode", {code}).then( (res)=>{
       if( res.code == 200){
         this.setData( {userInfo: res.data})
         app.setUserInfo( res.data )
       }
     })
   },
-  getPhoneNumber (e) {
-    this.bindPhone(e)
-  },
-  bindPhone(e){
-    if( e.detail.errMsg =="getPhoneNumber:ok"){
-      let param = {
-        "iv": e.detail.iv,
-        "encryptedData":e.detail.encryptedData,
+  doGetPhoneNumber( code, iv, encryptedData ){
+    let param = {code, iv, encryptedData }
+    app.formPost( "Auth.WxLoginByPhone", param).then( (res)=>{
+      if( res.code == 200){
+        this.setData( {userInfo: res.data})
+        app.setUserInfo( res.data )
       }
-      app.formPost( "User.bindphone", param).then( (res)=>{
-        if( res.code == 200){
-          this.setData( {userInfo: res.data})
-          app.setUserInfo( res.data )
-        }
-      })
-    }else{
-      app.message("绑定失败", 'error')
-    }
+    })
   },
   logOut() {
     wx.setStorageSync('userId', '')
     wx.setStorageSync('token', '')
-    app.reLogin( this.loadUserInfo )
+    wx.setStorageSync('@openid', '')
+    let userInfo = {}
+    this.setData({userInfo})
+    app.setUserInfo( userInfo )
+    wx.navigateTo({
+      url: '/pages/index/index',
+    })
+  },
+  gotoIdentify(){
+    wx.navigateTo({
+      url: '/pages/user/identify/index',
+    })
   }
 })

+ 23 - 16
pages/my/index/index.wxml

@@ -1,32 +1,39 @@
 
 
 <wxs module="filter" src="../../../wxs/exam-fun.wxs"></wxs>
-<view class='userinfo'>
-  <view class='userinfo-avatar'>
-    <open-data type="userAvatarUrl"></open-data>
+
+
+<view class='headImg'>
+  <button  wx:if="{{!userInfo.token}}"  type="primary"  bindtap="wxLogin" class="tc">
+    快捷登入
+  </button>
+
+  <view class="headImg-avatar" wx:else>
+    <image src="{{userInfo.headImg}}" mode="aspectFill"></image>
   </view>
 </view>
 
+
 <view>
   <i-cell-group i-class="my-group-margin">
     <i-cell is-link>
       <i-icon type="mobilephone_fill" slot="icon" size="20" />
-      <button wx:if="{{userInfo.phone}}" class="plain tl">
-        {{filter.phoneFormat(userInfo.phone)}}
+      <button  class="plain tl">
+        {{filter.phoneFormat(userInfo.phone)||"---"}}
       </button>
+    </i-cell>
 
-      <button wx:else open-type="getPhoneNumber" class="plain tl" bindgetphonenumber="getPhoneNumber">
-        绑定手机
+    <i-cell is-link>
+      <i-icon type="editor" slot="icon" size="20" />
+      <button class="plain tl">
+        {{userInfo.nickname ||"---"}}
       </button>
     </i-cell>
 
     <i-cell is-link>
       <i-icon type="editor" slot="icon" size="20" />
-      <button wx:if="{{userInfo.displayName && userInfo.displayName!='微信用户'}}" class="plain tl">
-        {{userInfo.displayName}}
-      </button>
-      <button wx:else open-type="getUserInfo"  class="plain tl" bindgetuserinfo="userInfoHandler"> 
-        保存头像
+      <button class="plain tl">
+        {{filter.cardIdFormat(userInfo.cardId)||"---"}}
       </button>
     </i-cell>
   </i-cell-group>
@@ -34,10 +41,10 @@
 
 <view>
   <i-cell-group i-class="my-group-margin">
-    <i-cell title="设置" is-link url="/pages/dashboard/index">
+    <i-cell title="设置" >
       <i-icon type="setup_fill" slot="icon" size="20" />
     </i-cell>
-    <i-cell title="反馈" is-link url="/pages/dashboard/index">
+    <i-cell title="反馈" >
       <i-icon type="praise_fill" slot="icon" size="20" />
     </i-cell>
     <i-cell title="关于" is-link url="/pages/dashboard/index">
@@ -48,13 +55,13 @@
 
 <view>
   <i-cell-group i-class="my-group-margin">
-    <i-cell title="清理缓存" bind:click="logOut">
+    <i-cell title="退出登入" bind:click="logOut">
       <i-icon type="flashlight_fill" slot="icon" size="20" />
     </i-cell>
   </i-cell-group>
 </view>
 
-<view class="copyright">宁德市建筑工程技术服务行业协会 提供技术支持</view>
+<view class="copyright">宁德市建筑工程技术服务行业协会</view>
 
 <i-spin size="large" fix wx:if="{{ spinShow }}"></i-spin>
 <i-message id="message" />

+ 10 - 17
pages/my/index/index.wxss

@@ -1,28 +1,21 @@
 /**index.wxss**/
-
-.userinfo {
+.headImg {
   display: flex;
   flex-direction: row;
   align-items: center;
-  background: #598ce4;
-  height: 100px;
-}
-
-.userinfo-avatar {
-  width: 48px;
-  height: 48px;
-  margin-left: 30px;
+  text-align: center;
+  background: #ffffff;
+  height: 300rpx;
 }
-
-.userinfo-nickname {
-  color: white;
-  margin-left: 20px;
+.headImg  image{
+  width: 150rpx;
+  height: 150rpx;
+  border-radius: 50%;
+  text-align: center;
+  margin-left: 300rpx;
 }
 
 
-.my-group-margin{
-  margin-top: 10px;
-}
 
 .copyright{
   color: #8c8c8c;

+ 159 - 0
pages/study/course/index.js

@@ -0,0 +1,159 @@
+//index.js
+//获取应用实例
+const app = getApp()
+
+Page({
+  data: {
+    spinShow: false,
+    buyModel:false,
+    code_url:'',
+    system: "",
+    userInfo:{},
+    info:{},
+    onPlay: false,
+    item:{},
+    courseId:0,
+    mediaList: []
+  },
+  onLoad: function( options ){
+    let courseId = +options.courseId||35;
+    this.setData({courseId})
+    app.getSystemInfo( system=>{
+      this.setData({system})
+    })
+    // 
+    app.getUserInfo( userInfo =>{
+      this.setData({userInfo})
+      this.loadData( courseId )
+    })
+  },
+  loadData: function( courseId ) {
+    let param ={ courseId}
+    app.formPost('Study.GetWxCourseInfo', param).then(res => {
+      if( res.code == 200){
+        let {info, list} = res.data
+        wx.setNavigationBarTitle({
+          title: info.name
+        })
+        this.setData({info, mediaList: list})
+      }
+    })
+  },
+  onReady(res) {
+    this.videoContext = wx.createVideoContext('myVideo')
+  },
+  gotoExam(){
+    let courseId = this.data.courseId
+    wx.navigateTo({
+      url: `/pages/study/exam/index?courseId=${courseId}`,
+    })
+  },
+  // 拖动快进
+  timeUpdate( e ){
+    let that = this;
+    let item = this.data.item
+    var position = item.position
+    var currentTime = parseInt(e.detail.currentTime)
+    if( currentTime - position < 1 || item.isFinish ){
+      return
+    }
+    // 
+    if( currentTime - position > 5 ){
+      let videoContext = wx.createVideoContext('myVideo');
+      videoContext.seek( position )
+      wx.showToast({
+        title: '未完整看完该视频,不能快进',
+        icon: 'none',
+        duration: 2000,
+      })
+      return;
+    }else{
+      item.position= currentTime
+    }
+    if( item.position - item.prev_tick > 4 ){
+      item.prev_tick = item.position;
+      // 前一秒完成
+      if( item.prev_tick >= e.detail.duration ){
+        item.isFinish = 1
+      }
+      this.doTick( item )
+    }
+    that.setData({item})
+  },
+  doTick( item ){
+    let param = {
+      id: item.id,
+      isFinish: item.isFinish||0,
+      position: item.position,
+    }
+    let mediaList = this.data.mediaList;
+    app.formPost('study.tick', param).then( res => {
+      if( res.code == 200){
+        item.isFinish = res.data.isFinish
+        if( !res.data.skip ){
+          item.position = res.data.position;
+        }
+        mediaList[item.index] = item;
+        this.setData( {item, mediaList} );
+      }
+    })
+  },
+  playMedia( e ){
+    let index = e.currentTarget.dataset.index;
+    let mediaList =  this.data.mediaList
+    let item = mediaList[index];
+    item.index = index;
+    item.prev_tick = item.position
+    wx.pageScrollTo({
+      scrollTop: 0,
+      duration: 1000
+   })
+
+    if( item.url ){
+      this.setData({onPlay: true, item})
+      return;
+    }
+    app.formPost('study.GetMedia', {id:item.id}).then( res => {
+      if( res.code == 200){
+        item.url = res.data
+        mediaList[index] = item;
+        this.setData({onPlay: true, item, mediaList})
+      }
+    });
+  },
+  doWxPay( data ){
+    let that = this
+    wx.requestPayment({
+      timeStamp: data.timeStamp,
+      nonceStr: data.nonceStr,
+      package: data.package, 
+      signType: data.signType,
+      paySign: data.paySign,
+      success: function (event) {
+        wx.showModal({
+          title: '支付成功',
+          showCancel: false,
+          content: '本次共支付费用¥'+(data.fee/100)+'元'+ `\n\n试卷更新可能延迟,请耐心等待`,
+          success(res) {
+            that.indexLoad()
+          }
+        })
+      }
+    })
+  },
+  startWxpay(e){
+    let groupId = +e.currentTarget.dataset.id
+    let system = this.data.system
+    app.formPost('User.PayExam', {groupId, system}).then(res => {
+      if (res.code === 200) {
+        if( res.data.payType=="free" ){
+          this.indexLoad()
+        }else if (res.data.payType=="qrcode"){
+          this.setData({info: res.data, buyModel:true})
+        }else{
+          this.doWxPay( res.data )
+        }
+      }
+    })
+  }
+})

+ 17 - 0
pages/study/course/index.json

@@ -0,0 +1,17 @@
+{
+  "usingComponents": {
+    "i-panel": "/component/iView/panel/index",
+    "i-cell-group": "/component/iView/cell-group/index",
+    "i-cell": "/component/iView/cell/index",
+    "i-collapse": "/component/iView/collapse/index",
+    "i-collapse-item": "/component/iView/collapse-item/index",
+    "i-message": "/component/iView/message/index",
+    "i-spin": "/component/iView/spin/index",
+    "i-icon": "/component/iView/icon/index",
+    "i-card": "/component/iView/card/index",
+    "i-avatar": "/component/iView/avatar/index",
+    "i-badge": "/component/iView/badge/index"
+  },
+  "enablePullDownRefresh": true,
+  "navigationBarTitleText": "鸿鹄在线练习系统"
+}

+ 58 - 0
pages/study/course/index.wxml

@@ -0,0 +1,58 @@
+<wxs module="util" src="../../../wxs/util-fun.wxs"></wxs>
+<view>
+  <view>
+    <video id="myVideo" src="{{item.url}}" autoplay initial-time="{{item.position}}" show-fullscreen-btn
+      bindtimeupdate="timeUpdate" show-play-btn="false" show-screen-lock-button="true" object-fit="cover"
+      wx:if="{{onPlay}}"></video>
+    <image src="{{info.tb}}" mode="widthFix" style="width:100%;" wx:else />
+  </view>
+
+  <!-- <view class="tc p20 fs30">
+    <text>学时: {{info.getXs/10}}/{{info.totalXs/10}}</text>
+    <text style="margin-left:10rpx">最高分: {{info.score}}</text>
+  </view> -->
+
+  <view class="cate-section">
+
+    <view class="cate-item">
+      <i-avatar  size="40" color="#e96900a0"> {{info.getXs/10}} </i-avatar>
+      <text class="pt20">获得学时</text>
+    </view>
+
+    <view class="cate-item">
+      <i-avatar size="40" color="#e96900a0"> {{info.totalXs/10}} </i-avatar>
+      <text class="pt20">总学时</text>
+    </view>
+
+    <view class="cate-item">
+      <i-avatar  size="40" color="#e96900a0"> {{info.score}} </i-avatar>
+      <text class="pt20">最高分</text>
+    </view>
+
+    <view class="cate-item" bindtap="gotoExam">
+      <i-avatar  size="40" color="#e96900a0"> {{info.score>60?'是':'否'}} </i-avatar>
+      <text class="pt20">进入考试</text>
+    </view>
+  </view>
+
+
+
+
+  <view wx:for="{{mediaList}}" wx:for-item="item" wx:for-index="index" wx:key="index" class="mt20">
+    <i-card title="{{item.name}}" bindtap="playMedia" data-index="{{index}}">
+      <view slot="content">视频学时: {{item.xs/10}}</view>
+      <view slot="footer">
+        学习进度:{{util.getPercent(item) }}%
+      </view>
+
+    </i-card>
+  </view>
+
+
+  <modal title="iOS端暂不支持虚拟支付业务" confirm-text="保存图片" hidden="{{!buyModel}}" no-cancel="true" bindconfirm="modalConfirm">
+    <image src="{{info.code_url}}" mode="widthFix" style="width:100%"></image>
+    <view style="color:red;text-align:center;">
+      <text> IOS端暂不支持虚拟支付业务</text>
+    </view>
+  </modal>
+</view>

+ 5 - 0
pages/study/course/index.wxss

@@ -0,0 +1,5 @@
+/**index.wxss**/
+
+#myVideo {
+  width: 100%;
+}

+ 141 - 0
pages/study/exam/index.js

@@ -0,0 +1,141 @@
+import {formatSeconds} from '../../../utils/util.js'
+let app = getApp()
+Page({
+  data: {
+    preList:["A","B","C", "D", "E", "F"],
+    userInfo: {},
+    modalShow: false,
+    timeOutShow: false,
+    remainTime: 0,
+    remainTimeStr: '',
+    index:0,
+    score:0,
+    useTime:0,
+    item: {},
+    info: {},
+    list: [],
+  },
+  onLoad: function(options) {
+    let courseId = +options.courseId||36
+    app.getUserInfo( userInfo =>{
+      this.setData({userInfo})
+      this.loadData( courseId )
+    })
+  },
+  loadData( courseId ){
+    let info = wx.getStorageSync('@examinfo')||{};
+    if( info && info.courseId == courseId){      
+      let index = info.index||0;
+      this.setData({info})
+      this.loadQuestion( index )
+      this.timeReduce()
+      return;
+    }
+    app.formPost('Course.startExam', {courseId}).then(res => {
+      if (res.code ==200) {
+        this.setData({info:res.data })
+        this.loadQuestion( 0 )
+        this.timeReduce()
+      }
+    })
+  },
+  selectquestion( e ){
+    let index = e.currentTarget.dataset.index
+    this.loadQuestion( index )
+  },
+  checkAnswer( e ){
+    let item = this.data.item;
+    let examId = this.data.index.examId;
+    if( !item.select ){
+      util.message("还未作答", 'error')
+      return;
+    }
+    let select = item.select;
+    if( item.type == 3) select = +select.join("");
+    let param = {id: item.id, examId, select}
+    app.formPost('Course.SubmitAnswer', param).then(res => {
+      this.nextAnswer( )
+    })
+  },
+  radioChange( e ){
+    let item = this.data.item
+    item.select = +e.detail.value;
+    console.log( "radioChange", item)
+    this.setData({item})
+    this.checkAnswer()
+  },
+  loadQuestion( index ) {
+    let item = this.data.info.answers[index];
+    item.index = index;
+    if( !item.title ){
+      app.formPost("course.loadAnswer", {id:item.id} ).then(res => {
+        if( res.code != 200) return;
+        Object.assign( item, res.data)
+        this.saveItem( item ) 
+      })
+    }else{
+      this.saveItem( item ) 
+    }
+  },
+  saveItem( item ){
+    let info = this.data.info;
+    info.index = item.index;
+    info.answers[ item.index] = item;
+    wx.setStorageSync('@examinfo', info)
+    console.log("item", item)
+    this.setData({item, info})
+  },
+  checkboxChange( e ){
+    let item = this.data.item
+    item.select = e.detail.value.sort()
+    console.log( "radioChange", item)
+    this.setData({item})
+  },
+  nextAnswer(  ){
+    console.log( "next")
+    this.loadQuestion( this.data.info.index+1)
+  },
+  returnRecord(){
+    wx.navigateBack({
+      delta: 1,
+    })
+  },
+  dosubmit(e){
+    let examId = this.data.info.examId
+    app.formPost("course.FinishExam", {examId}).then(res => {
+      if (res.code == 200) {
+        let { score, useTime } = res.data;
+        this.setData({score, useTime, modalShow:true})
+        wx.setStorageSync('@examinfo', {})
+        if( this.data.timer) clearInterval(this.data.timer)
+      }
+    });
+  },
+  timeOut() {
+    clearInterval(this.data.timer)
+    this.setData({
+      timeOutShow: true
+    });
+  },
+
+  timeReduce() {
+    let _this = this
+    let  remainTime = this.data.info.duration + this.data.info.startTime - parseInt(Date.now()/1000)
+    this.setData({remainTime})
+    let timer = setInterval(function() {
+      let remainTime = _this.data.remainTime
+      if (remainTime <= 0) {
+        _this.timeOut()
+      } else {
+        _this.setData({
+          remainTime: remainTime - 1,
+          remainTimeStr: formatSeconds(remainTime),
+          doTime: _this.data.doTime + 1
+        });
+      }
+    }, 1000)
+    _this.setData({
+      timer: timer
+    });
+  }
+})

+ 16 - 0
pages/study/exam/index.json

@@ -0,0 +1,16 @@
+{
+  "usingComponents": {
+    "i-panel": "/component/iView/panel/index",
+    "i-cell-group": "/component/iView/cell-group/index",
+    "i-cell": "/component/iView/cell/index",
+    "i-radio-group": "/component/iView/radio-group/index",
+    "i-radio": "/component/iView/radio/index",
+    "i-input": "/component/iView/input/index",
+    "i-action-sheet": "/component/iView/action-sheet/index",
+    "i-modal": "/component/iView/modal/index",
+    "i-col": "/component/iView/col/index",
+    "i-row": "/component/iView/row/index"
+  },
+  "enablePullDownRefresh": false,
+  "navigationBarTitleText": "考试"
+}

+ 96 - 0
pages/study/exam/index.wxml

@@ -0,0 +1,96 @@
+<wxs module="filter" src="../../../wxs/exam-fun.wxs"></wxs>
+
+<view class="exam-page p10">
+
+	<view class="view-wrap">
+    <view class="exam-count-down">{{remainTimeStr}}</view>
+	</view>
+	<view class="view-wrap-hidden">
+	</view>
+	
+
+	<i-panel i-class="exam-panel-title">
+		<i-cell-group i-class="exam-cell">
+			<!-- 单选题 -->
+			<i-cell wx:if="{{item.type==2}}">
+				<view>
+					<rich-text nodes="[单]{{item.title}}" />
+					<radio-group class="radio-answer" bindchange="radioChange" data-index="{{index}}">
+						<label class="radio" wx:for="{{preList}}" wx:for-item="answer" wx:key="anserIndex"
+							wx:if="{{item['answer'+(index+1)]}}">
+							<view class="radio-answer">
+								<radio color="#2d8cf0" value="{{index+1}}" checked="{{item.select==index+1}}">
+									{{answer}}. {{item['answer'+(index+1)]}}
+								</radio>
+							</view>
+						</label>
+					</radio-group>
+				</view>
+			</i-cell>
+			<!-- 多选题 -->
+			<i-cell wx:if="{{item.type==3}}">
+				<view>
+					<text> [多]{{item.title}} </text>
+					<checkbox-group class="checkbox-answer" style="margin-top:30rpx" bindchange="checkboxChange">
+						<label class="checkbox" wx:for="{{preList}}" wx:key="index" wx:for-item="answer"
+							wx:if="{{item['answer'+(index+1)]}}">
+							<view class="checkbox-answer">
+								<checkbox color="#2d8cf0" value="{{index+1}}" checked="{{filter.isSelect( index+1, item.select)}}">
+									{{answer}}. {{item['answer'+(index+1)]}}
+								</checkbox>
+							</view>
+						</label>
+					</checkbox-group>
+				</view>
+			</i-cell>
+			<!-- 判断 -->
+			<i-cell wx:if="{{item.type==1}}">
+				<view>
+					<rich-text nodes="[判]{{item.title}}" />
+					<radio-group class="radio-answer" bindchange="radioChange" data-index="{{index}}">
+						<label class="radio" wx:for="{{2}}" wx:for-item="answer">
+							<view class="radio-answer">
+								<radio color="#2d8cf0" value="{{index+1}}" checked="{{item.select==index+1}}">
+									{{preList[index]}}. {{item['answer'+(index+1)]}}
+								</radio>
+							</view>
+						</label>
+					</radio-group>
+				</view>
+			</i-cell>
+		</i-cell-group>
+
+		<view class="tc">
+			<button  type="primary" size="mini" bindtap='nextAnswer'>下一题</button>
+			<button  type="primary" size="mini" bindtap='dosubmit' class="ml20">交卷</button>
+		</view>
+	</i-panel>
+</view>
+
+<view class="bg-white">
+	<i-row >
+		<i-col span="4" wx:for="{{30}}" i-class="col-class">
+			<view class="item-select {{info.answers[index].select>0?'is-select':''}}" bindtap="selectquestion" data-index="{{index}}" > {{index+1}} </view>
+		</i-col>
+
+		<i-col span="4" wx:for="{{10}}" i-class="col-class" >
+			<view class="item-select {{info.answers[index+30].select>0?'is-select':''}}" bindtap="selectquestion" data-index="{{index+30}}"> {{index+31}} </view>
+		</i-col>
+
+		<i-col span="4" wx:for="{{10}}" i-class="col-class" >
+			<view class="item-select {{info.answers[index+40].select>0?'is-select':''}}" bindtap="selectquestion" data-index="{{index+40}}"> {{index+41}} </view>
+		</i-col>
+	</i-row>
+</view>
+
+
+<i-modal title="考试结果" visible="{{modalShow}}" bind:ok="returnRecord" bind:cancel="returnRecord">
+	<view>我的战绩:{{score}} </view>
+</i-modal>
+
+<i-action-sheet visible="true" visible="{{timeOutShow}}" mask-closable="{{ false }}">
+	<view slot="header" style="padding: 16px">
+		<view class="exam-timeout-title">考试试卷结束,请提交试卷!</view>
+		<button class="i-btn  i-btn-primary i-btn-square"  bindtap='dosubmit'>提交</button>
+	</view>
+</i-action-sheet>

+ 62 - 0
pages/study/exam/index.wxss

@@ -0,0 +1,62 @@
+.exam-tab-view {
+  margin-top: 42px;
+}
+
+.view-wrap {
+  position: fixed;
+  width: 100%;
+  background: #fff6f6;
+  text-align: center;
+  height: 35px;
+  z-index: 999;
+}
+
+.exam-count-down {
+  font-size: 15px;
+  line-height: 35px;
+}
+
+.view-wrap-hidden {
+  height: 35px;
+}
+
+
+.xzs-load-more {
+  margin-top: 60px !important;
+}
+
+.exam-page {
+  background: white;
+}
+
+.question-answer-error {
+  background-color: #fef0f0;
+  border-color: #fde2e2;
+  color: #f56c6c;
+}
+
+.question-answer-right {
+  background-color: #f0f9eb;
+  border-color: #e1f3d8;
+  color: #67c23a;
+}
+
+.exam-clear {
+  clear: both;
+  margin-left: 20rpx;
+}
+.exam-extend-item {
+  padding: 4px;
+}
+
+.item-select{
+  padding: 10rpx !important;
+  margin: 20rpx;
+  margin-top: 10rpx;
+  text-align: center;
+  height: 40rpx;
+}
+.is-select{
+  background: #dadada;
+  margin: 0rpx;
+}

+ 115 - 0
pages/study/index/index.js

@@ -0,0 +1,115 @@
+const app = getApp()
+Page({
+  data: {
+    spinShow: false,
+    buyModel:false,
+    code_url:'',
+    info:{},
+    system: "",
+    groups: [],
+    pushPaper: [],
+    timeLimitPaper: [],
+    userInfo:{},
+    from:0,
+    size: 10,
+    courseList: []
+  },
+  onLoad: function(){
+    let that = this
+    wx.getSystemInfo({
+      success: function(res) {
+        that.setData({system: res.system})
+      }
+    })
+  },
+  gotoCourse( e ){
+    let courseId = e.currentTarget.dataset.id;
+    wx.navigateTo({
+      url: `/pages/study/course/index?courseId=${courseId}`,
+    })
+  },
+  onShow: function () {
+    app.getUserInfo( userInfo =>{
+      this.setData({userInfo})
+      this.indexLoad()
+    })
+  },
+  onPullDownRefresh() {
+    if (!this.loading) {
+      this.indexLoad( this.stopPullDownRefresh )
+    }
+  },
+  stopPullDownRefresh(){
+    wx.stopPullDownRefresh()
+  },
+  indexLoad: function( cb ) {
+    let param ={ 
+      from: this.data.from,
+      size: this.data.size,
+      type:'施工现场专业人员',
+    }
+    app.formPost('Study.GetWxCourseList', param).then(res => {
+      if (res.code === 200) {
+        this.setData({
+          from: res.data.from,
+          courseList: res.data.list,
+        });
+       cb&&cb() 
+      }
+    })
+  },
+  gotoExam:function( e ){
+    let groupId = e.currentTarget.dataset.id
+    wx.navigateTo({
+      url: `/pages/exam/do/index?id=${groupId}`
+    })
+  },
+  gotoCollection(){
+    wx.navigateTo({
+      url: '/pages/exam/collection/index',
+    })
+  },
+  doWxPay( data ){
+    let that = this
+    wx.requestPayment({
+      timeStamp: data.timeStamp,
+      nonceStr: data.nonceStr,
+      package: data.package, 
+      signType: data.signType,
+      paySign: data.paySign,
+      success: function (event) {
+        wx.showModal({
+          title: '支付成功',
+          showCancel: false,
+          content: '本次共支付费用¥'+(data.fee/100)+'元'+ `\n\n试卷更新可能延迟,请耐心等待`,
+          success(res) {
+            that.indexLoad()
+          }
+        })
+      }
+    })
+  },
+  startWxpay(e){
+    let groupId = +e.currentTarget.dataset.id
+    let system = this.data.system
+    app.formPost('User.PayExam', {groupId, system}).then(res => {
+      if (res.code === 200) {
+        if( res.data.payType=="free" ){
+          this.indexLoad()
+        }else if (res.data.payType=="qrcode"){
+          this.setData({info: res.data, buyModel:true})
+        }else{
+          this.doWxPay( res.data )
+        }
+      }
+    })
+  },
+  onShareAppMessage: function(){
+
+  },
+  gotoError: function(){
+    wx.navigateTo({
+      url: '/pages/exam/error/index',
+    })
+  }
+})

+ 16 - 0
pages/study/index/index.json

@@ -0,0 +1,16 @@
+{
+  "usingComponents": {
+    "i-panel": "/component/iView/panel/index",
+    "i-cell-group": "/component/iView/cell-group/index",
+    "i-cell": "/component/iView/cell/index",
+    "i-collapse": "/component/iView/collapse/index",
+    "i-collapse-item": "/component/iView/collapse-item/index",
+    "i-message": "/component/iView/message/index",
+    "i-spin": "/component/iView/spin/index",
+    "i-icon": "/component/iView/icon/index",
+    "i-card": "/component/iView/card/index",
+    "i-badge": "/component/iView/badge/index"
+  },
+  "enablePullDownRefresh": true,
+  "navigationBarTitleText": "继续教育"
+}

+ 81 - 0
pages/study/index/index.wxml

@@ -0,0 +1,81 @@
+<wxs module="enumItem" src="../../../wxs/enumItem.wxs"></wxs>
+<view>
+  <view>
+    <swiper indicator-dots="false" autoplay="true" interval="5000" duration="1000">
+      <swiper-item>
+        <image src="/assets/carousel/1.png" class="slide-image" />
+      </swiper-item>
+      <swiper-item>
+        <image src="/assets/carousel/2.png" class="slide-image" />
+      </swiper-item>
+      <swiper-item>
+        <image src="/assets/carousel/3.png" class="slide-image" />
+      </swiper-item>
+      <swiper-item>
+        <image src="/assets/carousel/4.png" class="slide-image" />
+      </swiper-item>
+    </swiper>
+  </view>
+
+  <view wx:if="{{!userInfo.identify}}">
+    <view style="text-align:center;margin:50rpx">
+      <text> 您未开通在线练习业务 </text>
+    </view>
+    <view style="text-align:center;margin:50rpx">
+      <text> 实名认证后,可获得试卷 </text>
+    </view>
+
+    <navigator class="mt50" url="/pages/user/identify/index" hover-class="navigator-hover" open-type="navigate">
+      <button class="i-btn  i-btn-primary i-btn-square"> 实名认证 </button>
+    </navigator>
+  </view>
+
+  <view  wx:else>
+    <!-- 导航 -->
+    <view class="cate-section">
+
+      <navigator class="cate-item"  url="/pages/study/sign/index" >
+        <i-icon type="flag" size="40" color="#e96900a0" />
+        <text>学时证明</text>
+      </navigator>
+
+      <navigator class="cate-item"  url="/pages/study/market/index?type=施工现场专业人员" >
+        <i-icon type="shop_fill" size="40" color="#e96900a0" />
+        <text>所有课程</text>
+      </navigator>
+
+    </view>
+
+    <!-- 视频列表 -->
+    <view class="guess-section">
+      <block wx:for="{{courseList}}" wx:for-item="item" wx:for-index="index" wx:key="index">
+        <view class="guess-item">
+          <view class="image-wrapper item-img">
+            <image src="{{item.tb}}" mode="aspectFill"> </image>
+            <view class="circle" bindtap="gotoCourse" data-id="{{item.courseId}}">
+              <view class="circle_inner_play"></view>
+            </view>
+          </view>
+          <text class="title clamp">
+            【{{item.nd}}】 {{item.name}}
+          </text>
+          <view class="info">
+            <text class="price">
+              价格:{{"¥"+item.fee/100}}
+            </text>
+            <text class="xs">
+              学时:{{item.totalXs/10}}
+            </text>
+          </view>
+        </view>
+      </block>
+    </view>
+  </view>
+
+  <modal title="iOS端暂不支持虚拟支付业务" confirm-text="保存图片" hidden="{{!buyModel}}" no-cancel="true" bindconfirm="modalConfirm">
+    <image src="{{info.code_url}}" mode="widthFix" style="width:100%"></image>
+    <view style="color:red;text-align:center;">
+      <text> IOS端暂不支持虚拟支付业务</text>
+    </view>
+  </modal>
+</view>

+ 145 - 0
pages/study/index/index.wxss

@@ -0,0 +1,145 @@
+/**index.wxss**/
+
+.caption-wrap {
+  background-color: white;
+  margin-top: 15px;
+}
+
+.caption-title {
+  background-color: #f7f7f7;
+  display: block;
+  margin-left: 5px;
+}
+
+.index-collapse {
+  font-size: 14px;
+  line-height: 24px;
+}
+
+.index-collapse-item {
+  padding: 8px 15px !important;
+  border: 0px !important;
+}
+
+.slide-image {
+  width: 100%;
+  height: 150px;
+}
+
+.index-cell {
+  padding: 5px 15px !important;
+}
+
+/* 
+  列表展示 
+*/
+.guess-section {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-flex-wrap: wrap;
+  -ms-flex-wrap: wrap;
+  flex-wrap: wrap;
+  padding: 20rpx; 
+  background: #fff;
+}
+
+.guess-section .guess-item {
+  margin-top: 40rpx;
+  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;
+  width: 48%;
+  border-radius: 80rpx;
+  padding-bottom: 40rpx;
+}
+
+.guess-section .guess-item:nth-child(2n+1) {
+  margin-right: 4%;
+}
+
+.guess-section .image-wrapper {
+  width: 100%;
+  height: 210rpx;
+  border-radius: 3px;
+  overflow: hidden;
+}
+
+.guess-section .image-wrapper image {
+  width: 100%;
+  height: 100%;
+  opacity: 1;
+}
+
+.guess-section .title {
+  font-size: 26rpx;
+  color: #303133;
+  font-weight: 700;
+}
+
+.guess-section .info {
+  padding: 0rpx 20rpx;
+  float: left;
+  margin-left: 0rpx;
+}
+
+.guess-section .info .price {
+  font-size: 26rpx;
+  float: left;
+}
+
+.guess-section .info .xs {
+  font-size: 26rpx;
+  margin-left: 20rpx;
+  float: left;
+}
+
+
+.item-img{
+  height: 388rpx;
+  position: relative;
+}
+
+.circle {
+  border-radius: 50px;
+  height: 50px;
+  position: absolute;
+  width: 50px;
+  z-index: 9998;
+  color: #fff;
+  background: #000;
+  opacity: 0.6;
+  left: 50%;
+  margin-left: -50rpx;
+  text-align: center;
+  margin-top: -160rpx;
+}
+
+.circle_inner_play {
+  content: "";
+  display: block;
+  width: 0;
+  height: 0;
+  border-style: solid;
+  border-width: 10px 0 10px 20px;
+  border-color: transparent transparent transparent #fff;
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  margin: -10px 0 0 -7px;
+}
+
+
+
+
+
+
+
+

+ 127 - 0
pages/study/market/index.js

@@ -0,0 +1,127 @@
+//index.js
+//获取应用实例
+const app = getApp()
+
+Page({
+  data: {
+    spinShow: false,
+    buyModel:false,
+    code_url:'',
+    info:{},
+    system: "",
+    userInfo:{},
+    from:0,
+    size: 10,
+    type: '',
+    courseList: []
+  },
+  onLoad: function( options ){
+    let type= options.type||''
+    this.setData({type})
+    let that = this
+    wx.getSystemInfo({
+      success: function(res) {
+        that.setData({system: res.system})
+      }
+    })
+    wx.setNavigationBarTitle({
+      title: type+'-课程购买'
+    })
+  },
+  gotoCourse( e ){
+    let courseId = e.currentTarget.dataset.id;
+    wx.navigateTo({
+      url: `/pages/study/course/index?courseId=${courseId}`,
+    })
+  },
+  onShow: function () {
+    app.getUserInfo( userInfo =>{
+      this.setData({userInfo})
+      this.indexLoad()
+    })
+  },
+  onPullDownRefresh() {
+    if (!this.loading) {
+      this.setData({from:0, courseList:[]})
+      this.indexLoad( this.stopPullDownRefresh )
+    }
+  },
+  onReachBottom() {
+    if (!this.loading && this.data.from > -1) {
+      this.indexLoad(  )
+    }
+  },
+  stopPullDownRefresh(){
+    wx.stopPullDownRefresh()
+  },
+  indexLoad: function( cb ) {
+    let param ={ 
+      from: this.data.from,
+      size: this.data.size,
+      type: this.data.type,
+    }
+    let courseList = this.data.courseList;
+    app.formPost('Study.getWxCourseMarket', param).then(res => {
+      if (res.code === 200) {
+        if( param.from == 0){
+          courseList = [];
+        }
+        this.setData({
+          from: res.data.from,
+          courseList: courseList.concat(res.data.list),
+        });
+       cb&&cb() 
+      }
+    })
+  },
+  downloadFile: function(){
+    let url = this.data.info.code_url
+    util.downloadFile( url, res=>{
+      this.setData({buyModel:false, code_url:''})
+    } )
+  },
+  doWxPay( data ){
+    let that = this
+    wx.requestPayment({
+      timeStamp: data.timeStamp,
+      nonceStr: data.nonceStr,
+      package: data.package, 
+      signType: data.signType,
+      paySign: data.paySign,
+      success: function (event) {
+        wx.showModal({
+          title: '支付成功',
+          showCancel: false,
+          content: '本次共支付费用¥'+(data.fee/100)+'元'+ `\n\n试卷更新可能延迟,请耐心等待`,
+          success(res) {
+            that.indexLoad()
+          }
+        })
+      }
+    })
+  },
+  startWxpay(e){
+    let courseId = +e.currentTarget.dataset.id
+    let system = this.data.system
+    app.formPost('User.PayCourse', {courseId, system}).then(res => {
+      if (res.code === 200) {
+        if( res.data.payType=="free" ){
+          this.indexLoad()
+        }else if (res.data.payType=="qrcode"){
+          this.setData({info: res.data, buyModel:true})
+        }else{
+          this.doWxPay( res.data )
+        }
+      }
+    })
+  },
+
+  onShareAppMessage: function(){
+
+  },
+  gotoError: function(){
+    wx.navigateTo({
+      url: '/pages/exam/error/index',
+    })
+  }
+})

+ 16 - 0
pages/study/market/index.json

@@ -0,0 +1,16 @@
+{
+  "usingComponents": {
+    "i-panel": "/component/iView/panel/index",
+    "i-cell-group": "/component/iView/cell-group/index",
+    "i-cell": "/component/iView/cell/index",
+    "i-collapse": "/component/iView/collapse/index",
+    "i-collapse-item": "/component/iView/collapse-item/index",
+    "i-message": "/component/iView/message/index",
+    "i-spin": "/component/iView/spin/index",
+    "i-icon": "/component/iView/icon/index",
+    "i-card": "/component/iView/card/index",
+    "i-badge": "/component/iView/badge/index"
+  },
+  "enablePullDownRefresh": true,
+  "navigationBarTitleText": "鸿鹄在线练习系统"
+}

+ 58 - 0
pages/study/market/index.wxml

@@ -0,0 +1,58 @@
+<wxs module="enumItem" src="../../../wxs/enumItem.wxs"></wxs>
+<view>
+  <view wx:if="{{!userInfo.identify}}">
+    <view style="text-align:center;margin:50rpx">
+      <text> 您未开通在线练习业务 </text>
+    </view>
+    <view style="text-align:center;margin:50rpx">
+      <text> 实名认证后,可获得试卷 </text>
+    </view>
+
+    <navigator class="mt50" url="/pages/user/identify/index" hover-class="navigator-hover" open-type="navigate">
+      <button class="i-btn  i-btn-primary i-btn-square"> 实名认证 </button>
+    </navigator>
+  </view>
+
+  <view  wx:else>
+    <!-- 视频列表 -->
+    <view class="guess-section">
+      <block wx:for="{{courseList}}" wx:for-item="item" wx:for-index="index" wx:key="index">
+        <view class="guess-item">
+          <view class="image-wrapper item-img">
+            <image src="{{item.tb}}" mode="aspectFill"> </image>
+            <view class="circle" bindtap="gotoCourse" data-id="{{item.courseId}}" wx:if="{{item.isPay}}">
+              <view class="circle_inner_play"></view>
+            </view>
+
+            <view class="circle" bindtap="startWxpay" data-id="{{item.courseId}}" wx:else>
+              <i-icon type="lock" size="50" color="red" />
+            </view>
+
+          </view>
+          <text class="title clamp">
+            【{{item.nd}}】 {{item.name}}
+          </text>
+          <view class="info">
+            <text class="price">
+              价格:{{"¥"+item.fee/100}}
+            </text>
+            <text class="xs">
+              学时:{{item.totalXs/10}}
+            </text>
+          </view>
+        </view>
+      </block>
+    </view>
+
+    <view wx:if="{{from==-1}}"  class="m20">
+      <view class="padding tc">没有更多了</view>
+    </view>
+  </view>
+    
+  <modal title="iOS端暂不支持虚拟支付业务" confirm-text="保存图片" hidden="{{!buyModel}}" no-cancel="true" bindconfirm="downloadFile">
+    <image src="{{info.code_url}}" mode="widthFix" style="width:100%"></image>
+    <view style="color:red;text-align:center;">
+      <text> IOS端暂不支持虚拟支付业务</text>
+    </view>
+  </modal>
+</view>

+ 143 - 0
pages/study/market/index.wxss

@@ -0,0 +1,143 @@
+/**index.wxss**/
+
+.caption-wrap {
+  background-color: white;
+  margin-top: 15px;
+}
+
+.caption-title {
+  background-color: #f7f7f7;
+  display: block;
+  margin-left: 5px;
+}
+
+.index-collapse {
+  font-size: 14px;
+  line-height: 24px;
+}
+
+.index-collapse-item {
+  padding: 8px 15px !important;
+  border: 0px !important;
+}
+
+.slide-image {
+  width: 100%;
+  height: 150px;
+}
+
+.index-cell {
+  padding: 5px 15px !important;
+}
+
+/* 
+  列表展示 
+*/
+.guess-section {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-flex-wrap: wrap;
+  -ms-flex-wrap: wrap;
+  flex-wrap: wrap;
+  padding: 20rpx; 
+  background: #fff;
+}
+
+.guess-section .guess-item {
+  margin-top: 40rpx;
+  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;
+  width: 48%;
+  border-radius: 80rpx;
+  padding-bottom: 40rpx;
+}
+
+.guess-section .guess-item:nth-child(2n+1) {
+  margin-right: 4%;
+}
+
+.guess-section .image-wrapper {
+  width: 100%;
+  height: 210rpx;
+  border-radius: 3px;
+  overflow: hidden;
+}
+
+.guess-section .image-wrapper image {
+  width: 100%;
+  height: 100%;
+  opacity: 1;
+}
+
+.guess-section .title {
+  font-size: 26rpx;
+  color: #303133;
+  font-weight: 700;
+}
+
+.guess-section .info {
+  padding: 0rpx 20rpx;
+  float: left;
+  margin-left: 0rpx;
+}
+
+.guess-section .info .price {
+  font-size: 26rpx;
+  float: left;
+}
+
+.guess-section .info .xs {
+  font-size: 26rpx;
+  margin-left: 20rpx;
+  float: left;
+}
+
+
+.item-img{
+  height: 388rpx;
+  position: relative;
+}
+
+.circle {
+  border-radius: 50px;
+  height: 50px;
+  position: absolute;
+  width: 50px;
+  z-index: 10;
+  color: #fff;
+  background: #000;
+  opacity: 0.6;
+  left: 50%;
+  margin-left: -50rpx;
+  text-align: center;
+  margin-top: -160rpx;
+}
+
+.circle_inner_play {
+  content: "";
+  display: block;
+  width: 0;
+  height: 0;
+  border-style: solid;
+  border-width: 10px 0 10px 20px;
+  border-color: transparent transparent transparent #fff;
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  margin: -10px 0 0 -7px;
+}
+
+
+
+
+
+

+ 0 - 0
pages/course/play/index.js → pages/study/play/index.js


+ 0 - 0
pages/exam/buy/index.json → pages/study/play/index.json


+ 0 - 0
pages/course/play/index.wxml → pages/study/play/index.wxml


+ 0 - 0
pages/course/play/index.wxss → pages/study/play/index.wxss


+ 65 - 0
pages/study/sign/index.js

@@ -0,0 +1,65 @@
+
+const app = getApp()
+const {ossUrl} = require("../../../utils/util.js")
+Page({
+  data: {
+    userInfo:{},
+    signModel: false,
+    from: 0,
+    size: 20,
+    form:{},
+    list: []
+  },
+  onLoad: function( options ){
+    app.getUserInfo( userInfo =>{
+      this.setData({userInfo})
+      this.loadData( )
+    })
+  },
+  preview( e){
+    let url = e.currentTarget.dataset.url;
+    this.doPreview( url );
+  },
+  doPreview( url ){
+    let nurl = ossUrl+ url.split("#")[1]
+    wx.previewImage({
+      urls: [nurl],
+    })
+  },
+  makeSign( e) {
+    let index = +e.currentTarget.dataset.index;
+    let item = this.data.list[index];
+    item.index = index
+    let form = Object.assign( {}, item)
+    form.temp = item
+    this.setData({form,signModel:true})
+  },
+  cancelPrint(){
+    this.setData({signModel:false});
+  },
+  printCert(e){
+    let param = {
+      id: +this.data.form.id, 
+      rzCode: this.data.form.rzCode
+    }
+    app.formPost('Cert.printCert', param).then(res => {
+      if( res.code == 200){
+        let { url } = res.data;
+        if( url )this.doPreview( url )
+      }
+    })
+  },
+  updateRzcode(e){
+    this.setData({ "form.rzCode": e.detail.detail.value})
+  },
+  loadData: function(  ) {
+    let param ={ from: this.data.from, size: this.data.size }
+    app.formPost('Cert.GetCertList', param).then(res => {
+      if( res.code == 200){
+        let { from, list} = res.data
+        this.setData({from,list})
+      }
+    })
+  }
+
+})

+ 10 - 0
pages/study/sign/index.json

@@ -0,0 +1,10 @@
+{
+  "usingComponents": {
+    "i-icon": "/component/iView/icon/index",
+    "i-card": "/component/iView/card/index",
+    "i-input": "/component/iView/input/index",
+    "i-button": "/component/iView/button/index"
+  },
+  "enablePullDownRefresh": true,
+  "navigationBarTitleText": "学时证明"
+}

+ 33 - 0
pages/study/sign/index.wxml

@@ -0,0 +1,33 @@
+<view>
+
+  <view wx:for="{{list}}" wx:for-item="item" wx:for-index="index" wx:key="index" class="mt20">
+    <i-card title="{{item.name}}" data-index="{{index}}" i-class="pt30">
+      <view slot="content">证书类型: {{item.type}}</view>
+      <view slot="content" class="mt20">课程学时: {{item.totalXs/10}}</view>
+      <view slot="content" class="mt20">学习时间: {{item.startDate}} 到 {{item.endDate}}</view>
+      <view slot="content" class="mt20">
+        证书编号:{{item.rzCode}}
+      </view>
+
+      <view slot="content" class="mt20 flex tc">
+        <i-button inline type="primary" wx:if="{{item.signUrl}}" bindtap="preview" data-url="{{item.signUrl}}">查看证明
+        </i-button>
+        <i-button inline type="primary" wx:else bindtap="makeSign" data-index="{{index}}" >生成证明</i-button>
+      </view>
+    </i-card>
+  </view>
+
+  <view wx:if="{{from==-1}}" class="m20">
+    <view class="padding tc">没有更多了</view>
+  </view>
+</view>
+
+<modal title="打印学时证明"  hidden="{{!signModel}}" 
+  cancel-text="取消" 
+  bindcancel="cancelPrint"
+  confirm-text="生成证明"
+  bindconfirm="printCert" >
+  <i-panel title="">
+   <i-input title="证书编号" value="{{form.rzCode}}" name="rzCode" bind:change="updateRzcode"> </i-input>
+  </i-panel>
+</modal>

+ 1 - 0
pages/study/sign/index.wxss

@@ -0,0 +1 @@
+/* pages/study/sign/index.wxss */

+ 104 - 0
pages/train/index/index.js

@@ -0,0 +1,104 @@
+const app = getApp()
+Page({
+  data: {
+    spinShow: false,
+    buyModel:false,
+    code_url:'',
+    info:{},
+    system: "",
+    groups: [],
+    pushPaper: [],
+    timeLimitPaper: [],
+    userInfo:{},
+    from:0,
+    size: 10,
+    type:'岗前培训',
+    courseList: []
+  },
+  onLoad: function(){
+    let that = this
+    wx.getSystemInfo({
+      success: function(res) {
+        that.setData({system: res.system})
+      }
+    })
+  },
+  gotoCourse( e ){
+    let courseId = e.currentTarget.dataset.id;
+    wx.navigateTo({
+      url: `/pages/study/course/index?courseId=${courseId}`,
+    })
+  },
+  onShow: function () {
+    app.getUserInfo( userInfo =>{
+      this.setData({userInfo})
+      this.indexLoad()
+    })
+  },
+  onPullDownRefresh() {
+    if (!this.loading) {
+      this.indexLoad( this.stopPullDownRefresh )
+    }
+  },
+  stopPullDownRefresh(){
+    wx.stopPullDownRefresh()
+  },
+  indexLoad: function( cb ) {
+    let param ={ 
+      from: this.data.from,
+      size: this.data.size,
+      type:this.data.type,
+    }
+    app.formPost('Study.GetWxCourseList', param).then(res => {
+      if (res.code === 200) {
+        this.setData({
+          from: res.data.from,
+          courseList: res.data.list,
+        });
+       cb&&cb() 
+      }
+    })
+  },
+  gotoExam:function( e ){
+    let groupId = e.currentTarget.dataset.id
+    wx.navigateTo({
+      url: `/pages/exam/do/index?id=${groupId}`
+    })
+  },
+  doWxPay( data ){
+    let that = this
+    wx.requestPayment({
+      timeStamp: data.timeStamp,
+      nonceStr: data.nonceStr,
+      package: data.package, 
+      signType: data.signType,
+      paySign: data.paySign,
+      success: function (event) {
+        wx.showModal({
+          title: '支付成功',
+          showCancel: false,
+          content: '本次共支付费用¥'+(data.fee/100)+'元'+ `\n\n试卷更新可能延迟,请耐心等待`,
+          success(res) {
+            that.indexLoad()
+          }
+        })
+      }
+    })
+  },
+  startWxpay(e){
+    let groupId = +e.currentTarget.dataset.id
+    let system = this.data.system
+    app.formPost('User.PayExam', {groupId, system}).then(res => {
+      if (res.code === 200) {
+        if( res.data.payType=="free" ){
+          this.indexLoad()
+        }else if (res.data.payType=="qrcode"){
+          this.setData({info: res.data, buyModel:true})
+        }else{
+          this.doWxPay( res.data )
+        }
+      }
+    })
+  }
+
+})

+ 16 - 0
pages/train/index/index.json

@@ -0,0 +1,16 @@
+{
+  "usingComponents": {
+    "i-panel": "/component/iView/panel/index",
+    "i-cell-group": "/component/iView/cell-group/index",
+    "i-cell": "/component/iView/cell/index",
+    "i-collapse": "/component/iView/collapse/index",
+    "i-collapse-item": "/component/iView/collapse-item/index",
+    "i-message": "/component/iView/message/index",
+    "i-spin": "/component/iView/spin/index",
+    "i-icon": "/component/iView/icon/index",
+    "i-card": "/component/iView/card/index",
+    "i-badge": "/component/iView/badge/index"
+  },
+  "enablePullDownRefresh": true,
+  "navigationBarTitleText": "岗前培训"
+}

+ 81 - 0
pages/train/index/index.wxml

@@ -0,0 +1,81 @@
+<wxs module="enumItem" src="../../../wxs/enumItem.wxs"></wxs>
+<view>
+  <view>
+    <swiper indicator-dots="false" autoplay="true" interval="5000" duration="1000">
+      <swiper-item>
+        <image src="/assets/carousel/1.png" class="slide-image" />
+      </swiper-item>
+      <swiper-item>
+        <image src="/assets/carousel/2.png" class="slide-image" />
+      </swiper-item>
+      <swiper-item>
+        <image src="/assets/carousel/3.png" class="slide-image" />
+      </swiper-item>
+      <swiper-item>
+        <image src="/assets/carousel/4.png" class="slide-image" />
+      </swiper-item>
+    </swiper>
+  </view>
+
+  <view wx:if="{{!userInfo.identify}}">
+    <view style="text-align:center;margin:50rpx">
+      <text> 您未开通在线练习业务 </text>
+    </view>
+    <view style="text-align:center;margin:50rpx">
+      <text> 实名认证后,可获得试卷 </text>
+    </view>
+
+    <navigator class="mt50" url="/pages/user/identify/index" hover-class="navigator-hover" open-type="navigate">
+      <button class="i-btn  i-btn-primary i-btn-square"> 实名认证 </button>
+    </navigator>
+  </view>
+
+  <view  wx:else>
+    <!-- 导航 -->
+    <view class="cate-section">
+
+      <navigator class="cate-item"  url="/pages/study/sign/index" >
+        <i-icon type="flag" size="40" color="#e96900a0" />
+        <text>学时证明</text>
+      </navigator>
+
+      <navigator class="cate-item"  url="/pages/study/market/index?type=岗前培训" >
+        <i-icon type="shop_fill" size="40" color="#e96900a0" />
+        <text>所有课程</text>
+      </navigator>
+
+    </view>
+
+    <!-- 视频列表 -->
+    <view class="guess-section">
+      <block wx:for="{{courseList}}" wx:for-item="item" wx:for-index="index" wx:key="index">
+        <view class="guess-item">
+          <view class="image-wrapper item-img">
+            <image src="{{item.tb}}" mode="aspectFill"> </image>
+            <view class="circle" bindtap="gotoCourse" data-id="{{item.courseId}}">
+              <view class="circle_inner_play"></view>
+            </view>
+          </view>
+          <text class="title clamp">
+            【{{item.nd}}】 {{item.name}}
+          </text>
+          <view class="info">
+            <text class="price">
+              价格:{{"¥"+item.fee/100}}
+            </text>
+            <text class="xs">
+              学时:{{item.totalXs/10}}
+            </text>
+          </view>
+        </view>
+      </block>
+    </view>
+  </view>
+
+  <modal title="iOS端暂不支持虚拟支付业务" confirm-text="保存图片" hidden="{{!buyModel}}" no-cancel="true" bindconfirm="modalConfirm">
+    <image src="{{info.code_url}}" mode="widthFix" style="width:100%"></image>
+    <view style="color:red;text-align:center;">
+      <text> IOS端暂不支持虚拟支付业务</text>
+    </view>
+  </modal>
+</view>

+ 145 - 0
pages/train/index/index.wxss

@@ -0,0 +1,145 @@
+/**index.wxss**/
+
+.caption-wrap {
+  background-color: white;
+  margin-top: 15px;
+}
+
+.caption-title {
+  background-color: #f7f7f7;
+  display: block;
+  margin-left: 5px;
+}
+
+.index-collapse {
+  font-size: 14px;
+  line-height: 24px;
+}
+
+.index-collapse-item {
+  padding: 8px 15px !important;
+  border: 0px !important;
+}
+
+.slide-image {
+  width: 100%;
+  height: 150px;
+}
+
+.index-cell {
+  padding: 5px 15px !important;
+}
+
+/* 
+  列表展示 
+*/
+.guess-section {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-flex-wrap: wrap;
+  -ms-flex-wrap: wrap;
+  flex-wrap: wrap;
+  padding: 20rpx; 
+  background: #fff;
+}
+
+.guess-section .guess-item {
+  margin-top: 40rpx;
+  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;
+  width: 48%;
+  border-radius: 80rpx;
+  padding-bottom: 40rpx;
+}
+
+.guess-section .guess-item:nth-child(2n+1) {
+  margin-right: 4%;
+}
+
+.guess-section .image-wrapper {
+  width: 100%;
+  height: 210rpx;
+  border-radius: 3px;
+  overflow: hidden;
+}
+
+.guess-section .image-wrapper image {
+  width: 100%;
+  height: 100%;
+  opacity: 1;
+}
+
+.guess-section .title {
+  font-size: 26rpx;
+  color: #303133;
+  font-weight: 700;
+}
+
+.guess-section .info {
+  padding: 0rpx 20rpx;
+  float: left;
+  margin-left: 0rpx;
+}
+
+.guess-section .info .price {
+  font-size: 26rpx;
+  float: left;
+}
+
+.guess-section .info .xs {
+  font-size: 26rpx;
+  margin-left: 20rpx;
+  float: left;
+}
+
+
+.item-img{
+  height: 388rpx;
+  position: relative;
+}
+
+.circle {
+  border-radius: 50px;
+  height: 50px;
+  position: absolute;
+  width: 50px;
+  z-index: 9998;
+  color: #fff;
+  background: #000;
+  opacity: 0.6;
+  left: 50%;
+  margin-left: -50rpx;
+  text-align: center;
+  margin-top: -160rpx;
+}
+
+.circle_inner_play {
+  content: "";
+  display: block;
+  width: 0;
+  height: 0;
+  border-style: solid;
+  border-width: 10px 0 10px 20px;
+  border-color: transparent transparent transparent #fff;
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  margin: -10px 0 0 -7px;
+}
+
+
+
+
+
+
+
+

+ 160 - 0
pages/user/identify/index.js

@@ -0,0 +1,160 @@
+const app = getApp();
+const util = require("../../../utils/util.js")
+Page({
+  data: {
+    ctx: false,
+    hidden: true,
+    showcamara: false,
+    type:'card',
+    phone:'',
+    studyUser :{
+      cardId:"352202198709031536",
+      cardImg:"",
+      nickname:"吕君喜",
+      phone:'18850724428',
+      openid:'',
+      identify:0,
+      session_key:'',
+      cardBackImg:""
+    }
+  },
+  onShow: function () {
+    app.getUserInfo( studyUser =>{
+      this.setData({studyUser})
+    })
+  },
+  wxLogin(){
+    let that = this
+    wx.login({
+      success(wxres) {
+        if( !wxres.code){
+          util.showMsg("登入失败")
+        }else{
+          that.doLoginByCode( wxres.code )
+        }
+      }
+    })
+  },
+  doLoginByCode( code ){
+    app.formPost( "Auth.WxLoginByCode", {code}).then( (res)=>{
+      if( res.code == 200){
+        this.setData( {userInfo: res.data})
+        app.setUserInfo( res.data )
+        wx.navigateBack({
+          delta: 1
+        })
+      }
+    })
+  },
+  doIdentify( e ){
+    let that = this
+    wx.login({
+      success(wxres) {
+        if (wxres.code) {
+          that.doRegister( wxres.code, e.detail.value )
+        }
+      }
+    })
+  },
+  doRegister( code, info ){
+    let param = {
+      code: code,
+      phone:   info.phone,
+      cardId:  info.cardId,
+      nickname: info.nickname,
+    }
+    app.formPost( 'Auth.Register', param).then( res =>{
+      if( res.code == 200 ){
+        let studyUser= res.data
+        app.setUserInfo( studyUser )
+        util.showSuccess("实名认证成功")
+        this.setData({studyUser})
+      }else{
+        util.showMsg( res.msg  )
+      }
+    })
+  },
+  onReady: function (res) {
+    var ctx = wx.createCameraContext('myCamera')
+    this.setData({ ctx: ctx })
+  },
+  previewImage: function (e) {
+    var current = e.target.dataset.src;
+    wx.previewImage({
+      current: current, 
+      urls: [current]
+    })
+  } ,
+  takeCard(){
+    this.setData( {showcamara:true, type:'card'})
+  },
+  takeCardBack(){
+    this.setData( {showcamara:true, type:'cardBack'})
+  },
+  identify( err, {url} ){
+    if( err != 200 || !url ) {
+      util.showMsg("图片上传失败")
+      return
+    }
+    util.showBusy("识别图片中")
+    let info = this.data.info
+    let showcamara= false
+    app.formPost('Auth.wxUploadImg', {url}).then(res => {
+      util.showBusy("上传成功")
+      Object.assign( info, res)
+      this.setData({info,showcamara})
+    })
+  },
+  chooseImg: function () {
+    var that = this
+    wx.chooseImage({
+      count: 1,
+      sizeType: ['compressed'],
+      sourceType: ['album'], 
+      success: function (res) {
+        that.setData( {showcamara:false})
+        util.showSuccess("图片上传中")
+        util.uploadFile( res.tempFilePaths[0], that.identify )
+      },
+      fail:(res)=>{
+        console.log( res)
+        util.showMsg("图片选择失败")
+      }
+    })
+  },
+  takePhoto() {
+    var that = this
+    var ctx = this.data.ctx
+    ctx.takePhoto({
+      quality: 'low',
+      success: (res) => {
+        app.message("图片上传中")
+        that.setData( {showcamara:false})
+        var tempImagePath = res.tempImagePath
+        util.uploadFile( tempImagePath, that.identify )
+      },
+      fail:  (res)=> {
+        app.message("图片上传中", "error")
+      }
+    })
+  },
+  onConfirm( e ){
+    let {phone} = e.detail.value
+    let info = this.data.info
+    let {card_img, card_back_img} = this.data.info
+    if( !card_img ) return util.showMsg( "身份证正面有误");
+    if( !card_back_img ) return util.showMsg( "身份证背面有误");
+    if( !phone || phone.length != 11 ) return util.showMsg( "手机号码有误");
+    util.http( '/maker/identifyMaker', {phone}, (err,res)=>{
+      if( err!= 0 ) return;
+      info.identify = 1
+      app.identifyUser( )
+      this.setData({info})
+    })
+
+  },
+  goBack() {
+    this.setData({showcamara:false})
+  }
+
+})

+ 7 - 0
pages/user/identify/index.json

@@ -0,0 +1,7 @@
+{
+  "usingComponents": {
+    "i-panel": "/component/iView/panel/index",
+    "i-input": "/component/iView/input/index"
+  },
+  "navigationBarTitleText": "实名认证"
+}

+ 62 - 0
pages/user/identify/index.wxml

@@ -0,0 +1,62 @@
+<camera device-position="back" flash="auto" binderror="errorCamara" id="myCamera" wx:if="{{showcamara}}"
+  style="width: 100%; height:100vh;">
+  <cover-view class="mcover-view" style='width: 100%; height:100%; top:45%' wx:if="{{!hidden}}">
+    <cover-image class="dialog-body wh70" style='right:45%' src="/assets/loading.gif" />
+  </cover-view>
+  <cover-view class="mcover-bar" wx:if="{{hidden}}">
+    <cover-view class="mcover-view">
+      <cover-view>
+        <cover-image class="dialog-body circle wh60" src="/assets/img_gallery.png" bindtap="chooseImg" />
+      </cover-view>
+      <cover-view class="dialog-body camara" bindtap="takePhoto">
+        <cover-view class="camara-1"></cover-view>
+      </cover-view>
+
+      <cover-view>
+        <cover-image class="dialog-body circle wh60" src="/assets/img_close.png" bindtap="goBack" />
+      </cover-view>
+    </cover-view>
+  </cover-view>
+</camera>
+
+<scroll-view scroll-y="true" wx:else class="scroll-view">
+  <view class="identify-box" style="heigth:300rpx;">
+    <view class="identify-list">
+      <image wx:if="{{studyUser.cardImg}}" src="{{studyUser.cardImg+'?x-oss-process=image/resize,w_200'}}"
+        bindlongpress="takeCard" data-src="{{info.card_img}}" class="identify-img" bindtap="previewImage" />
+      <image wx:else src="/assets/card.png" class="identify-img" bindtap="takeCard" />
+    </view>
+    <view class="identify-list">
+      <image wx:if="{{studyUser.cardBackImg}}" src="{{studyUser.cardBackImg+'?x-oss-process=image/resize,w_200'}}"
+        data-src="{{studyUser.cardBackImg}}" class="identify-img" bindtap="previewImage" bindlongpress="takeCardBack" />
+      <image wx:else src="/assets/cardback.png" class="identify-img" bindtap="takeCardBack" />
+    </view>
+  </view>
+
+  <view class="p20 ">
+    <view class="info-title">用户信息</view>
+    <i-panel class="m20 p20" wx:if="{{info.identify}}">
+      <i-input value="{{ studyUser.nickname }}" error title="*身份姓名" class="mt20" disable />
+      <i-input value="{{ studyUser.cardId }}" error title="*身份号码" class="mt20" disable />
+      <i-input value="{{ studyUser.phone }}" error title="*联系方式" class="mt20" disable />
+    </i-panel>
+
+    <form wx:else class="p20" bindsubmit="doIdentify">
+      <i-input  value="{{ studyUser.nickname }}" name="nickname"  title="*身份姓名" class="mt20" maxlength="100" />
+      <i-input value="{{ studyUser.cardId }}"  name="cardId" title="*身份号码" class="mt20" maxlength="18"  />
+      <i-input value="{{ studyUser.phone }}"  name="phone" title="*联系方式" class="mt20" type="number" maxlength="11"/>
+
+      <button wx:if="{{!!studyUser.identify}}" class="i-btn  i-btn-square" type="text">已经实名认证</button>
+      <button wx:else class="i-btn  i-btn-primary i-btn-square" form-type="submit">实名认证</button>
+    </form>
+  </view>
+
+  <view class="tc">
+    <view>
+      <text> 已经实名认证的可以快捷登入 </text>
+    </view>
+    <button class="mt20" type="primary"  bindtap="wxLogin"  size="mini">
+      快捷登入
+    </button>
+  </view>
+</scroll-view>

+ 65 - 0
pages/user/identify/index.wxss

@@ -0,0 +1,65 @@
+.identify-box{
+  width:100%;
+  display: flex;
+  padding:0rpx 20rpx 20rpx 20rpx;
+  box-sizing: border-box;
+ }
+
+ .identify-list{
+  float: left;
+  width: 50%;
+  margin-top:30rpx;
+}
+.identify-img{
+  width:350rpx;
+  height:350rpx;
+  padding: 2rpx;
+}
+
+.fs36{ font-size: 36rpx;}
+
+.dialog-body{
+  text-align:center; 
+}
+.mcover-home{
+position: relative;
+flex-direction: row; 
+height: 100%;
+top: 0;
+z-index: 1000;
+display: flex;
+}
+
+.camara-1{
+  width: 50px; 
+  height: 50px; 
+  margin: 5px;
+  background-color: #f70264; 
+  -webkit-border-radius: 50px; 
+  -moz-border-radius:50px;
+  border-radius:50px;
+}
+
+.mcover-bar{
+  position: absolute;
+  bottom: 10px;
+  height: 70px;
+  margin: 0;
+  padding: 0;
+  width: 100%;
+}
+.mcover-view{
+  position: relative;
+  justify-content: space-around;
+  background-color: none;
+  display: flex;
+  z-index: 1001;
+}
+
+.info-title{
+  text-align: left;
+  font-size: 30rpx;
+  letter-spacing: 0.1em;
+  font-weight: 700;
+  line-height: 30rpx;
+}

+ 110 - 2
utils/util.js

@@ -1,3 +1,7 @@
+// const baseUrl = "http://192.168.3.2:8000/"
+const baseUrl = "https://edu.ndjsxh.cn:8443/"
+const ossUrl = "https://sm-sign.oss-cn-shanghai.aliyuncs.com/cert/"
+
 const formatTime = date => {
   const year = date.getFullYear()
   const month = date.getMonth() + 1
@@ -35,7 +39,6 @@ const formatSeconds = theTime => {
   }
   return result
 }
-
 const getMultResult = select=>{
   let prevList = ["", "A","B","C", "D", "E","F"]
   let slist = ''+select
@@ -47,8 +50,113 @@ const getMultResult = select=>{
   return res
 }
 
+var uploadFile = (tempFilePaths, fun) =>{
+  let header={}
+  let murl = `${baseUrl}upload`
+  let version= "1.0"
+  let mtime = parseInt(Date.now() / 1000);
+  // 未登入
+  let sign = "hall_" + version +  mtime;
+  wx.uploadFile({
+    url: `${murl}?t=${mtime}&v=1&s=${sign}`,
+    filePath: tempFilePaths,
+    name: "avatar",
+    header:header,
+    success: function (res) {
+      if( res.statusCode === 200){
+        let { code, data, msg} = JSON.parse(res.data)
+        if( code == 200 ){
+          fun&&fun(code, data)
+        }else{
+          fun&&fun(code, msg)
+        }  
+      }else{
+        fun&&fun(404, "请求异常")
+      }
+    },
+    fail: function (res) {
+      fun&&fun(404, "" );
+    }
+  })
+}
+
+// 显示繁忙提示
+var showBusy = text => wx.showToast({
+  title: text,
+  icon: 'loading',
+  duration: 2000
+})
+
+// 显示成功提示
+var showSuccess = text => wx.showToast({
+  title: text,
+  icon: 'success'
+})
+
+var showMsg = text => wx.showToast({
+title: text,
+image: '/assets/img_close.png',
+duration: 1000,
+mask: true
+})
+
+var showToast = (errCode, okText, text) => {
+if( errCode ==200 ){
+  showSuccess( okText );
+}else{
+  showMsg( text )
+}
+}
+
+// 显示失败提示
+var showModel = (title, content) => {
+  wx.hideToast();
+
+  wx.showModal({
+      title,
+      content: JSON.stringify(content),
+      showCancel: false
+  })
+}
+
+var downloadFile = ( imgSrc, cb )=>{
+  var save = wx.getFileSystemManager();
+  var number = Date.now()
+  save.writeFile({
+    filePath: wx.env.USER_DATA_PATH + '/pic_' + number + '.png',
+    data: imgSrc,
+    encoding: 'base64',
+    success: res => {
+      wx.saveImageToPhotosAlbum({
+        filePath: wx.env.USER_DATA_PATH + '/pic_' + number + '.png',
+        success: function (res) {
+          wx.showToast({
+            title: '保存成功',
+          })
+          cb &&cb( true );
+        },
+        fail: function (err) {
+          cb &&cb( false );
+        }
+      })
+    }, fail: err => {
+      cb &&cb( false );
+    }
+  })
+}
+   
+
 module.exports = {
+  baseUrl,
+  ossUrl,
+  downloadFile,
   formatSeconds: formatSeconds,
   formatTime: formatTime,
-  getMultResult
+  getMultResult,
+  uploadFile,
+  showModel,
+  showSuccess,
+  showToast,
+  showMsg,
+  showBusy
 }

+ 8 - 0
wxs/exam-fun.wxs

@@ -10,6 +10,13 @@ var filter = {
     }
     return value.substring(0, 4) +"****"+ value.substring(7,11)
   },
+  cardIdFormat: function(value) {
+    if( !value ) return "";
+    if( value.length < 18){
+      return '';
+    }
+    return value.substring(0, 4) +"****"+ value.substring(14,18)
+  },
   trueFalseFormatter: function(question) {
     for (var i = 0; i < question.items.length; i++) {
       if (question.items[i].prefix === question.correct) {
@@ -53,5 +60,6 @@ module.exports = {
   isSelect: filter.isSelect,
   phoneFormat: filter.phoneFormat,
   getMultResult:filter.getMultResult,
+  cardIdFormat:filter.cardIdFormat,
   numberToArray: filter.numberToArray,
 }

+ 9 - 0
wxs/util-fun.wxs

@@ -0,0 +1,9 @@
+var filter = {
+  getPercent: function(item){
+    if( item.isFinish) return 100;
+    return parseInt(item.position*10000/item.duration)/100;
+  }
+}
+module.exports = {
+  getPercent: filter.getPercent
+}