Baozhangchao il y a 3 ans
Parent
révision
896ae50727

+ 0
- 6
src/App.vue Voir le fichier

@@ -5,16 +5,10 @@
5 5
 </template>
6 6
 
7 7
 <script>
8
-import { UserLogin } from './util/api'
9 8
 import { mapState } from 'vuex'
10 9
 
11
-import Tabber from './views/Tabber.vue'
12
-
13 10
 export default {
14 11
   name: 'App',
15
-  components: {
16
-    Tabber
17
-  },
18 12
   computed: {
19 13
     ...mapState(['LOADING'])
20 14
   },

+ 28
- 0
src/components/Avatar/index.vue Voir le fichier

@@ -0,0 +1,28 @@
1
+<template>
2
+  <img class="avatar" :src="src" alt="">
3
+</template>
4
+
5
+<script>
6
+
7
+const defaultImg = require('@/assets/userImag/userImag.jpg')
8
+
9
+export default {
10
+  name: 'Avatar',
11
+  props: {
12
+    src: {
13
+      type: String,
14
+      default: defaultImg
15
+    }
16
+  }
17
+}
18
+</script>
19
+
20
+<style lang="less" scoped>
21
+.avatar {
22
+  display: inline-block;
23
+  width: 78px;
24
+  height: 78px;
25
+  border-radius: 50%;
26
+  box-shadow: 0 0 4px 4px rgba(0, 0, 0, 0.16);
27
+}
28
+</style>

+ 2
- 2
src/util/api.js Voir le fichier

@@ -87,7 +87,7 @@ export const getCourseInfof = (id) => request(`/api/wx/course/${id}`, { method:
87 87
  * @returns 
88 88
  * 
89 89
  */
90
-export const getSignInInfof = (id) => request(`/api/wx/sign-in/c54e0d34b35e2b93e1dd45e87724d9bd`, { method: 'get' })
90
+export const getSignInInfo = (id) => request(`/api/wx/sign-in/${id}`, { method: 'get' })
91 91
 
92 92
 
93 93
 
@@ -97,7 +97,7 @@ export const getSignInInfof = (id) => request(`/api/wx/sign-in/c54e0d34b35e2b93e
97 97
  * @returns 
98 98
  * 
99 99
  */
100
-export const getSignIn = (id) => request(`/api/wx/sign-in/c54e0d34b35e2b93e1dd45e87724d9bd`, { method: 'post' })
100
+export const postSignIn = (id) => request(`/api/wx/sign-in/${id}`, { method: 'post' })
101 101
 
102 102
 
103 103
 

+ 0
- 21
src/util/formattingData.js Voir le fichier

@@ -51,24 +51,3 @@ export function parseTime (time, pattern) {
51 51
 }
52 52
 
53 53
 
54
-export function SignInTime (time, pattern) {
55
-  var date = new Date()
56
-  // var year = date.getFullYear()
57
-  // var month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1
58
-  // var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate()
59
-  var hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours()
60
-  var minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()
61
-  var seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()
62
-  let week = date.getDay() // 星期
63
-  let weekArr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
64
-  // 拼接 时间格式处理
65
-  return hours + ':' + minutes + ':' + seconds + ' ' + weekArr[week]
66
-
67
-  //  * 在日期格式中,月份是从0开始的
68
-  //  * 使用三元表达式在小于10的前面加0,以达到格式统一  如 09:11:05
69
-
70
-}
71
-
72
-
73
-
74
-

+ 0
- 10
src/util/query.js Voir le fichier

@@ -1,10 +0,0 @@
1
-// 获取url参数
2
-export default function getUrlKey (name) {
3
-  return (
4
-    decodeURIComponent(
5
-      (new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(
6
-        location.href
7
-      ) || [, ''])[1].replace(/\+/g, '%20')
8
-    ) || null
9
-  )
10
-}

+ 1
- 1
src/views/ClassInfo.vue Voir le fichier

@@ -31,7 +31,7 @@
31 31
 
32 32
 <script>
33 33
 import { getCourseInfof, addCollection, deleteCollection } from '@/util/api'
34
-import { parseTime, SignInTime } from '@/util/formattingData'
34
+import { parseTime } from '@/util/formattingData'
35 35
 
36 36
 export default {
37 37
   components: {

+ 5
- 60
src/views/Course.vue Voir le fichier

@@ -1,25 +1,7 @@
1 1
 <template>
2 2
   <div class="Course-box">
3
-    <div class="banner-box-top mglr-10">
4
-      <van-swipe
5
-        class="banner-swipe"
6
-        :autoplay="3000"
7
-        @change="i => currentItem = i"
8
-        :show-indicators="false"
9
-      >
10
-        <van-swipe-item v-for="(image, index) in HomeBannerImages" :key="index">
11
-          <ration-div :ratio="0.6">
12
-            <van-image width="100%" height="100%" :src="image.thumb" />
13
-          </ration-div>
14
-        </van-swipe-item>
15
-      </van-swipe>
16
-      <div class="custom-indicator">
17
-        <span
18
-          v-for="(_, index) in HomeBannerImages"
19
-          :key="index"
20
-          :class="{'active': currentItem === index }"
21
-        ></span>
22
-      </div>
3
+    <div class="banner-box-top">
4
+      <banner-swipe :list="HomeBannerImages" />
23 5
     </div>
24 6
 
25 7
     <!-- list -->
@@ -46,13 +28,12 @@ import { getBanner, getCourse } from '@/util/api'
46 28
 
47 29
 export default {
48 30
   components: {
49
-    RationDiv: () => import('@/components/RatioDiv/index.vue'),
31
+    BannerSwipe: () => import('./components/BannerSwipe.vue'),
50 32
     CourseCard: () => import('./components/CourseCard.vue')
51 33
   },
52 34
 
53 35
   data() {
54 36
     return {
55
-      currentItem: -1,
56 37
       icon: require('@/assets/icon/courseIcon.svg'),
57 38
       loading: false,
58 39
       finished: true,
@@ -84,38 +65,12 @@ export default {
84 65
     },
85 66
     onBanner() {
86 67
       getBanner('Training').then((e) => {
87
-        this.HomeBannerImages = e.records
68
+        this.HomeBannerImages = (e.records || []).map((x) => x.thumb)
88 69
 
89 70
         console.log(e)
90 71
       })
91 72
     },
92
-    onLoad() {
93
-      // 异步更新数据
94
-      let params = {
95
-        // type: this.selectedType,
96
-        index: this.currentPage, //页数
97
-        size: this.pageSize //每页个数
98
-      }
99
-      // xxxxxxx(params).then((res) => {
100
-      //   console.log(res)
101
-      //   this.dataTotal = res.total
102
-      //   //进行判断
103
-      //   if (this.dataTotal <= this.pageSize) {
104
-      //     this.Array = res.data.list
105
-      //     console.log(this.Array)
106
-      //   } else {
107
-      //     this.currentPage++
108
-      //     let arr = res.data.data.list
109
-      //     this.Array = this.Array.concat(arr)
110
-      //   }
111
-      //   // 加载状态结束
112
-      //   this.loading = false
113
-      //   // 数据全部加载完成
114
-      //   if (this.Array.length >= this.dataTotal) {
115
-      //     this.finished = true //结束,显示我也是有底线的
116
-      //   }
117
-      // })
118
-    }
73
+    onLoad() {}
119 74
   }
120 75
 }
121 76
 </script>
@@ -130,16 +85,6 @@ export default {
130 85
   width: 100vw;
131 86
   padding-top: 10px;
132 87
 
133
-  .banner-box-top {
134
-    position: relative;
135
-    width: calc(100% - 20px);
136
-
137
-    .banner-swipe {
138
-      border-radius: 6px;
139
-      box-shadow: 0 0 6px 6px rgba(0, 0, 0, 0.12);
140
-    }
141
-  }
142
-
143 88
   .course-list {
144 89
     margin-top: 10vw;
145 90
   }

+ 10
- 15
src/views/StrongPhoto.vue Voir le fichier

@@ -1,10 +1,6 @@
1 1
 <template>
2 2
   <div class="Photo-box">
3
-    <van-swipe :autoplay="3000">
4
-      <van-swipe-item v-for="(image, index) in photoBannerImages" :key="index">
5
-        <van-image width="100%" height="57vw" :src="image.thumb" />
6
-      </van-swipe-item>
7
-    </van-swipe>
3
+    <banner-swipe :list="photoBannerImages" />
8 4
     <div style="display: flex; aline-itme:center;margin-top: 30px;position:relative ">
9 5
       <!-- <div :class="`${classStyle?'Zhedie-box Donghua':'Zhedie-box'}`"> -->
10 6
       <div :class="{'Zhedie-box': true, 'expand': classStyle}">
@@ -46,12 +42,15 @@
46 42
 </template>
47 43
 
48 44
 <script>
49
-import { getPhotoSotr, getPhotos } from '../util/api'
50
-import { parseTime, SignInTime } from '../util/formattingData'
45
+import { getPhotoSotr, getPhotos } from '@/util/api'
46
+import { parseTime } from '@/util/formattingData'
51 47
 
52
-import { getBanner } from '../util/api'
48
+import { getBanner } from '@/util/api'
53 49
 
54 50
 export default {
51
+  components: {
52
+    BannerSwipe: () => import('./components/BannerSwipe.vue'),
53
+  },
55 54
   data() {
56 55
     return {
57 56
       classStyle: false,
@@ -145,7 +144,7 @@ export default {
145 144
     },
146 145
     onBanner() {
147 146
       getBanner('Wonderful').then((e) => {
148
-        this.photoBannerImages = e.records
147
+        this.photoBannerImages = (e.records || []).map(x => x.thumb)
149 148
         // console.log(e)
150 149
       })
151 150
     }
@@ -158,12 +157,8 @@ export default {
158 157
   width: 100vw;
159 158
   height: 100%;
160 159
   background-color: #fff;
161
-  .van-swipe {
162
-    width: 95%;
163
-    border-radius: 10px;
164
-    margin: 10px auto;
165
-    box-shadow: 0px 8px 38px 0px rgba(0, 0, 0, 0.2);
166
-  }
160
+  padding-top: 10px;
161
+
167 162
   .Zhedie-box {
168 163
     padding: 0 4vw;
169 164
     overflow: hidden;

+ 0
- 74
src/views/Tabber.vue Voir le fichier

@@ -1,74 +0,0 @@
1
-<template>
2
-  <div class="tabbar">
3
-    <van-tabbar class="van-tabbar" v-model="active" @change="onChange">
4
-      <van-tabbar-item icon="column">培训通知</van-tabbar-item>
5
-      <van-tabbar-item icon="photo">精彩集锦</van-tabbar-item>
6
-      <van-tabbar-item icon="manager">个人中心</van-tabbar-item>
7
-    </van-tabbar>
8
-  </div>
9
-</template>
10
-
11
-<script>
12
-export default {
13
-  name: 'Tabber',
14
-  props: {
15
-    // active: Number
16
-  },
17
-  data() {
18
-    return {
19
-      // tabbarTempValue: this.active,
20
-      active: 0
21
-    }
22
-  },
23
-  created() {
24
-    //由于 vant 标签栏路由模式,无法自动加载页面,所以这里需要初始化
25
-    // console.log(this.$route) //打印当前路由属性
26
-    this.active = 0
27
-
28
-    switch (this.$route.name) {
29
-      case 'Course':
30
-        this.active = 0
31
-        break
32
-      case 'StrongPhoto':
33
-        this.active = 1
34
-        break
35
-      case 'UserCenter':
36
-        this.active = 2
37
-        break
38
-      default:
39
-        break
40
-    }
41
-  },
42
-  methods: {
43
-    onChange(index) {
44
-      // console.log(index)
45
-      switch (index) {
46
-        case 0:
47
-          this.$router.push('/')
48
-
49
-          break
50
-        case 1:
51
-          this.$router.push('/StrongPhoto')
52
-
53
-          break
54
-        case 2:
55
-          this.$router.push('/UserCenter')
56
-
57
-          break
58
-        default:
59
-          break
60
-      }
61
-      // const routerArray = ['/Course', '/StrongPhoto', '/UserCenter']
62
-      // this.$router.push(routerArray[index])
63
-    }
64
-  }
65
-}
66
-</script>
67
-
68
-<style lang="less" scoped>
69
-.tabbar {
70
-  .van-tabbar {
71
-    // padding-bottom: 2em;
72
-  }
73
-}
74
-</style>

+ 4
- 9
src/views/UserCenter.vue Voir le fichier

@@ -2,7 +2,7 @@
2 2
   <div class="User-box flex flex-column">
3 3
     <div class="user-card flex-0">
4 4
       <div class="profile flex" v-if="divShow">
5
-        <img class="flex-0" src="@/assets/userImag/userImag.jpg" />
5
+        <avatar />
6 6
         <div class="info-name flex-1">
7 7
           <div class="title">
8 8
             {{person.name}}
@@ -40,6 +40,9 @@
40 40
 import { mapState } from 'vuex'
41 41
 // import {SetUser} from '../util/api'
42 42
 export default {
43
+  components: {
44
+    avatar: () => import('@/components/Avatar/index.vue')
45
+  },
43 46
   data() {
44 47
     return {
45 48
       menus: [
@@ -92,14 +95,6 @@ export default {
92 95
 
93 96
     .profile {
94 97
       width: 100%;
95
-      
96
-      > img {
97
-        width: 70px;
98
-        height: 70px;
99
-        border-radius: 50%;
100
-        position: relative;
101
-        box-shadow: 0px 8px 38px 0px rgba(0, 0, 0, 0.2);
102
-      }
103 98
       .info-name {
104 99
         margin-left: 1em;
105 100
         position: relative;

+ 71
- 0
src/views/components/BannerSwipe.vue Voir le fichier

@@ -0,0 +1,71 @@
1
+<template>
2
+  <div class="banner-swipe-box" >
3
+    <van-swipe class="banner-swipe" :autoplay="3000" @change="i => current = i" :show-indicators="false">
4
+      <van-swipe-item v-for="image in list" :key="image">
5
+        <ration-div :ratio="0.6">
6
+          <van-image width="100%" height="100%" :src="image" />
7
+        </ration-div>
8
+      </van-swipe-item>
9
+    </van-swipe>
10
+    <div class="custom-indicator">
11
+      <span v-for="(image, index) in list" :key="image" :class="{'active': current === index }"></span>
12
+    </div>
13
+  </div>
14
+</template>
15
+
16
+<script>
17
+export default {
18
+  name: 'BannerSwipe',
19
+  components: {
20
+    RationDiv: () => import('@/components/RatioDiv/index.vue'),
21
+  },
22
+  props: {
23
+    list: {
24
+      type: Array,
25
+      default: () => ([])
26
+    }
27
+  },
28
+  data() {
29
+    return {
30
+      current: 0,
31
+    }
32
+  }
33
+}
34
+</script>
35
+
36
+<style lang="less" scoped>
37
+.banner-swipe-box {
38
+  position: relative;
39
+  margin-left: 10px;
40
+  margin-right: 10px;
41
+  width: calc(100% - 20px);
42
+
43
+  .banner-swipe {
44
+    border-radius: 6px;
45
+    box-shadow: 0 0 6px 6px rgba(0, 0, 0, 0.12);
46
+  }
47
+
48
+  .custom-indicator {
49
+    position: absolute;
50
+    width: 100%;
51
+    text-align: center;
52
+    left: 0;
53
+    right: 0;
54
+    z-index: 10;
55
+
56
+    & > span {
57
+      display: inline-block;
58
+      width: 1em;
59
+      height: 2px;
60
+      background: rgba(0, 0, 0, 0.2);
61
+
62
+      & + span {
63
+        margin-left: .2em;
64
+      }
65
+    }
66
+    .active {
67
+      background: rgba(0, 0, 0, .65);
68
+    }
69
+  }
70
+}
71
+</style>

+ 128
- 69
src/views/signIn.vue Voir le fichier

@@ -1,92 +1,144 @@
1 1
 <template>
2 2
   <div class="Clockln-box">
3 3
     <div class="box1">
4
-      <img src="../assets/userImag/userImag.jpg" alt />
5
-      <div class="box1-title">{{title}}</div>
4
+      <div class="box-item box1-avatar">
5
+        <avatar />
6
+      </div>
7
+      <div class="box-item box1-title">{{signInfo.name}}</div>
6 8
       <div class="box1-time">签到结束时间</div>
7
-      <div class="box1-time">{{parseTime(endTime, '{y}年{m}月{d}日 {h}:{i}')}}</div>
9
+      <div class="box1-time">{{endTimeStr}}</div>
8 10
     </div>
9
-    <div :class="{'myDIV':true, 'disabled':ok}" @click="goSign">
10
-      <div>上课打卡</div>
11
-      <span>{{SignInTime(nowTime)}}</span>
11
+    <div :class="{ 'myDIV': true }" @click="goSign">
12
+      <div>{{signText}}</div>
13
+      <span>{{currentTimeStr}}</span>
12 14
     </div>
13 15
 
14
-    <img src="../assets/basemap.png" alt width="100%" />
16
+    <img src="~@/assets/basemap.png" alt width="100%" />
15 17
   </div>
16 18
 </template>
17 19
 
18 20
 <script>
19
-import { getSignInInfof, getSignIn } from '../util/api'
20
-import query from '../util/query'
21
-import { parseTime, SignInTime } from '../util/formattingData'
21
+import { getSignInInfo, postSignIn } from '@/util/api'
22
+import { parseTime } from '@/util/formattingData'
23
+import { mapState } from 'vuex'
24
+
22 25
 export default {
26
+  components: {
27
+    avatar: () => import('@/components/Avatar/index.vue')
28
+  },
23 29
   data() {
24 30
     return {
25
-      signId: '',
26
-      phone: '',
27
-      ok: false,
28
-      endTime: '',
29
-      title: '',
30
-      nowTime: new Date()
31
+      signInfo: {},
32
+      canSign: false,
33
+      noSignErr: '',
34
+      shortErr: '',
35
+      ticker: null,
36
+      now: new Date()
37
+    }
38
+  },
39
+  computed: {
40
+    ...mapState({
41
+      person: s => s.user
42
+    }),
43
+    endTimeStr() {
44
+      if (!this.signInfo.endTime) return '未知';
45
+
46
+      return parseTime(this.signInfo.endTime, '{y}年{m}月{d}日 {h}:{i}')
47
+    },
48
+    currentTimeStr() {
49
+      return parseTime(this.now, '{h}:{i}:{s}')
50
+    },
51
+    signText() {
52
+      return this.canSign ? '签 到' : this.shortErr
53
+    }
54
+  },
55
+  watch: {
56
+    '$route.query.signId': {
57
+      handler(v) {
58
+        if (v) {
59
+          this.onLoadSinInfo(v)
60
+        }
61
+      },
62
+      immediate: true
31 63
     }
32 64
   },
65
+  created() {
66
+    this.ticker = setInterval(() => {
67
+      this.now = new Date()
68
+    }, 1000)
69
+  },
33 70
   mounted() {
34
-    this.signId = query('signId')
35
-    this.phone = this.$store.state.user.phone
36
-
37
-    this.onLoadSinInO()
38
-    let that = this
39
-    this.timer = setInterval(function () {
40
-      that.nowTime = new Date().toLocaleString()
41
-    })
71
+    const {phone} = this.person || {}
72
+
73
+    if (!phone) {
74
+      this.$dialog.alert({
75
+        message: '请先维护您的个人信息',
76
+      }).then(() => {
77
+        this.$router.push({ name: 'SetUser' })
78
+      })
79
+    }
42 80
   },
43
-  //离开当前页面后执行
44
-  destroyed: function () {
45
-    // 销毁时清除计时器
46
-    this.beforeDestroy()
81
+  beforeDestroy() {
82
+    if (this.ticker) {
83
+      clearInterval(this.ticker)
84
+    }
47 85
   },
86
+
48 87
   methods: {
49
-    SignInTime,
50 88
     parseTime,
51
-    // 销毁时清除计时器
52
-    beforeDestroy: function () {
53
-      console.log('销毁时清除计时器')
54
-      if (this.timer) {
55
-        clearInterval(this.timer)
56
-      }
57
-    },
58 89
     //首先判断他有没有资格
59 90
     //  this.$toast.success('修改成功!')
60
-    onLoadSinInO() {
61
-      getSignInInfof().then((e) => {
62
-        const { canSign, endTime, startTime, isSigned, name } = e
63
-        this.endTime = endTime
64
-        this.title = name
65
-
66
-        let starDtat = new Date(startTime) - new Date()
67
-        let endDtat = new Date(endTime) - new Date()
68
-
69
-        if (this.phone) {
70
-          if (canSign) {
71
-            if (starDtat < 0) {
72
-              if (endDtat < 0) {
73
-                if (!isSigned) {
74
-                  this.ok = true
75
-                } else {
76
-                  this.$toast.fail('您已签到过')
77
-                }
78
-              }
79
-            } else {
80
-              this.$toast.fail('未到签到时间')
81
-            }
82
-          }
83
-        } else {
84
-          this.$toast.fail('请维护手机号')
91
+    onLoadSinInfo(id) {
92
+      getSignInInfo(id).then((e) => {
93
+        this.signInfo = e
94
+        
95
+        // 必须属于签到池人员
96
+        if (!this.signInfo.canSign) {
97
+          this.canSign = false;
98
+          this.noSignErr = '当前活动您未参与';
99
+          this.shortErr = '未参与';
100
+          return;
85 101
         }
102
+
103
+        if (this.signInfo.isSigned) {
104
+          this.canSign = false;
105
+          this.noSignErr = '您已签到';
106
+          this.shortErr = '已签到';
107
+          return;
108
+        }
109
+
110
+        // 必须是签到时间
111
+        const isGtStart = (this.now - new Date(this.signInfo.startTime)) > 0
112
+        const isLtEnd = (this.now - new Date(this.signInfo.endTime)) < 0
113
+        if (!isGtStart) {
114
+          this.canSign = false;
115
+          this.noSignErr = '签到未开始';
116
+          this.shortErr = '未开始';
117
+          return;
118
+        }
119
+
120
+        if (!isLtEnd) {
121
+          this.canSign = false;
122
+          this.noSignErr = '签到已结束';
123
+          this.shortErr = '已结束';
124
+          return;
125
+        }
126
+
127
+        this.canSign = true;
128
+        this.noSignErr = '';
129
+        this.shortErr = '';
130
+
131
+      }).catch(e => {
132
+        this.$toast(e.message)
86 133
       })
87 134
     },
88 135
     goSign() {
89
-      getSignIn().then((e) => {
136
+      if (!this.canSign) {
137
+        this.$toast(this.noSignErr);
138
+        return;
139
+      }
140
+
141
+      postSignIn(this.$route.query.signId).then((e) => {
90 142
         console.log(e)
91 143
         this.$toast('签到成功')
92 144
       })
@@ -100,21 +152,27 @@ export default {
100 152
   background-color: #fff;
101 153
   height: 100%;
102 154
   width: 100vw;
155
+  padding-top: 60px;
156
+
157
+  .box-item {
158
+    & + .box-item {
159
+      margin-top: 3em;
160
+    }
161
+  }
103 162
   .box1 {
104 163
     width: 100%;
105
-    > img {
106
-      width: 80px;
107
-      border-radius: 50%;
108
-      margin: 0 auto;
109
-      display: block;
110
-      padding: 35px 0 20px 0;
164
+
165
+    &-avatar {
166
+      display: flex;
167
+      justify-content: center;
111 168
     }
169
+
112 170
     &-title {
113 171
       width: 90%;
114 172
       margin: 0 auto;
115 173
       text-align: center;
116 174
       color: #000;
117
-      font-size: 17px;
175
+      font-size: 18px;
118 176
       font-weight: 700;
119 177
       margin-bottom: 30px;
120 178
     }
@@ -147,6 +205,7 @@ export default {
147 205
       font-size: 19px;
148 206
       margin-bottom: 10px;
149 207
       font-weight: 600;
208
+      letter-spacing: 2px;
150 209
     }
151 210
 
152 211
     > span {