seamwang před 1 rokem
rodič
revize
4cd8f092ef
6 změnil soubory, kde provedl 164 přidání a 17956 odebrání
  1. 31 17893
      package-lock.json
  2. 1 0
      package.json
  3. 6 2
      src/api/course.js
  4. 8 22
      src/components/calendar.vue
  5. 1 1
      src/pages/class/detail.vue
  6. 117 38
      src/pages/class/gift.vue

Diff nebyl zobrazen, protože je příliš veliký
+ 31 - 17893
package-lock.json


+ 1 - 0
package.json

@@ -31,6 +31,7 @@
31 31
     "@dcloudio/uni-cli-i18n": "^2.0.1-34720220422002",
32 32
     "@dcloudio/uni-ui": "^1.4.14",
33 33
     "number-precision": "^1.4.0",
34
+    "regenerator-runtime": "^0.13.11",
34 35
     "vue": "^2.6.10",
35 36
     "vue-class-component": "^6.3.2",
36 37
     "vue-count-to": "^1.0.13",

+ 6 - 2
src/api/course.js

@@ -9,8 +9,8 @@ export function _intelligentDates () {
9 9
 	return fetch('/parents/Intelligent/getLigentDate')
10 10
 }
11 11
 //智能报课获取兴趣
12
-export function _intelligentInterests () {
13
-	return fetch('/parents/Intelligent/getLigentCategory')
12
+export function _intelligentInterests (params) {
13
+	return fetch('/parents/Intelligent/getLigentCategory', params)
14 14
 }
15 15
 //智能报课关键词检索
16 16
 export function _intelligentGetKeys (params) {
@@ -136,3 +136,7 @@ export function _getClasses (params) {
136 136
 export function _fixStudent (params) {
137 137
 	return fetch('/parents/student/update', params)
138 138
 }
139
+//检索冲突
140
+export function _checkConflict (params) {
141
+	return fetch('/parents/Intelligent/conflictcheck', params)
142
+}

+ 8 - 22
src/components/calendar.vue

@@ -7,7 +7,7 @@
7 7
       <view v-for="(item, index) in dateArr" :key="index" @tap="calendarTap(item, index)">
8 8
         <view
9 9
           class="date-head1"
10
-          :class="[todayIndex === index ? 'operationInProgress' : showBusiness ? item.styleClass : '', { showOverdue: item.showOverdue, 'date-class': item.dateClass }]"
10
+          :class="[todayIndex === index ? 'operationInProgress' : '', showBusiness ? item.styleClass : '', { showOverdue: item.showOverdue, 'date-class': item.dateClass }]"
11 11
         >
12 12
           <view>{{ item.dateNum }}</view>
13 13
         </view>
@@ -100,6 +100,8 @@ export default {
100 100
           const renderingTime = '' + year + (month + 1 > 9 ? month + 1 : '0' + (month + 1)) + (num > 9 ? num : '0' + num)
101 101
           if (Number(currentTime) > Number(renderingTime)) {
102 102
             showOverdue = 1 // 过期
103
+          } else if (Number(currentTime) == Number(renderingTime)) {
104
+            this.todayIndex = i
103 105
           } else {
104 106
             showOverdue = 0 // 有效
105 107
           }
@@ -152,7 +154,6 @@ export default {
152 154
 }
153 155
 .header-cal {
154 156
   font-size: 0;
155
-  /* padding: 0 24rpx;  */
156 157
 }
157 158
 .header-cal > view {
158 159
   display: inline-block;
@@ -160,7 +161,6 @@ export default {
160 161
   color: #5fd0e4;
161 162
   font-size: 30rpx;
162 163
   text-align: center;
163
-  /* border-bottom: 1px solid #D0D0D0;  */
164 164
   padding: 39rpx 0;
165 165
 }
166 166
 .weekMark {
@@ -213,36 +213,26 @@ export default {
213 213
 .nowDay .date-weight {
214 214
   color: #22a7f6;
215 215
 }
216
-/* 过期样式*/
217
-.showOverdue {
218
-  color: #5fd0e4;
219
-}
220 216
 /* 正在操作样式*/
221 217
 .operationInProgress {
222
-  // background: #20ba96;
223
-  // color: #fff;
224 218
   color: #20ba96;
225 219
 }
226 220
 /* 正常样式*/
227 221
 .normal {
228
-  // background: #4db8e4;
229
-  // color: #fff;
230 222
   &:after {
231 223
     content: '';
232 224
     position: absolute;
233 225
     bottom: 0;
234 226
     right: 0;
235
-    width: 0;
236
-    height: 0;
237
-    border-color: #39b54a transparent;
238
-    border-width: 0 0 12px 12px;
239
-    border-style: solid;
227
+    width: 6px;
228
+    height: 10px;
229
+    border-bottom: 2px solid #39b54a;
230
+    border-right: 2px solid #39b54a;
231
+    transform: rotate(45deg);
240 232
   }
241 233
 }
242 234
 /* 异常样式*/
243 235
 .abnormal {
244
-  // background: #ff7361;
245
-  // color: #fff;
246 236
   &:after {
247 237
     content: '';
248 238
     position: absolute;
@@ -256,8 +246,6 @@ export default {
256 246
   }
257 247
 }
258 248
 .leave {
259
-  // background: #3390f5;
260
-  // color: #fff;
261 249
   &:after {
262 250
     content: '';
263 251
     position: absolute;
@@ -271,8 +259,6 @@ export default {
271 259
   }
272 260
 }
273 261
 .late {
274
-  // background: #fbbd08;
275
-  // color: #fff;
276 262
   &:after {
277 263
     content: '';
278 264
     position: absolute;

+ 1 - 1
src/pages/class/detail.vue

@@ -72,7 +72,7 @@
72 72
         </view>
73 73
       </view>
74 74
       <!-- 道具选择 -->
75
-      <view class="shop margin-top-sm shadow" v-if="detail.prop && detail.prop.length > 0">
75
+      <view class="shop margin-top-sm shadow" v-if="detail.prop && detail.prop.length > 0 && !detail.prop[0].required">
76 76
         <view class="shop-title">请选择课程所需要的道具</view>
77 77
         <radio-group @change="radioChange" class="margin-top-xs">
78 78
           <label v-for="radio in radios" :key="radio.value" class="tool-choose margin-right-sm">

+ 117 - 38
src/pages/class/gift.vue

@@ -34,7 +34,7 @@
34 34
               </view>
35 35
               <view class="margin-top-sm">
36 36
                 <view v-for="(h, i) in params.hobbyOther" :key="i" class="hobby"
37
-                  >{{ h }}
37
+                  >{{ i + 1 }}.{{ h }}
38 38
                   <text class="cuIcon-close del-hobby text-red" @tap="delHobby(h)"></text>
39 39
                 </view>
40 40
               </view>
@@ -95,9 +95,9 @@
95 95
                               >
96 96
                               <view>
97 97
                                 <checkbox
98
-                                  :disabled="course.status == 0"
99 98
                                   :value="course.class_attend_id"
100
-                                  :checked="checked.includes(course.class_attend_id)"
99
+                                  :disabled="course.status == 0"
100
+                                  :checked="checked[i].includes(course.class_attend_id)"
101 101
                                   class="round cyan"
102 102
                                   style="transform: scale(0.7);"
103 103
                                 />
@@ -111,11 +111,13 @@
111 111
                           <label v-for="prop in course.prop" :key="prop.id">
112 112
                             <view>
113 113
                               <checkbox
114
+                                :checked="
115
+                                  checked_props[i][c] ? checked_props[i][c].class_attend_id === course.class_attend_id && checked_props[i][c].prop.includes(prop.id) : false
116
+                                "
114 117
                                 :disabled="course.status == 0"
115 118
                                 :value="prop.id"
116 119
                                 class="cyan"
117 120
                                 style="transform: scale(0.7);"
118
-                                :checked="checked_props[i].class_attend_id === course.class_attend_id && checked_props[i].prop.includes(prop.id)"
119 121
                               />{{ prop.name }}<text>¥{{ prop.money }}</text>
120 122
                             </view>
121 123
                           </label>
@@ -135,7 +137,6 @@
135 137
                   </button>
136 138
                 </view>
137 139
                 <view class="static-order flex">
138
-                  <shop-cart :class_attend_id="attend_id" @changeDisableBtn="changeDisableBtn"></shop-cart>
139 140
                   <button class="cu-btn round bg-student text-white margin-left-xs" @tap="addCart">报课</button>
140 141
                 </view>
141 142
               </view>
@@ -148,13 +149,10 @@
148 149
 </template>
149 150
 
150 151
 <script>
151
-import { _intelligentDates, _intelligentInterests, _intelligentCourses, _intelligentGetKeys, _joinShops } from '@/api/course'
152
-import shopCart from '@/components/shop-cart.vue'
152
+import { _intelligentDates, _intelligentInterests, _intelligentCourses, _intelligentGetKeys, _joinShops, _checkConflict } from '@/api/course'
153 153
 import { mapGetters } from 'vuex'
154
+import socket from '@/common/webSocket'
154 155
 export default {
155
-  components: {
156
-    shopCart
157
-  },
158 156
   data() {
159 157
     return {
160 158
       topHeader: this.globalCustomBarHeight,
@@ -189,13 +187,15 @@ export default {
189 187
       colors: ['#0CAAF4', '#082FCC', '#FDC534', '#09E294'],
190 188
       checked: [], // 选中
191 189
       checked_props: [], // 选中工具
190
+      checkedIds: [], //已选中选项
191
+      conflictIds: [], //冲突选项
192 192
       attend_id: 0, // 添加成功课程
193 193
       disableBtn: false, // 避免多次重复点击
194 194
       action: 'stopmove'
195 195
     }
196 196
   },
197 197
   computed: {
198
-    ...mapGetters(['kid'])
198
+    ...mapGetters(['kid', 'ifConnectOrder'])
199 199
   },
200 200
   onLoad(options) {
201 201
     const id = decodeURIComponent(options.package_id)
@@ -209,19 +209,36 @@ export default {
209 209
   methods: {
210 210
     init() {
211 211
       this.getDateConfig()
212
-      this.getHobbyConfig()
212
+      socket.initSocket()
213 213
     },
214 214
     getDateConfig() {
215 215
       _intelligentDates().then(res => {
216 216
         this.days = res.data
217 217
       })
218 218
     },
219
+    checkConflict(id) {
220
+      return new Promise((resolve, reject) => {
221
+        if (this.checkedIds.length < 1) {
222
+          resolve(false)
223
+          return
224
+        }
225
+        const params = {
226
+          checked: id,
227
+          ids: this.checkedIds.join(',')
228
+        }
229
+        _checkConflict(params).then(res => {
230
+          this.checkedIds = res.data.checked_list.map(item => item.class_attend_id)
231
+          this.conflictIds = res.data.conflict_list.map(item => item.class_attend_id)
232
+          resolve(res.data.checked_res)
233
+        })
234
+      })
235
+    },
219 236
     getHobbyConfig() {
220
-      _intelligentInterests().then(res => {
221
-        // this.interests = res.data
237
+      const params = { week: this.params.week.join(',') }
238
+      _intelligentInterests(params).then(res => {
222 239
         const choose = res.data[res.data.length - 1]
223 240
         this.params.hobby = [choose.id]
224
-        this.keys = [...new Set(choose.names)].filter(e => e)
241
+        this.keys = [...new Set(Object.values(choose.names))].filter(e => e)
225 242
         if (this.interests.length < 1) this.interests = this.keys.slice(0, 5)
226 243
       })
227 244
     },
@@ -239,6 +256,7 @@ export default {
239 256
       const params = { week: this.params.week.join(','), student_id: this.kid, keywords: key }
240 257
       _intelligentGetKeys(params).then(res => {
241 258
         if (res.data.length < 1) {
259
+          this.params.hobbyOther = this.params.hobbyOther.filter(k => k != key)
242 260
           uni.showToast({
243 261
             title: '未找到相关课程',
244 262
             icon: 'none',
@@ -257,17 +275,25 @@ export default {
257 275
         this.checked = [] //初始化选项
258 276
         if (this.attends.length > 0) {
259 277
           this.attends.map((course, index) => {
260
-            //过滤不能报课的
261 278
             const list = course.list
262 279
             const item = list[0]
263 280
             const class_attend_id = item.status > 0 ? item.class_attend_id : null
264
-            this.$set(this.checked, index, class_attend_id)
281
+            this.$set(this.checked, index, [class_attend_id])
265 282
             const prop = item.prop.length > 0 ? [item.prop[0].id] : []
266
-            this.$set(this.checked_props, index, { class_attend_id: class_attend_id, prop: prop })
283
+            this.$set(this.checked_props, index, [{ class_attend_id: class_attend_id, prop: prop }])
267 284
           })
285
+          this.checkedIds = this.getCheckedIds()
268 286
         }
269 287
       })
270 288
     },
289
+    getCheckedIds() {
290
+      //获取默认选择集合
291
+      let arr = []
292
+      this.checked.forEach(v => {
293
+        arr = arr.concat(v)
294
+      })
295
+      return arr.filter(e => e)
296
+    },
271 297
     delHobby(key) {
272 298
       this.params.hobbyOther = this.params.hobbyOther.filter(item => item != key)
273 299
     },
@@ -307,6 +333,9 @@ export default {
307 333
         uni.showToast({ title: '请先选择兴趣', icon: 'none' })
308 334
         return false
309 335
       }
336
+      if (index === 1) {
337
+        this.getHobbyConfig()
338
+      }
310 339
       const step = Math.abs(index - this.cur)
311 340
       if (step > 1) return false
312 341
       this.cur = index
@@ -320,27 +349,61 @@ export default {
320 349
     changeDisableBtn() {
321 350
       this.disableBtn = true
322 351
     },
323
-    classChange(course, i) {
352
+    async classChange(course, i) {
353
+      //失效课程点击无效
324 354
       if (course.status == 0) {
325 355
         return false
326 356
       }
327 357
       const class_attend_id = course.class_attend_id
328
-      if (this.checked.includes(class_attend_id)) {
329
-        this.$set(this.checked, i, null)
330
-        this.$set(this.checked_props, i, { class_attend_id: null, prop: [] })
358
+      if (this.checked[i].includes(class_attend_id)) {
359
+        this.batchCancel([class_attend_id])
331 360
       } else {
332
-        this.$set(this.checked, i, class_attend_id)
333
-        this.$set(this.checked_props, i, { class_attend_id: class_attend_id, prop: [] })
361
+        //判断课程冲突
362
+        const pass = await this.checkConflict(course.class_attend_id)
363
+        if (pass) {
364
+          //冲突取消之前选择
365
+          uni.showToast({ title: '存在课程时间冲突,已取消冲突课程!', icon: 'none', duration: 2000 })
366
+          this.batchCancel(this.conflictIds)
367
+        }
368
+        this.batchChoose(class_attend_id, [])
334 369
       }
335 370
     },
336
-    propChange(e, i) {
371
+    async propChange(e, i) {
337 372
       const parentId = e.target.dataset.id
338 373
       const values = e.detail.value.map(item => Number(item))
339
-      if (values.length > 0 && !this.checked.includes(parentId)) {
340
-        this.$set(this.checked, i, parentId)
374
+      if (values.length > 0 && !this.checked[i].includes(parentId)) {
375
+        //判断课程冲突
376
+        const pass = await this.checkConflict(parentId)
377
+        if (pass) {
378
+          //冲突取消之前选择
379
+          uni.showToast({ title: '存在课程时间冲突,已取消冲突课程!', icon: 'none', duration: 2000 })
380
+          this.batchCancel(this.conflictIds)
381
+        }
341 382
       }
342
-      const item = { class_attend_id: parentId, prop: values }
343
-      this.$set(this.checked_props, i, item)
383
+      this.batchChoose(parentId, values)
384
+    },
385
+    batchCancel(ids) {
386
+      if (ids.length < 1) return false
387
+      this.checked.forEach((e, i) => {
388
+        const f = e.findIndex(c => ids.includes(c))
389
+        if (f >= 0) {
390
+          this.$set(this.checked[i], f, null)
391
+          this.$set(this.checked_props[i], f, { class_attend_id: null, prop: [] })
392
+        }
393
+      })
394
+    },
395
+    batchChoose(id, props) {
396
+      this.attends.map((course, i) => {
397
+        const list = course.list
398
+        const c = list.findIndex(e => e.class_attend_id == id)
399
+        if (c >= 0) {
400
+          const choose = list[c]
401
+          this.$set(this.checked[i], c, choose.class_attend_id)
402
+          //道具选择
403
+          const items = props.length > 0 ? props : choose.prop.length > 0 ? [choose.prop[0].id] : []
404
+          this.$set(this.checked_props[i], c, { class_attend_id: choose.class_attend_id, prop: items })
405
+        }
406
+      })
344 407
     },
345 408
     TabSelect(e) {
346 409
       this.tabCur = e.currentTarget.dataset.id
@@ -348,10 +411,22 @@ export default {
348 411
       this.verticalNavTop = (e.currentTarget.dataset.id - 1) * 50
349 412
     },
350 413
     addCart() {
351
-      if (this.disableBtn) return false
414
+      uni.showLoading({
415
+        mask: true,
416
+        title: '加载中...'
417
+      })
418
+      //合并选中项
419
+      let arr = []
420
+      this.checked_props.forEach(v => {
421
+        arr = arr.concat(v)
422
+      })
423
+      if (this.disableBtn) {
424
+        uni.hideLoading()
425
+        return false
426
+      }
352 427
       this.disableBtn = true
353 428
       const _self = this
354
-      const list = this.checked_props
429
+      const list = arr
355 430
         .filter(item => item.class_attend_id)
356 431
         .map(item => {
357 432
           return {
@@ -361,13 +436,22 @@ export default {
361 436
           }
362 437
         })
363 438
       if (list.length < 1) {
439
+        uni.hideLoading()
364 440
         uni.showToast({ title: '请先选择课程', icon: 'none' })
365 441
         this.disableBtn = false
366 442
         return false
367 443
       }
368 444
       _joinShops({ list }).then(res => {
369 445
         if (res.code === 1) {
370
-          _self.globalNavigateTo('classCart')
446
+          setTimeout(() => {
447
+            if (!this.ifConnectOrder) {
448
+              // socket非正常状态
449
+              uni.hideLoading()
450
+              this.globalNavigateTo('order', { type: 1 })
451
+            }
452
+            this.disableBtn = false
453
+            this.$store.dispatch('setConnect', false)
454
+          }, 3000)
371 455
         } else {
372 456
           this.disableBtn = false
373 457
         }
@@ -405,12 +489,7 @@ export default {
405 489
 .hobby {
406 490
   position: relative;
407 491
   display: inline-block;
408
-  margin-left: 20rpx;
409
-  padding: 10rpx 40rpx;
410
-  border-radius: 100rpx;
411
-  border: 1px solid #eee;
412
-  color: #fff;
413
-  background-color: #09e294;
492
+  margin-left: 30rpx;
414 493
   .del-hobby {
415 494
     position: absolute;
416 495
     top: -6rpx;