浏览代码

添加新功能

lex-xin 5 年之前
父节点
当前提交
41192a5dd2
共有 63 个文件被更改,包括 1287 次插入11 次删除
  1. 0 0
      dist/css/Account.0da71852.css
  2. 0 0
      dist/css/CallNames.a5c49da3.css
  3. 0 0
      dist/css/CourseApply.874db7a1.css
  4. 1 0
      dist/css/ExchangeRecord.e23b8cdd.css
  5. 0 0
      dist/css/IStarted.2ceb2ecc.css
  6. 1 0
      dist/css/PeriodExchange.2519fb67.css
  7. 1 0
      dist/css/PeriodRecord.74104831.css
  8. 0 0
      dist/css/chunk-vendors.736d3854.css
  9. 0 0
      dist/css/chunk-vendors.96e82baf.css
  10. 二进制
      dist/img/icon_teacher.de517191.png
  11. 0 0
      dist/index.html
  12. 0 0
      dist/js/Account.8e881ff9.js
  13. 0 0
      dist/js/Account~Approval~Attendance~CallNames~CourseApply~ExchangeRecord~IStarted~Leave~PeriodAdjust~PeriodC~bed631d0.1e8062e4.js
  14. 0 0
      dist/js/Approval.08cf098b.js
  15. 0 0
      dist/js/Approval.df86ba16.js
  16. 0 0
      dist/js/Approval~Attendance~CallNames~IStarted~Leave~PeriodAdjust~PeriodChange~TeachingSchool~TeachingSet~VI~0d4456f6.8d78c334.js
  17. 0 0
      dist/js/Attendance.6dbaa6d7.js
  18. 0 0
      dist/js/Attendance.f24b6884.js
  19. 0 0
      dist/js/BookingSet.d617bf6f.js
  20. 0 0
      dist/js/Business.83056cc1.js
  21. 0 0
      dist/js/CallNames.6fbf6c4d.js
  22. 0 0
      dist/js/CallNames.888f73bf.js
  23. 0 0
      dist/js/CcMe.ebb8c1f7.js
  24. 0 0
      dist/js/CourseApply.fb7375f0.js
  25. 0 0
      dist/js/ExchangeRecord.c7ba1bb7.js
  26. 0 0
      dist/js/IStarted.57ad01d2.js
  27. 0 0
      dist/js/IStarted.aebd6840.js
  28. 0 0
      dist/js/Leave.0a7271b2.js
  29. 0 0
      dist/js/Leave.6d687860.js
  30. 0 0
      dist/js/PeriodAdjust.2c1731c1.js
  31. 0 0
      dist/js/PeriodAdjust~PeriodChange.6b7f9168.js
  32. 0 0
      dist/js/PeriodAdjust~PeriodChange.c4c05fdd.js
  33. 0 0
      dist/js/PeriodChange.e9399e06.js
  34. 0 0
      dist/js/PeriodExchange.ca2c75e7.js
  35. 0 0
      dist/js/PeriodRecord.aa0bcc99.js
  36. 0 0
      dist/js/StartedDetail.d61ed066.js
  37. 0 0
      dist/js/TeachingSchool.660d1b6f.js
  38. 0 0
      dist/js/TeachingSchool.a3bb12b8.js
  39. 0 0
      dist/js/TeachingSet.5d8fe527.js
  40. 0 0
      dist/js/TeachingSet.f7b28d17.js
  41. 0 0
      dist/js/VIPApply.2eff2436.js
  42. 0 0
      dist/js/app.99079cfb.js
  43. 0 0
      dist/js/app.c5866dbd.js
  44. 0 0
      dist/js/chunk-vendors.159b9db5.js
  45. 0 0
      dist/js/chunk-vendors.4c5b1713.js
  46. 0 0
      dist/js/order.15fbdbfb.js
  47. 0 0
      dist/js/order.f7045d59.js
  48. 0 0
      dist/js/privacy.d0732084.js
  49. 9 9
      package-lock.json
  50. 1 1
      package.json
  51. 35 0
      src/api/app.js
  52. 二进制
      src/assets/images/app/icon_lock.png
  53. 二进制
      src/assets/images/app/icon_times.png
  54. 二进制
      src/assets/images/app/plus-square-o.png
  55. 二进制
      src/assets/images/icon_teacher.png
  56. 48 0
      src/router/appRouter.js
  57. 2 0
      src/router/index.js
  58. 141 0
      src/views/app/Account.vue
  59. 710 0
      src/views/app/CourseApply.vue
  60. 106 0
      src/views/app/ExchangeRecord.vue
  61. 124 0
      src/views/app/PeriodExchange.vue
  62. 107 0
      src/views/app/PeriodRecord.vue
  63. 1 1
      vue.config.js

文件差异内容过多而无法显示
+ 0 - 0
dist/css/Account.0da71852.css


+ 0 - 0
dist/css/CallNames.aa6a39f9.css → dist/css/CallNames.a5c49da3.css


文件差异内容过多而无法显示
+ 0 - 0
dist/css/CourseApply.874db7a1.css


+ 1 - 0
dist/css/ExchangeRecord.e23b8cdd.css

@@ -0,0 +1 @@
+.mheader[data-v-61d0e2e4]{height:.44rem;overflow:hidden}.m-nav-header[data-v-61d0e2e4]{position:absolute;left:0;top:0;width:100%;height:.44rem;line-height:.44rem;background-color:#14928a;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;color:#fff}.m-nav-header.fixed[data-v-61d0e2e4]{position:fixed;z-index:99}.m-nav-header .m-nav-bar__title[data-v-61d0e2e4]{max-width:60%;margin:0 auto;color:#fff;font-weight:500;font-size:.16rem}.m-nav-header .m-nav-bar__left[data-v-61d0e2e4],.m-nav-header .m-nav-bar__right[data-v-61d0e2e4]{position:absolute;bottom:0}.m-nav-header .m-nav-bar__left[data-v-61d0e2e4]{left:.12rem}.m-nav-header .m-nav-bar__left .arrow-left[data-v-61d0e2e4]{font-size:.21rem;vertical-align:middle}.m-nav-header .m-nav-bar__right[data-v-61d0e2e4]{right:.12rem}.icon[data-v-67669af7]{width:2rem;height:2rem;margin:.5rem auto .05rem}.icon_nodata[data-v-67669af7]{background:url(../img/icon_nodata.81c87d57.png) no-repeat 50%;background-size:contain}.msg[data-v-67669af7]{color:#aaa;font-size:.16rem;text-align:center;line-height:.22rem}.periodExchange[data-v-1f090ab9]{min-height:100vh}.periodExchange .exchangeText[data-v-1f090ab9]{font-size:.17rem;color:#1a1a1a;line-height:.24rem}.periodExchange .exchangeText.enum[data-v-1f090ab9]{color:#2fb371}.periodExchange .info[data-v-1f090ab9]{font-size:.14rem;color:grey}

+ 0 - 0
dist/css/IStarted.06b3060c.css → dist/css/IStarted.2ceb2ecc.css


+ 1 - 0
dist/css/PeriodExchange.2519fb67.css

@@ -0,0 +1 @@
+.mheader[data-v-61d0e2e4]{height:.44rem;overflow:hidden}.m-nav-header[data-v-61d0e2e4]{position:absolute;left:0;top:0;width:100%;height:.44rem;line-height:.44rem;background-color:#14928a;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;color:#fff}.m-nav-header.fixed[data-v-61d0e2e4]{position:fixed;z-index:99}.m-nav-header .m-nav-bar__title[data-v-61d0e2e4]{max-width:60%;margin:0 auto;color:#fff;font-weight:500;font-size:.16rem}.m-nav-header .m-nav-bar__left[data-v-61d0e2e4],.m-nav-header .m-nav-bar__right[data-v-61d0e2e4]{position:absolute;bottom:0}.m-nav-header .m-nav-bar__left[data-v-61d0e2e4]{left:.12rem}.m-nav-header .m-nav-bar__left .arrow-left[data-v-61d0e2e4]{font-size:.21rem;vertical-align:middle}.m-nav-header .m-nav-bar__right[data-v-61d0e2e4]{right:.12rem}.periodExchange[data-v-e2dff0d0]{min-height:100vh;position:relative}.periodExchange .logo[data-v-e2dff0d0]{width:.5rem;height:.5rem;border-radius:50%;overflow:hidden;margin-right:.13rem}.periodExchange[data-v-e2dff0d0] .van-cell{padding:.26rem .16rem .88rem}.periodExchange .exchangeText[data-v-e2dff0d0]{font-size:.18rem;color:#1a1a1a}.periodExchange .info[data-v-e2dff0d0]{font-size:.16rem;color:grey}.pay_btn[data-v-e2dff0d0]{background:#14928a;line-height:.45rem;color:#fff;font-size:.18rem;border-radius:.5rem;text-align:center;position:absolute;width:90%;margin-left:5%;bottom:.2rem}

+ 1 - 0
dist/css/PeriodRecord.74104831.css

@@ -0,0 +1 @@
+.mheader[data-v-61d0e2e4]{height:.44rem;overflow:hidden}.m-nav-header[data-v-61d0e2e4]{position:absolute;left:0;top:0;width:100%;height:.44rem;line-height:.44rem;background-color:#14928a;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;color:#fff}.m-nav-header.fixed[data-v-61d0e2e4]{position:fixed;z-index:99}.m-nav-header .m-nav-bar__title[data-v-61d0e2e4]{max-width:60%;margin:0 auto;color:#fff;font-weight:500;font-size:.16rem}.m-nav-header .m-nav-bar__left[data-v-61d0e2e4],.m-nav-header .m-nav-bar__right[data-v-61d0e2e4]{position:absolute;bottom:0}.m-nav-header .m-nav-bar__left[data-v-61d0e2e4]{left:.12rem}.m-nav-header .m-nav-bar__left .arrow-left[data-v-61d0e2e4]{font-size:.21rem;vertical-align:middle}.m-nav-header .m-nav-bar__right[data-v-61d0e2e4]{right:.12rem}.icon[data-v-67669af7]{width:2rem;height:2rem;margin:.5rem auto .05rem}.icon_nodata[data-v-67669af7]{background:url(../img/icon_nodata.81c87d57.png) no-repeat 50%;background-size:contain}.msg[data-v-67669af7]{color:#aaa;font-size:.16rem;text-align:center;line-height:.22rem}.periodExchange[data-v-3e01d768]{min-height:100vh}.periodExchange .exchangeText[data-v-3e01d768]{font-size:.17rem;color:#1a1a1a;line-height:.24rem}.periodExchange .exchangeText.enum[data-v-3e01d768]{color:#ff5050}.periodExchange .info[data-v-3e01d768]{font-size:.14rem;color:grey}

文件差异内容过多而无法显示
+ 0 - 0
dist/css/chunk-vendors.736d3854.css


文件差异内容过多而无法显示
+ 0 - 0
dist/css/chunk-vendors.96e82baf.css


二进制
dist/img/icon_teacher.de517191.png


文件差异内容过多而无法显示
+ 0 - 0
dist/index.html


文件差异内容过多而无法显示
+ 0 - 0
dist/js/Account.8e881ff9.js


文件差异内容过多而无法显示
+ 0 - 0
dist/js/Account~Approval~Attendance~CallNames~CourseApply~ExchangeRecord~IStarted~Leave~PeriodAdjust~PeriodC~bed631d0.1e8062e4.js


文件差异内容过多而无法显示
+ 0 - 0
dist/js/Approval.08cf098b.js


文件差异内容过多而无法显示
+ 0 - 0
dist/js/Approval.df86ba16.js


文件差异内容过多而无法显示
+ 0 - 0
dist/js/Approval~Attendance~CallNames~IStarted~Leave~PeriodAdjust~PeriodChange~TeachingSchool~TeachingSet~VI~0d4456f6.8d78c334.js


文件差异内容过多而无法显示
+ 0 - 0
dist/js/Attendance.6dbaa6d7.js


文件差异内容过多而无法显示
+ 0 - 0
dist/js/Attendance.f24b6884.js


+ 0 - 0
dist/js/BookingSet.6b9c54a8.js → dist/js/BookingSet.d617bf6f.js


+ 0 - 0
dist/js/Business.3372f5e4.js → dist/js/Business.83056cc1.js


文件差异内容过多而无法显示
+ 0 - 0
dist/js/CallNames.6fbf6c4d.js


文件差异内容过多而无法显示
+ 0 - 0
dist/js/CallNames.888f73bf.js


+ 0 - 0
dist/js/CcMe.394544d6.js → dist/js/CcMe.ebb8c1f7.js


文件差异内容过多而无法显示
+ 0 - 0
dist/js/CourseApply.fb7375f0.js


文件差异内容过多而无法显示
+ 0 - 0
dist/js/ExchangeRecord.c7ba1bb7.js


文件差异内容过多而无法显示
+ 0 - 0
dist/js/IStarted.57ad01d2.js


文件差异内容过多而无法显示
+ 0 - 0
dist/js/IStarted.aebd6840.js


文件差异内容过多而无法显示
+ 0 - 0
dist/js/Leave.0a7271b2.js


文件差异内容过多而无法显示
+ 0 - 0
dist/js/Leave.6d687860.js


+ 0 - 0
dist/js/PeriodAdjust.6d4c77ab.js → dist/js/PeriodAdjust.2c1731c1.js


文件差异内容过多而无法显示
+ 0 - 0
dist/js/PeriodAdjust~PeriodChange.6b7f9168.js


文件差异内容过多而无法显示
+ 0 - 0
dist/js/PeriodAdjust~PeriodChange.c4c05fdd.js


+ 0 - 0
dist/js/PeriodChange.122cd9a5.js → dist/js/PeriodChange.e9399e06.js


文件差异内容过多而无法显示
+ 0 - 0
dist/js/PeriodExchange.ca2c75e7.js


文件差异内容过多而无法显示
+ 0 - 0
dist/js/PeriodRecord.aa0bcc99.js


+ 0 - 0
dist/js/StartedDetail.00237b08.js → dist/js/StartedDetail.d61ed066.js


文件差异内容过多而无法显示
+ 0 - 0
dist/js/TeachingSchool.660d1b6f.js


文件差异内容过多而无法显示
+ 0 - 0
dist/js/TeachingSchool.a3bb12b8.js


文件差异内容过多而无法显示
+ 0 - 0
dist/js/TeachingSet.5d8fe527.js


文件差异内容过多而无法显示
+ 0 - 0
dist/js/TeachingSet.f7b28d17.js


文件差异内容过多而无法显示
+ 0 - 0
dist/js/VIPApply.2eff2436.js


文件差异内容过多而无法显示
+ 0 - 0
dist/js/app.99079cfb.js


文件差异内容过多而无法显示
+ 0 - 0
dist/js/app.c5866dbd.js


文件差异内容过多而无法显示
+ 0 - 0
dist/js/chunk-vendors.159b9db5.js


文件差异内容过多而无法显示
+ 0 - 0
dist/js/chunk-vendors.4c5b1713.js


文件差异内容过多而无法显示
+ 0 - 0
dist/js/order.15fbdbfb.js


文件差异内容过多而无法显示
+ 0 - 0
dist/js/order.f7045d59.js


文件差异内容过多而无法显示
+ 0 - 0
dist/js/privacy.d0732084.js


+ 9 - 9
package-lock.json

@@ -988,9 +988,9 @@
       "dev": true
     },
     "@vant/icons": {
-      "version": "1.1.13",
-      "resolved": "https://registry.npm.taobao.org/@vant/icons/download/@vant/icons-1.1.13.tgz",
-      "integrity": "sha1-6ncpj08rGczHYQBQaKLHQ2CY5NQ="
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/@vant/icons/-/icons-1.2.1.tgz",
+      "integrity": "sha512-5ivsKQR4ySbdBW5UPoQDVqO6rdc1um3rvq/0VL+ZSA7Y3MdBQ3E4/NL0hoAY5/sZZeYfIDKEP21gpjUzdeEDQQ=="
     },
     "@vue/babel-helper-vue-jsx-merge-props": {
       "version": "1.0.0",
@@ -11049,12 +11049,12 @@
       }
     },
     "vant": {
-      "version": "2.1.4",
-      "resolved": "https://registry.npm.taobao.org/vant/download/vant-2.1.4.tgz",
-      "integrity": "sha1-qT51iPVhdQkbefLr2k4tinfkdvc=",
+      "version": "2.5.4",
+      "resolved": "https://registry.npmjs.org/vant/-/vant-2.5.4.tgz",
+      "integrity": "sha512-eIeXrzsEP5cNbMkskFwxu3i6kkzS2pR7/fF0pFoTXhl/oYRdkXUt46RnRQtazz/BNHVBf2j3dVnwLTIBPRGstQ==",
       "requires": {
         "@babel/runtime": "7.x",
-        "@vant/icons": "1.1.13",
+        "@vant/icons": "1.2.1",
         "@vue/babel-helper-vue-jsx-merge-props": "^1.0.0",
         "vue-lazyload": "1.2.3"
       }
@@ -11167,8 +11167,8 @@
     },
     "vue-lazyload": {
       "version": "1.2.3",
-      "resolved": "https://registry.npm.taobao.org/vue-lazyload/download/vue-lazyload-1.2.3.tgz",
-      "integrity": "sha1-kB+ewVx+bKeHgaK65KNDaGve2yw="
+      "resolved": "https://registry.npmjs.org/vue-lazyload/-/vue-lazyload-1.2.3.tgz",
+      "integrity": "sha512-DC0ZwxanbRhx79tlA3zY5OYJkH8FYp3WBAnAJbrcuoS8eye1P73rcgAZhyxFSPUluJUTelMB+i/+VkNU/qVm7g=="
     },
     "vue-loader": {
       "version": "15.7.1",

+ 1 - 1
package.json

@@ -12,7 +12,7 @@
     "core-js": "^2.6.5",
     "install": "^0.13.0",
     "qs": "^6.8.0",
-    "vant": "^2.1.4",
+    "vant": "^2.5.4",
     "vconsole": "^3.3.4",
     "vue": "^2.6.10",
     "vue-amap": "^0.5.10",

+ 35 - 0
src/api/app.js

@@ -0,0 +1,35 @@
+const axios = require('@/common/axios').default
+import qs from 'qs'
+// import axios from '@/common/axios'
+const api = '/api-teacher'
+
+// 创建课程
+const createCourseGroup = (data) => {
+  return axios({
+    url: api + '/courseGroup/createCourseGroup',
+    method: 'post',
+    data: data
+  })
+}
+
+const sysTenantAccountGet = (data) => {
+  return axios({
+    url: api + '/sysTenantAccount/get',
+    method: 'get',
+    params: data
+  })
+}
+
+const queryTenantAccountDetail = (data) => {
+  return axios({
+    url: api + '/sysTenantAccount/queryTenantAccountDetail',
+    method: 'get',
+    params: data
+  })
+}
+
+export {
+    createCourseGroup,
+    sysTenantAccountGet,
+    queryTenantAccountDetail
+}

二进制
src/assets/images/app/icon_lock.png


二进制
src/assets/images/app/icon_times.png


二进制
src/assets/images/app/plus-square-o.png


二进制
src/assets/images/icon_teacher.png


+ 48 - 0
src/router/appRouter.js

@@ -0,0 +1,48 @@
+let teacherRouter = [{
+    path: "/courseApply",
+    name: "courseApply",
+    component: () =>
+      import( /* webpackChunkName:'CourseApply'*/ "@/views/app/CourseApply.vue"),
+    meta: {
+      descrition: "课程创建",
+      weight: 1 // 页面权重
+    }
+  }, {
+    path: "/account",
+    name: "account",
+    component: () =>
+      import( /* webpackChunkName:'Account'*/ "@/views/app/Account.vue"),
+    meta: {
+      descrition: "我的账户",
+      weight: 1 // 页面权重
+    }
+  }, {
+    path: "/periodRecord",
+    name: "periodRecord",
+    component: () =>
+      import( /* webpackChunkName:'PeriodRecord'*/ "@/views/app/PeriodRecord.vue"),
+    meta: {
+      descrition: "课时使用记录",
+      weight: 2 // 页面权重
+    }
+  }, {
+    path: "/exchangeRecord",
+    name: "exchangeRecord",
+    component: () =>
+      import( /* webpackChunkName:'ExchangeRecord'*/ "@/views/app/ExchangeRecord.vue"),
+    meta: {
+      descrition: "兑换记录",
+      weight: 2 // 页面权重
+    }
+  }, {
+    path: "/periodExchange",
+    name: "periodExchange",
+    component: () =>
+      import( /* webpackChunkName:'PeriodExchange'*/ "@/views/app/PeriodExchange.vue"),
+    meta: {
+      descrition: "课时兑换",
+      weight: 2 // 页面权重
+    }
+  }, 
+];
+export default teacherRouter;

+ 2 - 0
src/router/index.js

@@ -1,6 +1,7 @@
 import Vue from 'vue'
 import Router from 'vue-router'
 import TeacherRouter from './teacherRouter'
+import AppRouter from './appRouter'
 
 
 Vue.use(Router)
@@ -31,6 +32,7 @@ let defaultRouter = [
 ]
 
 defaultRouter = defaultRouter.concat(TeacherRouter)
+                             .concat(AppRouter)
 
 const router = new Router({
   // mode: 'history',

+ 141 - 0
src/views/app/Account.vue

@@ -0,0 +1,141 @@
+<template>
+    <div class="account">
+        <m-header v-if="headerStatus" />
+
+        <div class="accountHeader">
+            <div class="bgColor"></div>
+            <van-row class="content" type="flex" justify="center" align="center">
+                <van-col span="12">
+                    <i class="icon icon_times"></i>剩余课时<span>{{ availableMinutes }}</span>
+                </van-col>
+                <van-col span="12">
+                    <i class="icon icon_lock"></i>冻结时间<span class="lock">{{ frozenMinutes }}</span>
+                </van-col>
+            </van-row>
+        </div>
+
+        <van-cell-group>
+            <van-cell title="课时兑换" is-link to="periodExchange" />
+            <van-cell title="兑换记录" is-link to="exchangeRecord" />
+            <van-cell title="课时使用记录" is-link to="periodRecord" />
+        </van-cell-group>
+
+    </div>
+</template>
+<script>
+/* eslint-disable */
+import MHeader from '@/components/MHeader'
+import { browser }  from '@/common/common'
+import { sysTenantAccountGet } from '@/api/app'
+export default {
+    name: 'courseApply',
+    components: { MHeader },
+    data() {
+        return {
+            headerStatus: true,
+            availableMinutes: 0,
+            frozenMinutes: 0
+        }
+    },
+    mounted() {
+        let params = this.$route.query
+        if(params.Authorization) {
+            localStorage.setItem('Authorization', decodeURI(params.Authorization))
+            localStorage.setItem('userInfo', decodeURI(params.Authorization))
+        }
+        
+        document.title = '我的账户'
+        if(browser().android || browser().iPhone) {
+            this.headerStatus = false
+        }
+
+        this.__init()
+    },
+    methods: {
+        __init() {
+            sysTenantAccountGet().then(res => {
+                let result = res.data
+                if(result.code == 200) {
+                    let tempResult = result.data
+                    if(tempResult) {
+                        this.availableMinutes = tempResult.availableMinutes ? tempResult.availableMinutes : 0
+                        this.frozenMinutes = tempResult.frozenMinutes ? tempResult.frozenMinutes : 0
+                    }
+                } else {
+                    this.$toast(result.msg)
+                }
+            })
+        }
+    }
+}
+</script>
+<style lang='less' scoped>
+@import url("../../assets/commonLess/variable.less");
+.account {
+    min-height: 100vh;
+}
+
+.accountHeader {
+    background: #fff;
+    padding-bottom: .2rem;
+    .bgColor {
+        margin-top: -1px;   
+        height: .9rem;
+        background: #14928A;
+    }
+    .content {
+        height:74px;
+        background: rgba(255,255,255,1);
+        box-shadow: 0px 0px 16px 0px rgba(0,0,0,0.19);
+        border-radius: .08rem;
+        margin: -.5rem .16rem 0;
+        text-align: center;
+        .van-col {
+            color: #1A1A1A;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            &:first-child {
+                border-right: 1px solid #CCCCCC;
+            }
+            span {
+                padding-left: .1rem;
+                color: #FF0909;
+                &.lock {
+                    color: #999999;
+                }
+            }
+        }
+        .icon {
+            display: inline-block;
+            width: .16rem;
+            height: .18rem;
+            margin-right: .05rem;
+        }
+        .icon_times {
+            background: url('../../assets/images/app/icon_times.png') no-repeat center center;
+            background-size: contain;
+        }
+        .icon_lock {
+            background: url('../../assets/images/app/icon_lock.png') no-repeat center center;
+            background-size: contain;
+        }
+    }
+}
+
+/deep/.van-cell-group {
+    &::after {
+        border-width: 0;;
+    }
+    /deep/.van-cell {
+        padding: .16rem;
+    }
+}
+
+/deep/.van-cell__title {
+    flex: 1 auto;
+    font-size: .16rem;
+    color: #1A1A1A;
+}
+
+</style>

+ 710 - 0
src/views/app/CourseApply.vue

@@ -0,0 +1,710 @@
+<template>
+    <div class="courseApply">
+        <m-header v-if="statusList.headerStatus" />
+        <van-cell-group>
+            <van-field v-model="form.name" label="课程班名称" input-align="right" size="large" 
+                placeholder="请输入班级名称" />
+            <van-field v-model="formName.subjectListName" @click="onGetSheetList('subjectList')" 
+                label="科目名称" :readonly="true" input-align="right" is-link size="large" placeholder="请选择" />
+        </van-cell-group>
+        <van-cell-group>
+            <van-field v-model="form.studentNum" label="每班人数" :readonly="true" input-align="right" size="large" is-link placeholder="每班预计招收人数" @click="statusList.studentNumStatus = true" />
+            <van-field v-model="form.singleClassMinutes" @click="onClickSingleClass" label="每课时长"  :readonly="true" input-align="right" is-link size="large" placeholder="请输入每课时长" />
+        </van-cell-group>
+        <van-cell-group>
+            <van-field v-model="form.courseCount" label="排课数量" input-align="right" size="large" placeholder="请输入排课数量" type="digit" @input="onCourseChange" />
+            <van-field @click="dataForm.status = true" v-model="form.courseStart" label="排课开始时间" :readonly="true" input-align="right" is-link size="large" placeholder="请选择" />
+
+            <van-cell title-class="title-time" v-for="(item, index) in scheduleList" :key="index">
+                <template slot="title">
+                    <span class="week">{{ item.weekStr }}</span>
+                    <span class="timer">{{ item.startTime + '-' + item.endTime }}</span>
+                </template>
+                <template slot="default">
+                    <van-button type="warning" @click="onScheduleRemove(item)" round size="small" plain >删除</van-button>
+                </template>
+            </van-cell>
+            <div class="add-plan van-cell" @click="onCourseShedule">
+                <p><van-icon name="add-o" />请设置循环周期/每周</p>
+                <!-- <p style="color: #999; font-size: .14rem">请选择开课周期/上课时间点</p> -->
+            </div>
+            <van-field label="排课列表" v-if="scheduleList.length > 0" 
+                disabled input-align="right" @click="onShowTimeTable" is-link size="large" />
+        </van-cell-group>
+
+        <van-cell-group>
+            <van-field v-model="consumePeriodText" label="预计消耗课时" disabled input-align="right" size="large" placeholder="预计消耗课时" />
+            <van-field v-model="usePeriodText" label="剩余可用课时" input-align="right" disabled size="large" placeholder="剩余可用课时" />
+        </van-cell-group>
+
+        <!-- <div class="agreeProtocol">
+            <van-checkbox v-model="statusList.agreeStatus"></van-checkbox>
+            <i style="font-style: normal;" @click="statusList.agreeStatus = !statusList.agreeStatus">已阅读并同意</i> <span>《课程创建协议》</span>
+        </div> -->
+
+        <div class="button-group">
+            <van-button type="primary" @click="onSubmit" round size="large">确认</van-button>
+        </div>
+
+        <!-- 每班人数 -->
+        <van-action-sheet v-model="statusList.studentNumStatus" :round="false" :actions="loadData.studentNumList" cancel-text="取消"  @cancel="statusList.studentNumStatus = false" @select="onStudentSelect" />
+        <!-- 每课时长 -->
+        <van-popup v-model="statusList.classTimerStatus" position="bottom">
+            <van-picker :columns="loadData.classTimer" show-toolbar @cancel="statusList.classTimerStatus = false" @confirm="onClassTimerSelect" />
+        </van-popup>
+
+        <!-- 课程信息所用 :close-on-click-overlay="false"  -->
+        <van-popup v-model="sheetForm.sheetStatus" position="bottom">
+            <van-picker :loading="sheetForm.loading" :default-index="sheetForm.index" :columns="sheetForm.columns" 
+                show-toolbar @cancel="sheetForm.sheetStatus = false" @confirm="onSheetConfirm" />
+        </van-popup>
+        <!-- 课时安排 -->
+        <van-popup v-model="dataForm.status" position="bottom">
+            <van-datetime-picker v-model="dataForm.currentDate" type="date" :min-date="dataForm.minDate" 
+                :max-date="dataForm.maxDate" :formatter="formatter" @cancel="dataForm.status = false" 
+                @confirm="onCurrentConfirm" />
+        </van-popup>
+        <!-- 课时安排 -->
+        <van-popup v-model="courseForm.teachingStatus" position="bottom">
+            <van-picker :columns="courseForm.columns" show-toolbar @cancel="courseForm.teachingStatus = false" @confirm="onTeachinConfirm" />
+        </van-popup>
+        <!-- 课表展示 -->
+        <van-popup v-model="statusList.classTime" position="bottom">
+            <van-row>
+                <!-- <van-col span="12">上课类型</van-col> -->
+                <van-col span="24">上课时间</van-col>
+            </van-row>
+            <div class="tableContainer">
+                <van-row v-for="(item, index) in timeTable" :key="index">
+                    <!-- <van-col span="12">线上</van-col> -->
+                    <van-col span="24">
+                        {{ item.classDate }} {{ item.startClassTimeStr }}
+                    </van-col>
+                </van-row>
+            </div>
+        </van-popup>
+    </div>
+</template>
+<script>
+/* eslint-disable */
+import MHeader from '@/components/MHeader'
+import { browser }  from '@/common/common'
+import { findSubSubjects } from '@/api/teacher'
+import { createCourseGroup, sysTenantAccountGet } from '@/api/app'
+let minutes = []  // 分钟数
+for(let i = 0; i < 60; i++) {
+    let mi = i < 10 ? '0' + i : i
+    minutes.push(mi + '分')
+}
+export default {
+    name: 'courseApply',
+    components: { MHeader },
+    data() {
+        return {
+            dataForm: { // 时间下拉框
+                status: false,
+                minDate: new Date(),
+                maxDate: new Date(2025, 10, 1),
+                currentDate: new Date()
+            },
+            statusList: { // 散状态集合
+                classTime: false, // 课表展示
+                headerStatus: true, // 头部是否展示
+                studentNumStatus: false, // 每班人数
+                classTimerStatus: false, // 每课时长状态
+                agreeStatus: false // 协议状态
+            },
+            loadData: { // 下拉加载数据
+                subjectList: [], // 声部列表
+                subjectListSelect: [], // 选中的声部JSON
+                classTimer: [{
+                    values: [15, 30, 45, 60, 75, 90, 105, 120],
+                    className: 'classTimer'
+                }], // 每课时长
+                studentNumList: [{ name: 1, subname: '(人)'},{ name: 2, subname: '(人)'},{ name: 3, subname: '(人)'},{ name: 4, subname: '(人)'},{ name: 5, subname: '(人)'}]
+            },
+            sheetForm: { // 上拉弹窗
+                currentType: null, // 当前选择的类型
+                sheetStatus: false,
+                loading: true, // 加载数据
+                index: 0, // 选中的索引值
+                columns: []
+            },
+            courseForm: { // 排课弹窗
+                teachingStatus: false, // 课时安排状态
+                columns: [{
+                    values: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
+                    className: 'week'
+                }, {
+                    values: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23],
+                    className: 'hours',
+                    defaultIndex: 7
+                }, {
+                    values: minutes,
+                    className: 'minutes'
+                }]
+            },
+            form: {
+                name: null,
+                subjectIdList: null,
+                studentNum: null,
+                singleClassMinutes: null,
+                courseCount: null,
+                courseStart: null,
+                giveTeachMode: null
+            },
+            formName: {
+                subjectListName: null, // 声部名称
+                subjectListIndex: 0, // 声部名称
+            },
+            scheduleList: [], // 课时安排
+            timeTable: [], // 生成的课表
+            onSubmitStatus: true, // 点击
+            consumePeriod: 0, // 消耗课时
+            consumePeriodText: '0小时',
+            usePeriod: 0, // 可用课时
+            usePeriodText: '0分钟',
+        }
+    },
+    mounted() {
+        let params = this.$route.query
+        if(params.Authorization) {
+            localStorage.setItem('Authorization', decodeURI(params.Authorization))
+            localStorage.setItem('userInfo', decodeURI(params.Authorization))
+        }
+        
+        document.title = '课程创建'
+        if(browser().android || browser().iPhone) {
+            this.headerStatus = false
+        }
+
+        sysTenantAccountGet().then(res => {
+            let result = res.data
+            if(result.code == 200) {
+                let tempResult = result.data
+                if(tempResult) {
+                    this.usePeriod = tempResult.availableMinutes ? tempResult.availableMinutes : 0
+                    this.usePeriodText = this.usePeriod + '分钟'
+                }
+            } else {
+                this.$toast(result.msg)
+            }
+        })
+    },
+    methods: {
+        onGetSheetList(name) { // 获取科目列表
+            let sheetForm = this.sheetForm
+            sheetForm.sheetStatus = true
+            sheetForm.loading = true
+            sheetForm.currentType = name
+            sheetForm.index = 0
+            let arr = this.loadData[name]
+            if(arr.length > 0) {
+                sheetForm.columns = arr
+                sheetForm.index = this.formName[name + 'Index']
+                sheetForm.loading = false
+            } else {
+                this.onLoadingData(name)
+            }
+            
+        },
+        onLoadingData() { // 加载数据
+            let sheetForm = this.sheetForm
+            if(sheetForm.currentType == 'subjectList') { // 声部列表
+                findSubSubjects().then(res => {
+                    let result = res.data
+                    if(result.code == 200 && result.data.length > 0) {
+                        let tempArr = []
+                        result.data.forEach(item => {
+                            item.value = item.id
+                            item.text = item.name
+                            tempArr.push(item)
+                        })
+                        this.loadData.subjectList = tempArr
+                        sheetForm.columns = tempArr
+                        sheetForm.loading = false
+                    } else {
+                        this.$toast('暂无科目列表')
+                        sheetForm.loading = false
+                    }
+                })
+            }
+        },
+        onSheetConfirm(value, index) { // 上拉弹窗
+            let sheetForm = this.sheetForm,
+                form = this.form,
+                formName = this.formName,
+                loadData = this.loadData
+            if(!value) {
+                return
+            }
+            if(sheetForm.currentType == 'subjectList') { // 科目名称赋值
+                form.subjectIdList = value.value
+                formName.subjectListName = value.text
+                formName.subjectListIndex = index
+                loadData.subjectListSelect = value
+            }
+            sheetForm.sheetStatus = false
+        },
+        onClickSingleClass() {
+            this.statusList.classTimerStatus = true
+        },
+        onCourseChange() {
+            // 计算消耗课时
+            this.calcTimer()
+            this.scheduleList = []
+            this.timeTable = []
+            // 重新生成课表
+            this.setTimeTable()
+
+        },
+        onClassTimerSelect(value) { // 每课时长设置
+            // 判断两次选的时间是否一致
+            if(this.form.singleClassMinutes == value[0]) {
+                return
+            }
+            this.form.singleClassMinutes = value[0]
+            this.statusList.classTimerStatus = false
+            // 计算消耗课时
+            this.calcTimer()
+
+            // 重置课表和课时安排
+            this.scheduleList = [] // 课时安排
+            this.timeTable = [] // 生成的课表
+        },
+        onStudentSelect(value) { // 每班人数
+            this.form.studentNum = value.name
+            this.statusList.studentNumStatus = false
+        },
+        onCurrentConfirm(value) { // 排课开始时间
+            let selectDate = new Date(value)
+            let tempMonth = selectDate.getMonth() + 1 >= 10 ? selectDate.getMonth() + 1 : '0' + (selectDate.getMonth() + 1)
+            let tempDay = selectDate.getDate() >= 10 ? selectDate.getDate() : '0' + selectDate.getDate()
+            this.form.courseStart = selectDate.getFullYear() + '-' + tempMonth + '-' + tempDay
+            this.dataForm.status = false
+        },
+        onCourseShedule() { // 课时安排
+            if(!this.form.singleClassMinutes) {
+                this.$toast('请选择每课时长')
+                return
+            }
+            if(!this.form.courseCount) {
+                this.$toast('请选择排课数')
+                return
+            }
+            if(!this.form.courseStart) {
+                this.$toast('请选择排课开始时间')
+                return
+            }
+            if(this.scheduleList.length >= this.form.courseCount) {
+                this.$toast('循环周期次数不能大于排课数量')
+                return
+            }
+
+            this.courseForm.teachingStatus = true
+        },
+        onScheduleRemove(item) { // 删除课程安排
+            let index = this.scheduleList.indexOf(item)
+            if(index !== -1) {
+                this.scheduleList.splice(index, 1)
+            }
+        },
+        onTeachinConfirm(value) { // 添加课程
+            let scheduleList = this.scheduleList
+            let startTime = (value[1] >= 10 ? value[1] : '0' + value[1]) + ':' + value[2].split('分')[0]
+            let endTime = this.MinutesTest(value[1], value[2], this.form.singleClassMinutes)
+
+            let isAdd = true
+            scheduleList.forEach(item => {
+                let isStartTime = this.timeIsrange(startTime, endTime, item.startTime);
+                let isEndTime = this.timeIsrange(startTime, endTime, item.endTime);
+                if(isAdd) { // 
+                   if(value[0] == item.weekStr) {
+                        if(isStartTime || isEndTime) {
+                            isAdd = false
+                        } else {
+                            isAdd = true
+                        }
+                    } else if(value[0] != item.weekStr) {
+                        isAdd = true
+                    } 
+                }
+            })
+
+            if(isAdd) { // 判断时间范围是否有重复
+                scheduleList.push({
+                    weekStr: value[0],
+                    weekIndex: this.getWeek(value[0]),
+                    startTime: startTime,
+                    endTime: endTime,
+                    id: Date.now()
+                })
+
+                this.courseForm.teachingStatus = false
+
+                // this.setTimeTable()
+            } else {
+                this.$toast('该时间段已排课请重选时间')
+                return
+            }
+        },
+        calcTimer() { // 计算课时
+            let form = this.form
+            // ...
+            if(!form.singleClassMinutes || !form.courseCount) {
+                return
+            }
+            let countMinutes = form.singleClassMinutes * form.courseCount
+            this.consumePeriod = countMinutes
+            this.consumePeriodText = (countMinutes) + '分钟'
+        },
+        onShowTimeTable() { // 显示排课列表
+            this.statusList.classTime = true
+            this.setTimeTable()
+        },
+        setTimeTable () {
+            // 重置排课列表
+            this.timeTable = []
+
+            let form = this.form,
+                scheduleList = this.scheduleList
+            // 判断是否有课程安排
+            if (scheduleList.length <= 0) {
+                return
+            }
+            // debugger
+            let totalCount = this.form.courseCount
+            let tempCourseStart = form.courseStart.replace(/-/ig, '/')
+            let dateOperation  = new Date(tempCourseStart)
+            let forMark = 0
+            while(totalCount && totalCount > 0) {
+                for(let i = 0; i < scheduleList.length; i++) {
+                    let num = scheduleList[i].weekIndex - dateOperation.getDay()
+                    if(forMark > 0 && num == 0 && i == 0) {
+                        num = num + 7
+                    }
+                    if(num < 0) { // 如果为负数则为下周
+                        num = num + 7
+                    } 
+                    let dataStr = this.getThinkDate(dateOperation, num)
+
+                    // 判断是否大于当前时间
+                    let nowGetTime = new Date().getTime()
+                    let courseTime = new Date(dataStr.replace(/-/ig, '/') + ' ' + scheduleList[i].startTime + ':00').getTime()
+                    if(nowGetTime < courseTime) {
+                        let tempArr = {
+                            'classDate': dataStr,
+                            'startClassTimeStr': scheduleList[i].startTime,
+                            "endClassTimeStr": scheduleList[i].endTime
+                        }
+                        this.timeTable.push(tempArr)
+                    }
+                    totalCount--
+                    if(totalCount <= 0) {
+                        return
+                    }
+                }
+                // 加一周
+                if(scheduleList.length == 1) {
+                    dateOperation.setDate(dateOperation.getDate() + 7)
+                } else if(scheduleList.every( item => item.weekStr === scheduleList[0].weekStr)) {
+                    // 标记循环次数(标记判断课程安排是不是同一天)
+                    forMark++
+                }
+            }
+        },
+        getThinkDate (date, num) {
+            let Stamp = date
+            Stamp.setDate(date.getDate() + num) // 获取当前月数的第几天
+            var year = Stamp.getFullYear(); //获取完整的年份(4位,1970-????)
+            var month = Stamp.getMonth() + 1; //获取当前月份(0-11,0代表1月)
+            var mvar = '';
+            if (month < 10) {
+                mvar = '0' + month;
+            } else {
+                mvar = month + '';
+            }
+            var day = Stamp.getDate();
+            var dvar = '';
+            if (day < 10) {
+                dvar = '0' + day;
+            } else {
+                dvar = day + '';
+            }
+            return year + "-" + mvar + '-' + dvar;
+        },
+        // 分钟小时相加减
+        MinutesTest (houer, mins, interval) {
+            let min = mins.split('分')[0]
+            let sdate1 = new Date(1900, 1, 1, houer, min)
+            sdate1.setMinutes(sdate1.getMinutes() + parseInt(interval))
+            let H = sdate1.getHours()
+            let M = sdate1.getMinutes()
+            if (H < 10) H = '0' + H
+            if (M < 10) M = '0' + M
+            return H + ':' + M
+        },
+        // 判断时间是否在时间段内
+        timeIsrange (beginTime, endTime, nowTime) {
+            var strb = beginTime.split(":");
+            if (strb.length != 2) {
+                return false;
+            }
+            var stre = endTime.split(":");
+            if (stre.length != 2) {
+                return false;
+            }
+            var strn = nowTime.split(":");
+            if (stre.length != 2) {
+                return false;
+            }
+            var b = new Date();
+            var e = new Date();
+            var n = new Date();
+            b.setHours(strb[0]);
+            b.setMinutes(strb[1]);
+            e.setHours(stre[0]);
+            e.setMinutes(stre[1]);
+            n.setHours(strn[0]);
+            n.setMinutes(strn[1]);
+
+            if (n.getTime() - b.getTime() >= 0 && n.getTime() - e.getTime() <= 0) {
+                // 在时间范围内
+                return true
+            } else {
+                // 不在时间范围内
+                return false
+            }
+        },
+        getWeek(str) { // 获取周几索引值
+            let template = {
+                '周一': 1,
+                '周二': 2,
+                '周三': 3,
+                '周四': 4,
+                '周五': 5,
+                '周六': 6,
+                '周日': 0
+            }
+            return template[str]
+        },
+        formatter(type, value) {
+            if (type === 'year') {
+                return `${value}年`;
+            } else if (type === 'month') {
+                return `${value}月`
+            } else if (type === 'day') {
+                return `${value}日`
+            }
+            return value;
+        },
+        onSubmit() {
+            let form = this.form
+            let statusList = this.statusList
+            // 排课
+            this.setTimeTable()
+
+            if(!(form.name)) {
+                this.$toast('请输入课程班名称')
+                return false
+            }
+            if(!form.subjectIdList) {
+                this.$toast('请选择科目')
+                return false
+            }
+            
+            if(!form.singleClassMinutes) {
+                this.$toast('请选择每课时长')
+                return false
+            }
+
+            if(this.scheduleList.length <= 0) {
+                this.$toast('课时安排不能为空')
+                return false
+            }
+
+            let courseTime = []
+            this.scheduleList.forEach(item => {
+                courseTime.push({
+                    dayOfWeek: item.weekIndex == 0 ? 7 : item.weekIndex,
+                    startClassTime: item.startTime + ':00'
+                })
+            })
+
+            // 判断剩余时长是否足够
+            if(this.consumePeriod > this.usePeriod) {
+                this.$dialog.confirm({
+                    message: '剩余可用时间不足,是否充值?',
+                    confirmButtonText: '去充值'
+                }).then(() => {
+                    // 跳转充值页面
+                    this.$router.push('/periodExchange')
+                }).catch(() => {
+                    // on cancel
+                })
+                return
+            }
+
+            let params = {
+                coursesGroup: {
+                    name: form.name,
+                    subjectId: form.subjectIdList,
+                    maxStudentNum: form.studentNum
+                },
+                courseCycleInfo: {
+                    courseCreateStartTime: form.courseStart,
+                    teachMode: 'ONLINE',
+                    courseCount: Number(form.courseCount),
+                    singleClassMinutes: form.singleClassMinutes,
+                    courseTimes: courseTime
+                }
+            }
+            if(!this.onSubmitStatus) {
+                return
+            }
+            this.onSubmitStatus = false
+            this.$dialog.confirm({
+                title: '确认创建',
+                message: '是否确认创建课程组'
+            }).then(() => {
+                createCourseGroup(params).then(res => {
+                    let result =res.data
+                    if(result.code == 200) {
+                        this.$toast('申请成功')
+                        setTimeout(() => {
+                            this.onSubmitStatus = true
+                            if(browser().iPhone) {
+                                window.webkit.messageHandlers.DAYA.postMessage(JSON.stringify({api: 'back'}))
+                            } else if(browser().android) {
+                                DAYA.postMessage(JSON.stringify({api: 'back'}))
+                            }
+                            //  else {
+                            //     this.$router.push('/business')
+                            // }
+                        }, 500)
+                    } else {
+                        this.onSubmitStatus = true
+                        this.$toast(result.msg)
+                    }
+                })
+            }).catch(() => {
+                // on cancel
+            })
+            
+        }
+    }
+}
+</script>
+<style lang='less' scoped>
+@import url("../../assets/commonLess/variable.less");
+.courseApply {
+    min-height: 100vh;
+}
+.vip-title {
+    padding: .06rem 0 .04rem;
+    font-size: .12rem;
+    color: @mFontColor;
+    text-align: center;
+}
+
+.add-plan {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    padding: .2rem 0;
+    font-size: .16rem;
+    color: @tFontColor;
+    .van-icon {
+        margin-right: .05rem;
+        font-size: .20rem;
+    }
+    p {
+        display: flex;
+        align-items: center;
+    }
+}
+
+.title-time {
+    display: flex;
+    align-items: center;
+    flex: 1 auto;
+    color: #4A4A4A;
+    .online {
+        color: @tFontColor;
+    }
+    .week {
+        padding-right: .15rem;
+    }
+}
+/deep/.van-cell-group {
+    margin-bottom: .15rem;
+}
+
+/deep/.van-field__label, /deep/.van-cell__value {
+    flex: 1 auto;
+    font-size: .16rem;
+}
+/deep/.van-field__control {
+    &:disabled {
+        color: #6a6969;
+    }
+}
+
+.button-group {
+    margin: .2rem .26rem;
+    .van-button--primary {
+        background: @mColor;
+        font-size: .18rem;
+    }
+}
+
+.van-row {
+    line-height: .4rem;
+    border-top: 1px solid #edeef0;
+    text-align: center;
+    font-size: .14rem;
+    &:first-child {
+        border-top: 0;
+        background: #edeef0;
+        color: #444;
+        font-size: .15rem;
+    }
+}
+.tableContainer {
+    max-height: 2.44rem;
+    overflow: auto;
+    .van-row {
+        color: #444;
+        &:first-child {
+            border-top: 0;
+            background: #fff;
+            font-size: .14rem;
+        }
+    }
+}
+
+.agreeProtocol {
+    font-size: .14rem;
+    display: flex;
+    align-items: center;
+    color: #333333;
+    padding: .05rem .16rem;
+    .van-checkbox {
+        padding-right: .08rem;
+        
+    }
+    /deep/.van-checkbox__icon .van-icon {
+        // border-color: #14928A;
+        background: #fff;
+    }
+    /deep/.van-checkbox__icon--checked .van-icon {
+        color: #fff;
+        background-color: #F85043;
+        border-color: #F85043;
+    }
+    span {
+        color: #14928A;
+    }
+}
+</style>

+ 106 - 0
src/views/app/ExchangeRecord.vue

@@ -0,0 +1,106 @@
+<template>
+    <div class="periodExchange">
+        <m-header v-if="headerStatus" />
+
+        <van-list v-model="loading" v-if="dataShow" key="data"
+            :finished="finished"
+            finished-text="我是有底线的"
+            @load="getAccountDetail">
+            <van-cell-group>
+                <van-cell  v-for="i in 5" :key="i" :center="true">
+                    <template slot="title">
+                        <p class="exchangeText">兑换2000小时</p>
+                    </template>
+                    <template slot="label">
+                        <p class="info">02-28 18:18</p>
+                    </template>
+                    <template slot="default">
+                        <p class="exchangeText enum">+2000</p>
+                        <p class="info">剩余2020小时</p>
+                    </template>
+                </van-cell>
+            </van-cell-group>
+        </van-list>
+        <m-empty class="empty" msg="暂无兑换记录" v-else key="data" />
+    </div>
+</template>
+<script>
+/* eslint-disable */
+import MHeader from '@/components/MHeader'
+import MEmpty from '@/components/MEmpty'
+import { browser }  from '@/common/common'
+import { queryTenantAccountDetail } from '@/api/app'
+
+export default {
+    name: 'courseApply',
+    components: { MHeader, MEmpty },
+    data() {
+        return {
+            headerStatus: true,
+            loading: false,
+            finished: false,
+            params: {
+                search: null,
+                transType: 'RECHARGE',
+                page: 1,
+                rows: 20
+            },
+            dataShow: true, // 是否有数据
+            dataList: []
+        }
+    },
+    mounted() {
+        let params = this.$route.query
+        if(params.Authorization) {
+            localStorage.setItem('Authorization', decodeURI(params.Authorization))
+            localStorage.setItem('userInfo', decodeURI(params.Authorization))
+        }
+        
+        document.title = '兑换记录'
+        if(browser().android || browser().iPhone) {
+            this.headerStatus = false
+        }
+    },
+    methods: {
+        getAccountDetail() {
+            let params = this.params
+            queryTenantAccountDetail(params).then(res => {
+                let result = res.data
+                this.loading = false
+                if(result.code == 200) {
+                    params.page = result.data.pageNo
+                    this.dataList = this.dataList.concat(result.data.rows)
+                    if(params.page >= result.data.totalPage) {
+                        this.finished = true
+                    }
+                    this.params.page++
+                } else {
+                    this.finished = true
+                }
+                // 判断是否有数据
+                if(this.dataList.length <= 0) {
+                    this.dataShow = false
+                }
+            })
+        }
+    }
+}
+</script>
+<style lang='less' scoped>
+@import url("../../assets/commonLess/variable.less");
+.periodExchange {
+    min-height: 100vh;
+    .exchangeText {
+        font-size: .17rem;
+        color: #1A1A1A;
+        line-height: .24rem;
+        &.enum {
+            color: #2FB371;
+        }
+    }
+    .info {
+        font-size: .14rem;
+        color: #808080;
+    }
+}
+</style>

+ 124 - 0
src/views/app/PeriodExchange.vue

@@ -0,0 +1,124 @@
+<template>
+    <div class="periodExchange">
+        <m-header v-if="headerStatus" />
+
+        <van-cell-group>
+            <van-cell :center="true">
+                <template slot="icon">
+                    <img class="logo" src="@/assets/images/icon_teacher.png" alt="">
+                </template>
+                <template slot="title">
+                    <p class="exchangeText">刘老师</p>
+                </template>
+                <template slot="label">
+                    <p class="info">剩余时长:2000</p>
+                </template>
+            </van-cell>
+        </van-cell-group>
+    
+        <div class="pay_btn" >确认兑换</div>
+    </div>
+</template>
+<script>
+/* eslint-disable */
+import MHeader from '@/components/MHeader'
+import { browser }  from '@/common/common'
+import { queryTenantAccountDetail } from '@/api/app'
+
+export default {
+    name: 'courseApply',
+    components: { MHeader },
+    data() {
+        return {
+            headerStatus: true,
+            loading: false,
+            finished: false,
+            params: {
+                search: null,
+                page: 1,
+                rows: 20
+            },
+            dataShow: true, // 是否有数据
+            dataList: []
+        }
+    },
+    mounted() {
+        let params = this.$route.query
+        if(params.Authorization) {
+            localStorage.setItem('Authorization', decodeURI(params.Authorization))
+            localStorage.setItem('userInfo', decodeURI(params.Authorization))
+        }
+        
+        document.title = '课时兑换'
+        if(browser().android || browser().iPhone) {
+            this.headerStatus = false
+        }
+    },
+    methods: {
+        getAccountDetail() {
+            let params = this.params
+            queryTenantAccountDetail(params).then(res => {
+                let result = res.data
+                this.loading = false
+                if(result.code == 200) {
+                    params.page = result.data.pageNo
+                    this.dataList = this.dataList.concat(result.data.rows)
+                    if(params.page >= result.data.totalPage) {
+                        this.finished = true
+                    }
+                    this.params.page++
+                } else {
+                    this.finished = true
+                }
+                // 判断是否有数据
+                if(this.dataList.length <= 0) {
+                    this.dataShow = false
+                }
+            })
+        },
+        desensitPhone(phone) { // 手机号脱敏
+            let first = phone.substr(0, 3)
+            let last  = phone.substr(-4)
+            return first + '****' + last
+        }
+    }
+}
+</script>
+<style lang='less' scoped>
+@import url("../../assets/commonLess/variable.less");
+.periodExchange {
+    min-height: 100vh;
+    position: relative;
+    .logo {
+        width: .5rem;
+        height: .5rem;
+        border-radius: 50%;
+        overflow: hidden;
+        margin-right: .13rem;
+    }
+    /deep/.van-cell {
+        padding: .26rem .16rem .88rem;
+    }
+    .exchangeText {
+        font-size: .18rem;
+        color: #1A1A1A;
+    }
+    .info {
+        font-size: .16rem;
+        color: #808080;
+    }
+    
+}
+.pay_btn {
+    background: #14928A;
+    line-height: 0.45rem;
+    color: #fff;
+    font-size: 0.18rem;
+    border-radius: 0.5rem;
+    text-align: center;
+    position: absolute;
+    width: 90%;
+    margin-left: 5%;
+    bottom: .2rem;
+}
+</style>

+ 107 - 0
src/views/app/PeriodRecord.vue

@@ -0,0 +1,107 @@
+<template>
+    <div class="periodExchange">
+        <m-header v-if="headerStatus" />
+
+        <van-list v-model="loading" v-if="dataShow" key="data"
+            :finished="finished"
+            finished-text="我是有底线的"
+            @load="getAccountDetail">
+            <van-cell-group>
+                <van-cell  v-for="i in 5" :key="i" :center="true">
+                    <template slot="title">
+                        <p class="exchangeText">长笛基础课</p>
+                    </template>
+                    <template slot="label">
+                        <p class="info">进行中</p>
+                        <p class="info">02-28 18:18</p>
+                    </template>
+                    <template slot="default">
+                        <p class="exchangeText enum">冻结2000小时</p>
+                        <p class="info">已消耗2020小时</p>
+                    </template>
+                </van-cell>
+            </van-cell-group>
+        </van-list>
+        <m-empty class="empty" msg="暂无兑换记录" v-else key="data" />
+    </div>
+</template>
+<script>
+/* eslint-disable */
+import MHeader from '@/components/MHeader'
+import MEmpty from '@/components/MEmpty'
+import { browser }  from '@/common/common'
+import { queryTenantAccountDetail } from '@/api/app'
+
+export default {
+    name: 'courseApply',
+    components: { MHeader, MEmpty },
+    data() {
+        return {
+            headerStatus: true,
+            loading: false,
+            finished: false,
+            params: {
+                search: null,
+                transType: 'RECHARGE',
+                page: 1,
+                rows: 20
+            },
+            dataShow: true, // 是否有数据
+            dataList: []
+        }
+    },
+    mounted() {
+        let params = this.$route.query
+        if(params.Authorization) {
+            localStorage.setItem('Authorization', decodeURI(params.Authorization))
+            localStorage.setItem('userInfo', decodeURI(params.Authorization))
+        }
+        
+        document.title = '兑换记录'
+        if(browser().android || browser().iPhone) {
+            this.headerStatus = false
+        }
+    },
+    methods: {
+        getAccountDetail() {
+            let params = this.params
+            queryTenantAccountDetail(params).then(res => {
+                let result = res.data
+                this.loading = false
+                if(result.code == 200) {
+                    params.page = result.data.pageNo
+                    this.dataList = this.dataList.concat(result.data.rows)
+                    if(params.page >= result.data.totalPage) {
+                        this.finished = true
+                    }
+                    this.params.page++
+                } else {
+                    this.finished = true
+                }
+                // 判断是否有数据
+                if(this.dataList.length <= 0) {
+                    this.dataShow = false
+                }
+            })
+        }
+    }
+}
+</script>
+<style lang='less' scoped>
+@import url("../../assets/commonLess/variable.less");
+.periodExchange {
+    min-height: 100vh;
+    .exchangeText {
+        font-size: .17rem;
+        color: #1A1A1A;
+        line-height: .24rem;
+        &.enum {
+            color: #FF5050;
+        }
+    }
+    .info {
+        font-size: .14rem;
+        color: #808080;
+    }
+}
+</style>

+ 1 - 1
vue.config.js

@@ -1,5 +1,5 @@
 let targetUrl = 'http://mteadev.dayaedu.com'
-// let targetUrl = 'http://192.168.3.8:8000'
+// let targetUrl = 'http://dyme.utools.club'
 // let targetUrl = 'https://online.dayaedu.com'
 // let targetUrl = 'http://testadm.dayaedu.com/'
 // let targetUrl = 'http://192.168.3.48:8080'

部分文件因为文件数量过多而无法显示