Explorar el Código

Merge branch 'master' of http://git.dayaedu.com/lex/orchestra-app

mo hace 2 años
padre
commit
13b5fce55e
Se han modificado 77 ficheros con 1790 adiciones y 980 borrados
  1. 8 5
      dist/index.html
  2. 8 5
      dist/school.html
  3. 8 5
      dist/teacher.html
  4. 11 1
      public/project/initiation.html
  5. 2 1
      public/project/js/utils.js
  6. 12 2
      public/project/preRegister.html
  7. 1 1
      public/project/schoolRegister.html
  8. 3 3
      src/helpers/native-message.ts
  9. 1 1
      src/router/routes-common.ts
  10. 1 1
      src/school/App.tsx
  11. 13 0
      src/school/approval-manage/agency/index.tsx
  12. 3 2
      src/school/approval-manage/batch-adjust.tsx
  13. 1 1
      src/school/attendance/components/attend-student.tsx
  14. 1 1
      src/school/attendance/components/attend-teacher.tsx
  15. 18 8
      src/school/companion-teacher/companion-detail.tsx
  16. 85 0
      src/school/companion-teacher/companion-teacher-register.module.less
  17. 65 28
      src/school/companion-teacher/companion-teacher-register.tsx
  18. 4 2
      src/school/mass-message/component/class-list/index.tsx
  19. 12 4
      src/school/orchestra-story/index.tsx
  20. 27 17
      src/school/orchestra-story/story-operation/index.tsx
  21. 1 1
      src/school/orchestra/compontent/information.tsx
  22. 187 14
      src/school/orchestra/compontent/photo-create.tsx
  23. 19 1
      src/school/orchestra/compontent/photo.module.less
  24. 2 2
      src/school/orchestra/compontent/plan.tsx
  25. 2 1
      src/school/orchestra/create-orchestra/index.tsx
  26. 4 4
      src/school/orchestra/modal/add-information.tsx
  27. 1 1
      src/school/orchestra/orchestra-information.tsx
  28. 1 1
      src/school/ranking-list/components/day-bang.tsx
  29. 1 1
      src/school/ranking-list/components/timer-bang.tsx
  30. 3 1
      src/school/school-detail/eidt-school.tsx
  31. 5 0
      src/school/school-detail/index.module.less
  32. 1 1
      src/student/App.tsx
  33. BIN
      src/student/member-center/images/icon-question.png
  34. BIN
      src/student/member-center/images/member_bg1.png
  35. 29 0
      src/student/member-center/index.module.less
  36. 120 79
      src/student/member-center/index.tsx
  37. 1 1
      src/student/music-group/pre-apply/component/apply.tsx
  38. 66 79
      src/student/music-group/pre-apply/component/order.tsx
  39. 3 1
      src/student/music-group/pre-apply/order-detail.tsx
  40. 1 1
      src/student/music-group/shop-address/index.tsx
  41. 64 1
      src/student/payment-result/index.module.less
  42. 147 2
      src/student/payment-result/index.tsx
  43. 7 118
      src/student/trade-record/component/paid-list.tsx
  44. 5 4
      src/student/trade-record/component/refund-list.tsx
  45. 5 4
      src/student/trade-record/component/wait-pay.tsx
  46. 14 5
      src/styles/index.less
  47. 1 1
      src/teacher/App.tsx
  48. 1 1
      src/teacher/attendance/index.tsx
  49. 2 1
      src/views/404/index.tsx
  50. 8 8
      src/views/courseList/index.tsx
  51. 14 9
      src/views/coursewarePlay/index.tsx
  52. 198 182
      src/views/exercise-after-class/index.module.less
  53. 213 206
      src/views/exercise-after-class/index.tsx
  54. 1 1
      src/views/exercise-record/index.tsx
  55. 1 0
      src/views/information/help-center/index.module.less
  56. 1 1
      src/views/information/index.tsx
  57. 9 3
      src/views/mine-orchestra/index.tsx
  58. 9 4
      src/views/mine-orchestra/my-class/index.tsx
  59. 12 3
      src/views/mine-orchestra/my-photo/index.tsx
  60. 9 2
      src/views/mine-orchestra/orchestra-deeds/index.tsx
  61. 2 2
      src/views/mine-orchestra/photo-list/detail.tsx
  62. 46 38
      src/views/mine-orchestra/photo-list/index.module.less
  63. 1 1
      src/views/mine-orchestra/photo-list/index.tsx
  64. 34 9
      src/views/unit-test/examination-mode/index.tsx
  65. 6 5
      src/views/unit-test/index.tsx
  66. 11 1
      src/views/unit-test/model/anser-title/index.tsx
  67. 5 0
      src/views/unit-test/model/drag-question/index.module.less
  68. 14 11
      src/views/unit-test/model/drag-question/index.tsx
  69. 78 27
      src/views/unit-test/model/play-question/index.tsx
  70. BIN
      src/views/unit-test/model/unit-audio/images/icon-pause.png
  71. BIN
      src/views/unit-test/model/unit-audio/images/icon-play.png
  72. 1 1
      src/views/unit-test/model/unit-audio/index.module.less
  73. 5 7
      src/views/unit-test/model/unit-audio/index.tsx
  74. 27 6
      src/views/unit-test/practice-mode/index.tsx
  75. 3 3
      src/views/unit-test/unit-create/modals/newspaper-item.tsx
  76. 79 32
      src/views/unit-test/unit-create/uni-last.tsx
  77. 26 4
      src/views/unit-test/unit-detail/index.tsx

+ 8 - 5
dist/index.html

@@ -34,7 +34,7 @@
   <meta name="apple-touch-fullscreen" content="yes" />
   <!-- windows phone 点击无高光 -->
   <meta name="msapplication-tap-highlight" content="no" />
-  <title>酷乐秀</title>
+  <title>管乐团</title>
   <script src="./flexible.js" charset="UTF-8"></script>
   <script type="text/javascript">
     window.paymentType = 'STUDENT'
@@ -42,15 +42,18 @@
   <script type="module" crossorigin src="./assets/index.14ce4599.js"></script>
   <link rel="modulepreload" href="./assets/index.879f7421.js">
   <link rel="stylesheet" href="./assets/index.6d794fa2.css">
-  <script type="module">!function(){try{new Function("m","return import(m)")}catch(o){console.warn("vite: loading legacy build because dynamic import is unsupported, syntax error above should be ignored");var e=document.getElementById("vite-legacy-polyfill"),n=document.createElement("script");n.src=e.src,n.onload=function(){System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))},document.body.appendChild(n)}}();</script>
+  <script
+    type="module">!function () { try { new Function("m", "return import(m)") } catch (o) { console.warn("vite: loading legacy build because dynamic import is unsupported, syntax error above should be ignored"); var e = document.getElementById("vite-legacy-polyfill"), n = document.createElement("script"); n.src = e.src, n.onload = function () { System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src')) }, document.body.appendChild(n) } }();</script>
 </head>
 
 <body>
   <div id="app"></div>
-  
-  <script nomodule>!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script>
+
+  <script
+    nomodule>!function () { var e = document, t = e.createElement("script"); if (!("noModule" in t) && "onbeforeload" in t) { var n = !1; e.addEventListener("beforeload", (function (e) { if (e.target === t) n = !0; else if (!e.target.hasAttribute("nomodule") || !n) return; e.preventDefault() }), !0), t.type = "module", t.src = ".", e.head.appendChild(t), t.remove() } }();</script>
   <script nomodule id="vite-legacy-polyfill" src="./assets/polyfills-legacy.3b4651af.js"></script>
-  <script nomodule id="vite-legacy-entry" data-src="./assets/index-legacy.fbc3f795.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
+  <script nomodule id="vite-legacy-entry"
+    data-src="./assets/index-legacy.fbc3f795.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
 </body>
 
 </html>

+ 8 - 5
dist/school.html

@@ -34,7 +34,7 @@
   <meta name="apple-touch-fullscreen" content="yes" />
   <!-- windows phone 点击无高光 -->
   <meta name="msapplication-tap-highlight" content="no" />
-  <title>酷乐秀</title>
+  <title>管乐团</title>
   <script src="./flexible.js" charset="UTF-8"></script>
   <script type="text/javascript">
     window.paymentType = 'SCHOOL'
@@ -42,15 +42,18 @@
   <script type="module" crossorigin src="./assets/school.c1e59d77.js"></script>
   <link rel="modulepreload" href="./assets/index.879f7421.js">
   <link rel="stylesheet" href="./assets/index.6d794fa2.css">
-  <script type="module">!function(){try{new Function("m","return import(m)")}catch(o){console.warn("vite: loading legacy build because dynamic import is unsupported, syntax error above should be ignored");var e=document.getElementById("vite-legacy-polyfill"),n=document.createElement("script");n.src=e.src,n.onload=function(){System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))},document.body.appendChild(n)}}();</script>
+  <script
+    type="module">!function () { try { new Function("m", "return import(m)") } catch (o) { console.warn("vite: loading legacy build because dynamic import is unsupported, syntax error above should be ignored"); var e = document.getElementById("vite-legacy-polyfill"), n = document.createElement("script"); n.src = e.src, n.onload = function () { System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src')) }, document.body.appendChild(n) } }();</script>
 </head>
 
 <body>
   <div id="app"></div>
-  
-  <script nomodule>!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script>
+
+  <script
+    nomodule>!function () { var e = document, t = e.createElement("script"); if (!("noModule" in t) && "onbeforeload" in t) { var n = !1; e.addEventListener("beforeload", (function (e) { if (e.target === t) n = !0; else if (!e.target.hasAttribute("nomodule") || !n) return; e.preventDefault() }), !0), t.type = "module", t.src = ".", e.head.appendChild(t), t.remove() } }();</script>
   <script nomodule id="vite-legacy-polyfill" src="./assets/polyfills-legacy.3b4651af.js"></script>
-  <script nomodule id="vite-legacy-entry" data-src="./assets/school-legacy.545ba943.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
+  <script nomodule id="vite-legacy-entry"
+    data-src="./assets/school-legacy.545ba943.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
 </body>
 
 </html>

+ 8 - 5
dist/teacher.html

@@ -34,7 +34,7 @@
   <meta name="apple-touch-fullscreen" content="yes" />
   <!-- windows phone 点击无高光 -->
   <meta name="msapplication-tap-highlight" content="no" />
-  <title>酷乐秀</title>
+  <title>管乐团</title>
   <script src="./flexible.js" charset="UTF-8"></script>
   <script type="text/javascript">
     window.paymentType = 'TEACHER'
@@ -42,15 +42,18 @@
   <script type="module" crossorigin src="./assets/teacher.8a138f88.js"></script>
   <link rel="modulepreload" href="./assets/index.879f7421.js">
   <link rel="stylesheet" href="./assets/index.6d794fa2.css">
-  <script type="module">!function(){try{new Function("m","return import(m)")}catch(o){console.warn("vite: loading legacy build because dynamic import is unsupported, syntax error above should be ignored");var e=document.getElementById("vite-legacy-polyfill"),n=document.createElement("script");n.src=e.src,n.onload=function(){System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))},document.body.appendChild(n)}}();</script>
+  <script
+    type="module">!function () { try { new Function("m", "return import(m)") } catch (o) { console.warn("vite: loading legacy build because dynamic import is unsupported, syntax error above should be ignored"); var e = document.getElementById("vite-legacy-polyfill"), n = document.createElement("script"); n.src = e.src, n.onload = function () { System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src')) }, document.body.appendChild(n) } }();</script>
 </head>
 
 <body>
   <div id="app"></div>
-  
-  <script nomodule>!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script>
+
+  <script
+    nomodule>!function () { var e = document, t = e.createElement("script"); if (!("noModule" in t) && "onbeforeload" in t) { var n = !1; e.addEventListener("beforeload", (function (e) { if (e.target === t) n = !0; else if (!e.target.hasAttribute("nomodule") || !n) return; e.preventDefault() }), !0), t.type = "module", t.src = ".", e.head.appendChild(t), t.remove() } }();</script>
   <script nomodule id="vite-legacy-polyfill" src="./assets/polyfills-legacy.3b4651af.js"></script>
-  <script nomodule id="vite-legacy-entry" data-src="./assets/teacher-legacy.e10aa72f.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
+  <script nomodule id="vite-legacy-entry"
+    data-src="./assets/teacher-legacy.e10aa72f.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
 </body>
 
 </html>

+ 11 - 1
public/project/initiation.html

@@ -310,7 +310,7 @@
           showPicker: false,
           classPicker: false,
           submitStatus: false,
-          pattern: /^1(3|4|5|6|7|8|9)\d{9}$/,
+          pattern: /^((13[0-9])|(14(0|[5-7]|9))|(15([0-3]|[5-9]))|(16(2|[5-7]))|(17[0-8])|(18[0-9])|(19([0-3]|[5-9])))\d{8}$/,
           nameReg: /^[\u4E00-\u9FA5]+$/,
           currentGrade: [
             { text: '一年级', value: 1 },
@@ -339,6 +339,7 @@
           checkPhone: true,
           showPopup: false,
           code: '',
+          canSignUp: '',
         }
       },
       async mounted() {
@@ -382,6 +383,11 @@
           var orchestraDetail = await axios.get('/api-student/open/orchestra/detail/' + this.orchestraId)
           if (orchestraDetail.data.code === 200 && orchestraDetail.data.data) {
             this.orchestraName = orchestraDetail.data.data.name || ''
+            this.canSignUp = orchestraDetail.data.data.status
+            if (orchestraDetail.data.data.status !== 'INITIATION_SURVEY') {
+              vant.showToast('乐团启蒙阶段已结束')
+              return
+            }
           }
         } catch {
           vant.showDialog({
@@ -472,6 +478,10 @@
           }
         },
         async onSubmit() {
+          if (this.canSignUp !== 'INITIATION_SURVEY') {
+            vant.showToast('乐团启蒙阶段已结束')
+            return
+          }
           this.btnLoading = true
           try {
             var stu = this.stu

+ 2 - 1
public/project/js/utils.js

@@ -1,5 +1,6 @@
 function phoneValidate(phone) {
-  var reg = /^1(3|4|5|6|7|8|9)\d{9}$/
+  var reg =
+    /^((13[0-9])|(14(0|[5-7]|9))|(15([0-3]|[5-9]))|(16(2|[5-7]))|(17[0-8])|(18[0-9])|(19([0-3]|[5-9])))\d{8}$/
   if (reg.test(phone)) {
     return true
   } else {

+ 12 - 2
public/project/preRegister.html

@@ -326,7 +326,7 @@
           classPicker: false,
           subjectPicker: false,
           submitStatus: false,
-          pattern: /^1(3|4|5|6|7|8|9)\d{9}$/,
+          pattern: /^((13[0-9])|(14(0|[5-7]|9))|(15([0-3]|[5-9]))|(16(2|[5-7]))|(17[0-8])|(18[0-9])|(19([0-3]|[5-9])))\d{8}$/,
           nameReg: /^[\u4E00-\u9FA5]+$/,
           currentGrade: [
             { text: '一年级', value: 1 },
@@ -355,7 +355,8 @@
           btnLoading: false,
           checkPhone: true,
           showPopup: false,
-          code: ''
+          code: '',
+          canSignUp: ''
         }
       },
       async mounted() {
@@ -399,6 +400,11 @@
           var orchestraDetail = await axios.get('/api-student/open/orchestra/detail/' + this.orchestraId)
           if (orchestraDetail.data.code === 200) {
             this.orchestraName = orchestraDetail.data.data.name || ''
+            this.canSignUp = orchestraDetail.data.data.status
+            if (orchestraDetail.data.data.status !== 'PRE_REGISTER') {
+              vant.showToast('乐团预报名阶段已结束')
+              return
+            }
           }
 
           var subjects = await axios.post('/api-student/open/orchestraSubjectConfig/pageByOrchestraId', {
@@ -527,6 +533,10 @@
           }
         },
         async onSubmit() {
+          if (this.canSignUp !== 'PRE_REGISTER') {
+            vant.showToast('乐团预报名阶段已结束')
+            return
+          }
           this.btnLoading = true
           try {
             var stu = this.stu

+ 1 - 1
public/project/schoolRegister.html

@@ -168,7 +168,7 @@
         return {
           showPicker: false,
           submitStatus: false,
-          pattern: /^1(3|4|5|6|7|8|9)\d{9}$/,
+          pattern: /^((13[0-9])|(14(0|[5-7]|9))|(15([0-3]|[5-9]))|(16(2|[5-7]))|(17[0-8])|(18[0-9])|(19([0-3]|[5-9])))\d{8}$/,
           emailPattern: /^\w+@([\da-z\.-]+)\.([a-z]+|[\u2E80-\u9FFF]+)$/,
           columns: [],
           pickerType: null, // 下拉类型

+ 3 - 3
src/helpers/native-message.ts

@@ -27,7 +27,7 @@ window.postMessage = (message: IPostMessage) => {
 type CallBack = (evt?: IPostMessage) => void
 
 // eslint-disable-next-line @typescript-eslint/no-empty-function
-const loop = () => {}
+const loop = () => { }
 
 const calls: { [key: string]: CallBack | CallBack[] } = {}
 
@@ -39,7 +39,7 @@ if (browserInfo.isApp) {
       console.log('app交互接受:', evt.data)
       const data = evt.data ? (typeof evt.data === 'object' ? evt.data : JSON.parse(evt.data)) : {}
       const uuid = data.content?.uuid || data.uuid
-      // console.log(uuid, data.content, 'uuid')
+      console.log(uuid, data.content, 'uuid')
       try {
         if (data.content) {
           data.content = JSON.parse(data.content)
@@ -105,7 +105,7 @@ export const removeListenerMessage = (api: string, callback: CallBack) => {
     const uuid = api
     if (Array.isArray(calls[uuid])) {
       const indexOf = (calls[uuid] as CallBack[]).indexOf(callback)
-      ;(calls[uuid] as CallBack[]).splice(indexOf, 1)
+        ; (calls[uuid] as CallBack[]).splice(indexOf, 1)
     }
   }
 }

+ 1 - 1
src/router/routes-common.ts

@@ -243,7 +243,7 @@ export const rootRouter = [
     path: '/:pathMatch(.*)*',
     component: () => import('@/views/404'),
     meta: {
-      title: '404 Not Fund',
+      title: '404',
       platform: paymentType
     }
   }

+ 1 - 1
src/school/App.tsx

@@ -28,7 +28,7 @@ export default defineComponent({
               message: () => (
                 <>
                   <Vue3Lottie class={'toastAnimate'} animationData={AstronautJSON}></Vue3Lottie>
-                  <p>加载中...</p>
+                  {/* <p>加载中...</p> */}
                 </>
               )
             }}

+ 13 - 0
src/school/approval-manage/agency/index.tsx

@@ -67,6 +67,19 @@ export default defineComponent({
       loading.value = true
       try {
         const res: any = await request.post(`${state.platformApi}/schoolWeekSalaryRecord/manage`)
+        if (Array.isArray(res?.data?.salaryRecordList)){
+          data.salaryRecordList = res.data.salaryRecordList
+        }
+        data.schoolWeekPhoto = res?.data?.schoolWeekPhoto || {}
+        data.schoolWeekNews = res?.data?.schoolWeekNews || {}
+        if (data.schoolWeekPhoto){
+          data.schoolWeekPhoto.startDate = data.schoolWeekPhoto?.startDate?.split(' ')[0]
+          data.schoolWeekPhoto.endDate = data.schoolWeekPhoto?.endDate?.split(' ')[0]
+        }
+        if (data.schoolWeekNews){
+          data.schoolWeekNews.startDate = data.schoolWeekNews?.startDate?.split(' ')[0]
+          data.schoolWeekNews.endDate = data.schoolWeekNews?.endDate?.split(' ')[0]
+        }
       } catch (error) {}
       loading.value = false
       refreshing.value = false

+ 3 - 2
src/school/approval-manage/batch-adjust.tsx

@@ -41,7 +41,8 @@ export default defineComponent({
           data: {
             page: 1,
             rows: 100,
-            schoolId: state.user.data.school.id
+            schoolId: state.user.data.school.id,
+            status: 'DONE'
           }
         })
         forms.orchestraList = data.rows || []
@@ -96,7 +97,7 @@ export default defineComponent({
         <OHeader />
 
         <CellGroup inset>
-          <Cell isLink onClick={() => (forms.orchestraStatus = true)}>
+          <Cell isLink onClick={() => (forms.orchestraStatus = true)} valueClass={['van-ellipsis']}>
             {{ title: () => '乐团名称', value: () => forms.orchestraName }}
           </Cell>
           <Cell

+ 1 - 1
src/school/attendance/components/attend-student.tsx

@@ -119,7 +119,7 @@ export default defineComponent({
     const getOrchestraList = async () => {
       try {
         const res = await request.post('/api-teacher/orchestra/page', {
-          data: { page: 1, rows: 9999 }
+          data: { page: 1, rows: 9999, status: 'DONE' }
         })
         state.actions = res.data.rows.map((item) => {
           return {

+ 1 - 1
src/school/attendance/components/attend-teacher.tsx

@@ -123,7 +123,7 @@ export default defineComponent({
     const getOrchestraList = async () => {
       try {
         const res = await request.post('/api-school/orchestra/page', {
-          data: { page: 1, rows: 9999 }
+          data: { page: 1, rows: 9999, status: 'DONE' }
         })
         state.actions = res.data.rows.map((item) => {
           return {

+ 18 - 8
src/school/companion-teacher/companion-detail.tsx

@@ -72,15 +72,25 @@ export default defineComponent({
     }
 
     const onDetail = async () => {
-      if (state.classList.length > 0) {
-        router.push({
-          path: '/companion-unbind',
-          query: { id: route.query.id }
-        })
-        return
-      }
+      try {
+        const { data } = await request.post(
+          '/api-school/classGroup/teacherHandoverList/' + route.query.id,
+          {}
+        )
+        const classList = data || []
+
+        if (classList.length > 0) {
+          router.push({
+            path: '/companion-unbind',
+            query: { id: route.query.id }
+          })
+          return
+        }
 
-      state.showDialog = true
+        state.showDialog = true
+      } catch {
+        //
+      }
     }
 
     const onConfirm = async () => {

+ 85 - 0
src/school/companion-teacher/companion-teacher-register.module.less

@@ -310,3 +310,88 @@ span {
 .fieldTitle {
   color: #fff !important;
 }
+
+.filterTitle {
+  font-size: 18px;
+  font-weight: 500;
+  color: #000000;
+  line-height: 25px;
+  text-align: center;
+  padding: 18px 0;
+}
+
+.searchResult {
+  padding: 0 16px;
+  overflow: hidden;
+  margin-bottom: 20px;
+  .searchTitle {
+    font-size: 16px;
+    color: #333333;
+    line-height: 22px;
+  }
+}
+
+.childContent {
+  display: flex;
+  flex-wrap: wrap;
+  text-align: center;
+  .item {
+    display: block;
+    margin-right: 5px;
+    margin-bottom: 10px;
+    min-width: 80px;
+    height: 32px;
+    &:nth-child(4n + 0) {
+      margin-right: 0;
+    }
+  }
+}
+
+.radio {
+  box-sizing: border-box;
+  :global {
+    .van-radio__icon,
+    .van-checkbox__icon {
+      display: none;
+    }
+    .van-checkbox__label {
+      margin-left: 0;
+    }
+    .van-tag--large {
+      // width: 94px;
+      // height: 30px;
+      font-size: 14px;
+      text-align: center;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+    }
+    .van-tag {
+      box-sizing: border-box;
+    }
+
+    .van-tag--primary {
+      color: #333333;
+      background-color: #fff;
+      border: #d8d8d8;
+    }
+    .van-tag--primary.van-tag--plain {
+      color: var(--van-primary-color);
+      background-color: #fff5f2;
+      border: var(--van-primary-color);
+    }
+
+    .van-tag--primary:before {
+      position: absolute;
+      top: 0;
+      right: 0;
+      bottom: 0;
+      left: 0;
+      border: 0.02667rem solid;
+      border-color: inherit;
+      border-radius: inherit;
+      content: '';
+      pointer-events: none;
+    }
+  }
+}

+ 65 - 28
src/school/companion-teacher/companion-teacher-register.tsx

@@ -16,7 +16,9 @@ import {
   closeToast,
   Picker,
   Popup,
-  CountDown
+  CountDown,
+  CheckboxGroup,
+  Sticky
 } from 'vant'
 import { defineComponent, onMounted, reactive, ref } from 'vue'
 import { useRoute } from 'vue-router'
@@ -51,6 +53,7 @@ export default defineComponent({
       pattern: /^1(3|4|5|6|7|8|9)\d{9}$/,
       columns: [] as any,
       pickerType: null, // 下拉类型
+      popupSelectSubjects: [] as any,
       selectSubjects: [] as any, // 选中的声部
       forms: {
         realName: '',
@@ -123,6 +126,7 @@ export default defineComponent({
     }
 
     const onSubjectRemove = (item: any, index: any) => {
+      console.log(item)
       showDialog({
         title: '提示',
         message: '您是否删除选中的声部',
@@ -130,36 +134,31 @@ export default defineComponent({
         showCancelButton: true
       }).then(() => {
         state.selectSubjects.splice(index, 1)
-        const tempSubjectIds: any = []
-        state.selectSubjects.forEach((subject: any) => {
-          tempSubjectIds.push(subject.value)
-        })
-        state.forms.subjectIds = tempSubjectIds
-        state.forms.showSubjectIds = tempSubjectIds.join(',')
+
+        const tIndex = state.popupSelectSubjects.findIndex((s: any) => s === item.value)
+        state.popupSelectSubjects.splice(tIndex, 1)
+
+        // const tempSubjectIds: any = []
+        // state.selectSubjects.forEach((subject: any) => {
+        //   tempSubjectIds.push(subject.value)
+        // })
+        state.forms.subjectIds = state.popupSelectSubjects
+        state.forms.showSubjectIds = state.popupSelectSubjects.join(',')
       })
     }
     // 选择声部
-    const onConfirmSubject = (val: any) => {
-      const selected = val.selectedOptions[0]
-      let isCheck = false
-      state.selectSubjects.forEach((subject: any) => {
-        if (subject.value === selected.value) {
-          isCheck = true
+    const onConfirmSubject = () => {
+      const tempSubjects: any = []
+      state.columnSubject.forEach((item: any) => {
+        if (state.popupSelectSubjects.includes(item.value)) {
+          tempSubjects.push(item)
         }
       })
-      // 判断是否有选择一样的数据
-      if (isCheck) {
-        state.showSubject = false
-        return
-      }
 
-      state.selectSubjects.push(val.selectedOptions[0])
-      const tempSubjectIds: any = []
-      state.selectSubjects.forEach((subject: any) => {
-        tempSubjectIds.push(subject.value)
-      })
-      state.forms.subjectIds = tempSubjectIds
-      state.forms.showSubjectIds = tempSubjectIds.join(',')
+      state.selectSubjects = tempSubjects
+      state.forms.subjectIds = state.popupSelectSubjects || []
+      state.forms.showSubjectIds = state.popupSelectSubjects.join(',')
+
       state.showSubject = false
     }
 
@@ -363,6 +362,7 @@ export default defineComponent({
         const subjects = data.subjectId
           ? data.subjectId.split(',').map((subject: any) => Number(subject))
           : []
+        state.popupSelectSubjects = subjects || []
         // 显示声部
         subjects.forEach((subject: any) => {
           const item = state.columnSubject.find((item: any) => item.value === subject)
@@ -700,13 +700,50 @@ export default defineComponent({
             columnsFieldNames={{ text: 'name', value: 'code', children: 'areas' }}
           />
         </Popup>
-        <Popup v-model:show={state.showSubject} position="bottom" round>
-          <Picker
+        <Popup
+          v-model:show={state.showSubject}
+          position="bottom"
+          round
+          safeAreaInsetBottom
+          closeable
+        >
+          {/* <Picker
             showToolbar
             columns={state.columnSubject}
             onCancel={() => (state.showSubject = false)}
             onConfirm={onConfirmSubject}
-          />
+          /> */}
+          <div class={styles.filterTitle}>全部声部</div>
+          <div class={styles.searchResult} style={{ maxHeight: '45vh', overflowY: 'auto' }}>
+            <CheckboxGroup
+              class={[styles.childContent, styles['radio-group']]}
+              modelValue={state.popupSelectSubjects}
+              onUpdate:modelValue={(val) => {
+                console.log(val)
+                state.popupSelectSubjects = val
+              }}
+            >
+              {state.columnSubject.map((item: any) => (
+                <Checkbox key={item.value} name={item.value} class={styles.radio}>
+                  <Tag
+                    class={[styles.item, 'van-ellipsis']}
+                    plain={state.popupSelectSubjects.includes(item.value)}
+                    type="primary"
+                    size="large"
+                  >
+                    {item.text}
+                  </Tag>
+                </Checkbox>
+              ))}
+            </CheckboxGroup>
+            <Sticky position="bottom" offsetBottom={0}>
+              <div class={['btnGroup']}>
+                <Button type="primary" round block onClick={onConfirmSubject}>
+                  确 认
+                </Button>
+              </div>
+            </Sticky>
+          </div>
         </Popup>
         {/* 学历 */}
         {/* 学历分为专科、本科、硕士、博士、其他 */}

+ 4 - 2
src/school/mass-message/component/class-list/index.tsx

@@ -68,7 +68,8 @@ export default defineComponent({
           data: {
             page: 1,
             rows: 100,
-            schoolId: baseState.user.data.school.id
+            schoolId: baseState.user.data.school.id,
+            status: 'DONE'
           }
         })
         const temps = data.rows || []
@@ -100,7 +101,8 @@ export default defineComponent({
         const { data } = await request.post('/api-school/classGroup/page', {
           data: {
             ...forms.params,
-            schoolId: baseState.user.data.school.id
+            schoolId: baseState.user.data.school.id,
+            orchestraId: forms.orchestraId
           }
         })
         forms.isClick = false

+ 12 - 4
src/school/orchestra-story/index.tsx

@@ -57,7 +57,8 @@ export default defineComponent({
           data: {
             page: 1,
             rows: 100,
-            schoolId: baseState.user.data.school.id
+            schoolId: baseState.user.data.school.id,
+            status: 'DONE'
           }
         })
         const temps = data.rows || []
@@ -72,7 +73,13 @@ export default defineComponent({
 
         // 判断是否有乐团
         if (s.length > 0) {
-          state.selectOrchestra = s[0]
+          const orchestraId = sessionStorage.getItem('orchestraStoryId')
+          if (orchestraId) {
+            const item = s.find((child: any) => child.value === orchestraId)
+            state.selectOrchestra = item || s[0]
+          } else {
+            state.selectOrchestra = s[0]
+          }
 
           getList()
         }
@@ -123,7 +130,8 @@ export default defineComponent({
       router.push({
         path: '/story-operation',
         query: {
-          id: item.id
+          id: item.id,
+          orchestraId: state.selectOrchestra.value
         }
       })
     }
@@ -229,7 +237,7 @@ export default defineComponent({
             onConfirm={(val: any) => {
               state.selectOrchestra = val.selectedOptions[0]
               state.orchestraStatus = false
-
+              sessionStorage.setItem('orchestraStoryId', state.selectOrchestra.value)
               onRefresh()
             }}
           />

+ 27 - 17
src/school/orchestra-story/story-operation/index.tsx

@@ -32,6 +32,7 @@ export default defineComponent({
     const route = useRoute()
     const forms = reactive({
       id: route.query.id || null,
+      orchestraId: route.query.orchestraId || null,
       content: '',
       orchestraStatus: false,
       orchestraList: [] as any,
@@ -52,7 +53,8 @@ export default defineComponent({
         const { data } = await request.post('/api-school/orchestra/page', {
           data: {
             page: 1,
-            rows: 100
+            rows: 100,
+            status: 'DONE'
           }
         })
         const temps = data.rows || []
@@ -67,7 +69,12 @@ export default defineComponent({
 
         // 判断是否有乐团
         if (s.length > 0) {
-          forms.selectOrchestra = s[0]
+          if (forms.orchestraId) {
+            const item = s.find((child: any) => child.value === forms.orchestraId)
+            forms.selectOrchestra = item || s[0]
+          } else {
+            forms.selectOrchestra = s[0]
+          }
         }
       } catch {
         //
@@ -177,22 +184,24 @@ export default defineComponent({
             }
           })
 
-          setTimeout(() => {
-            showSuccessToast('修改成功')
-          }, 100)
+          // setTimeout(() => {
+          //   showSuccessToast('修改成功')
+          // }, 100)
+          router.back()
         } else {
           await request.post('/api-school/orchestraStory/save', {
             data: params
           })
 
-          setTimeout(() => {
-            showSuccessToast('添加成功')
-          }, 100)
+          // setTimeout(() => {
+          //   showSuccessToast('添加成功')
+          // }, 100)
+          router.back()
         }
 
-        setTimeout(() => {
-          router.back()
-        }, 1100)
+        // setTimeout(() => {
+        //   router.back()
+        // }, 1100)
       } catch {
         //
       }
@@ -208,12 +217,13 @@ export default defineComponent({
           }
         })
 
-        setTimeout(() => {
-          showSuccessToast('删除成功')
-        }, 100)
-        setTimeout(() => {
-          router.back()
-        }, 1100)
+        router.back()
+        // setTimeout(() => {
+        //   showSuccessToast('删除成功')
+        // }, 100)
+        // setTimeout(() => {
+        //   router.back()
+        // }, 1100)
       } catch {
         //
       }

+ 1 - 1
src/school/orchestra/compontent/information.tsx

@@ -65,7 +65,7 @@ export default defineComponent({
       params: {
         startTime: dayjs(dayjs().year() + startTime.value).format('YYYY-MM-DD HH:mm:ss'),
         endTime: dayjs(dayjs().year() + endTime.value)
-          .subtract(1, 'year')
+          .add(1, 'year')
           .format('YYYY-MM-DD HH:mm:ss'),
         page: 1,
         rows: 20

+ 187 - 14
src/school/orchestra/compontent/photo-create.tsx

@@ -3,6 +3,7 @@ import request from '@/helpers/request'
 import {
   ActionSheet,
   Button,
+  closeToast,
   Dialog,
   Field,
   Image,
@@ -10,8 +11,11 @@ import {
   Popover,
   Popup,
   showConfirmDialog,
+  showLoadingToast,
   showToast,
-  Sticky
+  Space,
+  Sticky,
+  Uploader
 } from 'vant'
 import { defineComponent, onMounted, reactive } from 'vue'
 import { useRoute, useRouter } from 'vue-router'
@@ -19,6 +23,8 @@ import styles from './photo.module.less'
 import iconPhoneDefaut from '../images/icon-photo-default.png'
 import OHeader from '@/components/o-header'
 import OSticky from '@/components/o-sticky'
+import { getOssUploadUrl } from '@/state'
+import umiRequest from 'umi-request'
 
 export default defineComponent({
   name: 'phone',
@@ -33,6 +39,7 @@ export default defineComponent({
     const router = useRouter()
     const state = reactive({
       oPopover: false,
+      showPhoto: false,
       status: false,
       isLoading: false,
       photoName: null, // 相册名称
@@ -47,7 +54,9 @@ export default defineComponent({
         rows: 20
       },
       selectItem: {} as any,
-      selectType: 'add'
+      selectType: 'add',
+      fileList: [] as any,
+      bucket: 'gyt',
     })
 
     const onAddPhoto = async () => {
@@ -180,22 +189,146 @@ export default defineComponent({
     onMounted(() => {
       getList()
     })
+    const beforeRead = (file: any) => {
+      // console.log(file, 'beforeRead')
+      const isLt2M = file.size / 1024 / 1024 < 5
+      if (!isLt2M) {
+        showToast(`上传文件大小不能超过 5MB`)
+        return false
+      }
+      return true
+    }
+    const beforeDelete = (file: any, detail: { index: any }) => {
+      // this.dataModel.splice(detail.index, 1)
+      return true
+    }
+    const afterRead = async (file: any, detail: any) => {
+      try {
+        file.status = 'uploading'
+        file.message = '上传中...'
+        await uploadFile(file)
+      } catch (error) {
+        //
+        closeToast()
+      }
+    }
+
+    const uploadFile = async (files: any) => {
+      // 上传文件
+      try {
+        console.log(files, 'files')
+        const file = files.file
+        // 获取签名
+        const signUrl = '/api-school/open/getUploadSign'
+        const tempName = file.name || ''
+        const fileName = '/orchestra/' + (tempName && tempName.replace(/ /gi, '_'))
+        const key = new Date().getTime() + fileName
+
+        const res = await request.post(signUrl, {
+          data: {
+            filename: fileName,
+            bucketName: state.bucket,
+            postData: {
+              filename: fileName,
+              acl: 'public-read',
+              key: key,
+              unknowValueField: []
+            }
+          }
+        })
+        showLoadingToast({
+          message: '加载中...',
+          forbidClick: true,
+          loadingType: 'spinner',
+          duration: 0
+        })
+        const obj = {
+          policy: res.data.policy,
+          signature: res.data.signature,
+          key: key,
+          KSSAccessKeyId: res.data.kssAccessKeyId,
+          acl: 'public-read',
+          name: fileName
+        }
+        const formData = new FormData()
+        for (const key in obj) {
+          formData.append(key, obj[key])
+        }
+        formData.append('file', file, fileName)
+        await umiRequest(getOssUploadUrl(state.bucket), {
+          method: 'POST',
+          data: formData
+        })
+        // console.log(getOssUploadUrl(state.bucket) + key)
+        const uploadUrl = getOssUploadUrl(state.bucket) + key
+        closeToast()
+
+        // state.fileList.push({ url: uploadUrl })
+        files.src = uploadUrl
+        files.status = 'done'
+      } catch (error) {
+        files.status = 'failed'
+        console.log(error, 'uploadFile')
+      }
+    }
+
+    // 上传图片
+    const onSubmitPhoto = async () => {
+      try {
+        if (state.fileList.length <= 0) {
+          showToast('请上传照片')
+          return
+        }
+        const files = state.fileList.map((file: any) => {
+          return file.src
+        })
+        console.log(files, 'onSubmitPhoto')
+
+        await request.post('/api-school/orchestraPhoto/save', {
+          data: {
+            orchestraId: route.query.orchestraId,
+            orchestraPhotoAlbumId: route.query.parentId,
+            fileUrl: files.join(',')
+          }
+        })
+
+        state.showPhoto = false
+        state.fileList = []
+        state.params.page = 1
+        state.list = []
+        state.listState.dataShow = true // 判断是否有数据
+        state.listState.loading = false
+        state.listState.finished = false
+        getList()
+      } catch {
+        //
+      }
+    }
     return () => (
       <div class={!state.listState.dataShow && 'emptyRootContainer'}>
         <OSticky position="top">
           <OHeader title={'创建相册'}></OHeader>
-          <Button
-            style={{ margin: '12px auto 0 auto', width: '90%' }}
-            icon="plus"
-            block
-            class={styles.addPhone}
-            onClick={() => {
-              state.status = true
-              state.selectType = 'add'
-            }}
-          >
-            新建相册
-          </Button>
+          <div class={styles.btnGroup}>
+            <Button
+              icon="plus"
+              block
+              class={styles.addPhone}
+              onClick={() => {
+                state.status = true
+                state.selectType = 'add'
+              }}
+            >
+              新建相册
+            </Button>
+            <Button
+              icon="plus"
+              block
+              class={styles.addPhone}
+              onClick={() => (state.showPhoto = true)}
+            >
+              上传照片
+            </Button>
+          </div>
         </OSticky>
         <div class={styles.phone}>
           {state.listState.dataShow ? (
@@ -281,6 +414,46 @@ export default defineComponent({
             ]}
           />
         </div>
+
+        <Popup v-model:show={state.showPhoto} round style={{ width: '92%' }}>
+          <div class={styles.container}>
+            <div class={styles.dialogTitle}>
+              <i></i>
+              上传照片
+            </div>
+
+            <div class={styles.photos}>
+              <Uploader
+                v-model={state.fileList}
+                afterRead={afterRead}
+                beforeRead={beforeRead}
+                beforeDelete={beforeDelete}
+                accept="image/*"
+                maxCount={9}
+              />
+            </div>
+
+            <div class={['van-hairline--top van-dialog__footer']}>
+              <Button
+                onClick={() => {
+                  state.showPhoto = false
+                  state.fileList = []
+                }}
+                class={['van-button van-button--default van-button--large van-dialog__cancel']}
+              >
+                取消
+              </Button>
+              <Button
+                onClick={onSubmitPhoto}
+                class={[
+                  'van-button van-button--default van-button--large van-dialog__confirm van-hairline--left'
+                ]}
+              >
+                确认
+              </Button>
+            </div>
+          </div>
+        </Popup>
       </div>
     )
   }

+ 19 - 1
src/school/orchestra/compontent/photo.module.less

@@ -8,7 +8,13 @@
   border-radius: 10px;
   font-size: 16px;
 }
-
+.btnGroup{
+  display: flex;
+  padding: 12px;
+  .addPhone{
+    margin: 0 8px;
+  }
+}
 .phoneContainer {
   display: flex;
   justify-content: space-between;
@@ -81,3 +87,15 @@
   margin: 0 15px 30px;
   width: auto;
 }
+
+.photos {
+  padding: 0 16px 16px;
+}
+:global{
+  .van-image-preview{
+    .van-image-preview__close-icon,
+    .van-image-preview__index{
+      top: 50px
+    }
+  }
+}

+ 2 - 2
src/school/orchestra/compontent/plan.tsx

@@ -48,7 +48,7 @@ export default defineComponent({
       params: {
         startTime: dayjs(dayjs().year() + startTime.value).format('YYYY-MM-DD HH:mm:ss'),
         endTime: dayjs(dayjs().year() + endTime.value)
-          .subtract(1, 'year')
+          .add(1, 'year')
           .format('YYYY-MM-DD HH:mm:ss'),
         page: 1,
         rows: 20
@@ -121,7 +121,7 @@ export default defineComponent({
           return
         }
         const rows = result.rows || []
-        state.list = state.list.concat([])
+        state.list = state.list.concat(rows || [])
         state.listState.finished = result.current >= result.pages
         state.params.page = result.current + 1
         state.listState.dataShow = state.list.length > 0

+ 2 - 1
src/school/orchestra/create-orchestra/index.tsx

@@ -48,7 +48,8 @@ export default defineComponent({
           data: {
             page: 1,
             rows: 100,
-            schoolId: baseState.user.data.school.id
+            schoolId: baseState.user.data.school.id,
+            status: 'DONE'
           }
         })
         const temps = data.rows || []

+ 4 - 4
src/school/orchestra/modal/add-information.tsx

@@ -26,7 +26,7 @@ export default defineComponent({
       title: null,
       linkUrl: '',
       linkType: 'OUT',
-      memo: null
+      summary: null
     })
     const onSubmit = async () => {
       if (!forms.coverImage) {
@@ -35,7 +35,7 @@ export default defineComponent({
       } else if (!forms.title) {
         showToast('请输入资讯标题')
         return
-      } else if (!forms.memo) {
+      } else if (!forms.summary) {
         showToast('请输入内容简介')
         return
       } else if (!forms.linkUrl) {
@@ -76,7 +76,7 @@ export default defineComponent({
         forms.coverImage = selectItem.coverImage
         forms.title = selectItem.title
         forms.linkUrl = selectItem.linkUrl
-        forms.memo = selectItem.memo
+        forms.summary = selectItem.summary
       }
     })
 
@@ -100,7 +100,7 @@ export default defineComponent({
           type="textarea"
           rows={2}
           class={styles.field}
-          v-model={forms.memo}
+          v-model={forms.summary}
         />
 
         <div class={styles.title}>

+ 1 - 1
src/school/orchestra/orchestra-information.tsx

@@ -174,7 +174,7 @@ export default defineComponent({
                     title: () => (
                       <div>
                         <div class={[styles.title, 'van-ellipsis']}>{item.title}</div>
-                        <div class={[styles.content, 'van-multi-ellipsis--l2']}>{item.memo}</div>
+                        <div class={[styles.content, 'van-multi-ellipsis--l2']}>{item.summary}</div>
                         <div
                           style={{
                             display: 'flex',

+ 1 - 1
src/school/ranking-list/components/day-bang.tsx

@@ -126,7 +126,7 @@ export default defineComponent({
       //   .join(',')
       try {
         const res = await request.post('/api-school/orchestra/page', {
-          data: { page: 1, rows: 9999 }
+          data: { page: 1, rows: 9999, status: 'DONE' }
         })
         state.actions = res.data.rows.map((item) => {
           return {

+ 1 - 1
src/school/ranking-list/components/timer-bang.tsx

@@ -126,7 +126,7 @@ export default defineComponent({
       //   .join(',')
       try {
         const res = await request.post('/api-school/orchestra/page', {
-          data: { page: 1, rows: 9999 }
+          data: { page: 1, rows: 9999, status: 'DONE' }
         })
         state.actions = res.data.rows.map((item) => {
           return {

+ 3 - 1
src/school/school-detail/eidt-school.tsx

@@ -200,7 +200,6 @@ export default defineComponent({
               </Field>
               <Field
                 label-align="top"
-                v-model={forms.address}
                 maxlength={50}
                 placeholder="请选择学校地址"
                 disabled
@@ -212,6 +211,9 @@ export default defineComponent({
                     <p class={[styles.addP, styles.addDet]}>
                       学校地址 <Image width={19} height={18} src={locIcon}></Image>
                     </p>
+                  ),
+                  input: () => (
+                    <div style={{ paddingTop: '6px', paddingRight: '13px' }}>{forms.address}</div>
                   )
                 }}
               </Field>

+ 5 - 0
src/school/school-detail/index.module.less

@@ -118,6 +118,11 @@
       .van-cell {
         padding: 18px 12px;
       }
+      .van-field__control {
+        font-size: 16px;
+        color: #333;
+        line-height: 22px;
+      }
     }
   }
 }

+ 1 - 1
src/student/App.tsx

@@ -28,7 +28,7 @@ export default defineComponent({
               message: () => (
                 <>
                   <Vue3Lottie class={'toastAnimate'} animationData={AstronautJSON}></Vue3Lottie>
-                  <p>加载中...</p>
+                  {/* <p>加载中...</p> */}
                 </>
               )
             }}

BIN
src/student/member-center/images/icon-question.png


BIN
src/student/member-center/images/member_bg1.png


+ 29 - 0
src/student/member-center/index.module.less

@@ -29,6 +29,12 @@
       }
     }
   }
+  .beforMemberContainer {
+    padding-bottom: 12px !important;
+    .memberImgs {
+      margin-top: 8px;
+    }
+  }
   .level {
     width: 18px;
     height: 16px;
@@ -39,6 +45,29 @@
     width: auto;
     border-radius: 10px;
     padding: 20px 12px 30px;
+
+    &.purchaseMember {
+      background: url('./images/member_bg1.png') no-repeat center #ffce9a;
+      background-size: cover;
+      .userInfo {
+        color: #7a5420;
+      }
+
+      .beforeQuestion {
+        display: flex;
+        align-items: center;
+        font-size: 14px;
+        color: #7a5420;
+        line-height: 20px;
+        .iconQeustion {
+          font-size: 18px;
+          margin-right: 4px;
+        }
+        span {
+          color: #eb8000;
+        }
+      }
+    }
     .userImgSection {
       padding: 2px;
       border: 1px solid #feecd2;

+ 120 - 79
src/student/member-center/index.tsx

@@ -15,6 +15,8 @@ import OHeader from '@/components/o-header'
 import member1 from './images/member-1.png'
 import member2 from './images/member-2.png'
 import member3 from './images/member-3.png'
+import iconQuestion from './images/icon-question.png'
+import ODialog from '@/components/o-dialog'
 
 export const getAssetsHomeFile = (fileName: string) => {
   const path = `./images/${fileName}`
@@ -29,7 +31,8 @@ export default defineComponent({
     return {
       functionList: [] as any,
       selectMember: {} as any,
-      users: {} as any
+      users: {} as any,
+      memberStatus: false
     }
   },
   computed: {
@@ -51,40 +54,40 @@ export default defineComponent({
     try {
       const userInfo = await request.get('/api-student/student/member')
       this.users = userInfo.data || {}
-      this.functionList = [
-        {
-          title: '五线谱<br />跟播',
-          icon: getAssetsHomeFile(`1.png`)
-        },
-        {
-          title: '演奏指法<br />跟播',
-          icon: getAssetsHomeFile(`2.png`)
-        },
-        {
-          title: '原声/伴奏<br />切换',
-          icon: getAssetsHomeFile(`3.png`)
-        },
-        {
-          title: '播放速度<br />调整',
-          icon: getAssetsHomeFile(`4.png`)
-        },
-        {
-          title: '五线谱选段<br />播放',
-          icon: getAssetsHomeFile(`5.png`)
-        },
-        {
-          title: '智能评测',
-          icon: getAssetsHomeFile(`6.png`)
-        },
-        {
-          title: '评测报告',
-          icon: getAssetsHomeFile(`7.png`)
-        },
-        {
-          title: '评测音视频<br />云储存',
-          icon: getAssetsHomeFile(`8.png`)
-        }
-      ]
+      // this.functionList = [
+      //   {
+      //     title: '五线谱<br />跟播',
+      //     icon: getAssetsHomeFile(`1.png`)
+      //   },
+      //   {
+      //     title: '演奏指法<br />跟播',
+      //     icon: getAssetsHomeFile(`2.png`)
+      //   },
+      //   {
+      //     title: '原声/伴奏<br />切换',
+      //     icon: getAssetsHomeFile(`3.png`)
+      //   },
+      //   {
+      //     title: '播放速度<br />调整',
+      //     icon: getAssetsHomeFile(`4.png`)
+      //   },
+      //   {
+      //     title: '五线谱选段<br />播放',
+      //     icon: getAssetsHomeFile(`5.png`)
+      //   },
+      //   {
+      //     title: '智能评测',
+      //     icon: getAssetsHomeFile(`6.png`)
+      //   },
+      //   {
+      //     title: '评测报告',
+      //     icon: getAssetsHomeFile(`7.png`)
+      //   },
+      //   {
+      //     title: '评测音视频<br />云储存',
+      //     icon: getAssetsHomeFile(`8.png`)
+      //   }
+      // ]
 
       const { data } = await request.post(`/api-student/cityFeeSetting/member`)
       this.selectMember = data
@@ -188,7 +191,10 @@ export default defineComponent({
         <OHeader background="#ffe5cc" border={false} />
         <div class={styles.member_container}>
           <Cell
-            class={styles.userMember}
+            class={[
+              styles.userMember,
+              this.users.purchaseMemberRecord ? styles.purchaseMember : ''
+            ]}
             labelClass={styles.timeRemaining}
             center
             v-slots={{
@@ -217,13 +223,26 @@ export default defineComponent({
               ),
               label: () => (
                 <div class={styles.member_time}>
-                  {this.userInfo.isVip ? (
-                    <div>
-                      会员权益有效期剩余
-                      <span class={styles.remaining}>{this.userInfo.membershipDays}</span>天
-                    </div>
+                  {!this.users.purchaseMemberRecord ? (
+                    <>
+                      {this.userInfo.isVip ? (
+                        <div>
+                          会员权益有效期剩余
+                          <span class={styles.remaining}>{this.userInfo.membershipDays}</span>天
+                        </div>
+                      ) : (
+                        <div>亲,您还不是会员哟</div>
+                      )}
+                    </>
                   ) : (
-                    <div>亲,您还不是会员哟</div>
+                    <div class={styles.beforeQuestion}>
+                      <Icon
+                        name={iconQuestion}
+                        class={styles.iconQeustion}
+                        onClick={() => (this.memberStatus = true)}
+                      />
+                      您有<span>待激活</span>团练宝
+                    </div>
                   )}
                 </div>
               )
@@ -231,29 +250,38 @@ export default defineComponent({
           ></Cell>
         </div>
 
-        <div class={styles.memberContainer}>
+        <div
+          class={[
+            styles.memberContainer,
+            this.users.purchaseMemberRecord ? styles.beforMemberContainer : ''
+          ]}
+        >
           <div class={styles.memberItem}>
             <div class={styles.title}>
               会员<span>VIP</span>
             </div>
 
-            <div class={styles['system-list']}>
-              <div class={[styles['system-item'], styles.active]}>
-                <p class={[styles.title, 'van-hairline--bottom']}>
-                  半年会员
-                  <span>(6个月)</span>
-                </p>
-                <div class={styles.priceGroup}>
-                  <p class={styles.price}>
-                    <span>¥</span>
-                    {moneyFormat(this.selectMember.salePrice)}
+            {!this.users.purchaseMemberRecord ? (
+              <div class={styles['system-list']}>
+                <div class={[styles['system-item'], styles.active]}>
+                  <p class={[styles.title, 'van-hairline--bottom']}>
+                    半年会员
+                    <span>(6个月)</span>
                   </p>
-                  <del class={styles.originalPrice}>
-                    ¥{moneyFormat(this.selectMember.originalPrice)}
-                  </del>
+                  <div class={styles.priceGroup}>
+                    <p class={styles.price}>
+                      <span>¥</span>
+                      {moneyFormat(this.selectMember.salePrice)}
+                    </p>
+                    <del class={styles.originalPrice}>
+                      ¥{moneyFormat(this.selectMember.originalPrice)}
+                    </del>
+                  </div>
                 </div>
               </div>
-            </div>
+            ) : (
+              ''
+            )}
           </div>
           <div class={styles.memberImgs}>
             <img src={member1} />
@@ -280,30 +308,43 @@ export default defineComponent({
             </div>
           </div> */}
         </div>
-        <div class={styles.btnGroup}>
-          <div class={styles.priceSection}>
-            支付金额:
-            <div class={styles.price}>
-              <span class={styles.priceUnit}>¥</span>
-              <span class={styles.priceNum}>
-                {moneyFormat(this.calcSalePrice(this.selectMember) || 0)}
-              </span>
-            </div>
-            {this.selectMember?.discount == 1 && (
-              <div class={[styles.discountItem, styles.discountBuy]}>
-                <img src={iconDiscount} />
+        {!this.users.purchaseMemberRecord ? (
+          <div class={styles.btnGroup}>
+            <div class={styles.priceSection}>
+              支付金额:
+              <div class={styles.price}>
+                <span class={styles.priceUnit}>¥</span>
+                <span class={styles.priceNum}>
+                  {moneyFormat(this.calcSalePrice(this.selectMember) || 0)}
+                </span>
               </div>
-            )}
+              {this.selectMember?.discount == 1 && (
+                <div class={[styles.discountItem, styles.discountBuy]}>
+                  <img src={iconDiscount} />
+                </div>
+              )}
+            </div>
+            <Button
+              color="linear-gradient(220deg, #DFA164 0%, #FAC87E 100%)"
+              round
+              class={styles.btn}
+              onClick={this.onSubmit}
+            >
+              {this.userInfo.isVip ? '立即续费' : '立即开通'}
+            </Button>
           </div>
-          <Button
-            color="linear-gradient(220deg, #DFA164 0%, #FAC87E 100%)"
-            round
-            class={styles.btn}
-            onClick={this.onSubmit}
-          >
-            {this.userInfo.isVip ? '立即续费' : '立即开通'}
-          </Button>
-        </div>
+        ) : (
+          ''
+        )}
+        {/*  */}
+
+        <ODialog
+          v-model:show={this.memberStatus}
+          title="待激活团练宝"
+          message="为了避免团练宝会员时长浪费,报名乐团时购买的团练宝会员将在乐团首次训练结束后激活,具体训练时间请咨询乐团管理老师。"
+          messageAlign="left"
+          confirmButtonText="我知道了"
+        />
       </div>
     )
   }

+ 1 - 1
src/student/music-group/pre-apply/component/apply.tsx

@@ -165,7 +165,7 @@ export default defineComponent({
           }
         })
         setTimeout(() => {
-          showToast('报名成功')
+          // showToast('报名成功')
           emit('next', 'payment')
         }, 100)
       } catch {

+ 66 - 79
src/student/music-group/pre-apply/component/order.tsx

@@ -81,71 +81,71 @@ export default defineComponent({
       }
     }
 
-    const getDefaultParams = async () => {
-      try {
-        const { data } = await request.get('/api-student/sysParamConfig/queryByParamName', {
-          params: {
-            paramName: 'refund_reason'
-          }
-        })
-        const temp = data.paramValue.split('\n') || []
-        temp.forEach((item: any, index: number) => {
-          form.resionList.push({
-            text: item,
-            value: index + 1
-          })
-        })
-        form.resionList.push({
-          text: '其它原因',
-          value: 999
-        })
-        console.log(form.resionList, 'resionList')
-      } catch {
-        //
-      }
-    }
+    // const getDefaultParams = async () => {
+    //   try {
+    //     const { data } = await request.get('/api-student/sysParamConfig/queryByParamName', {
+    //       params: {
+    //         paramName: 'refund_reason'
+    //       }
+    //     })
+    //     const temp = data.paramValue.split('\n') || []
+    //     temp.forEach((item: any, index: number) => {
+    //       form.resionList.push({
+    //         text: item,
+    //         value: index + 1
+    //       })
+    //     })
+    //     form.resionList.push({
+    //       text: '其它原因',
+    //       value: 999
+    //     })
+    //     console.log(form.resionList, 'resionList')
+    //   } catch {
+    //     //
+    //   }
+    // }
 
-    // 确认退费
-    const onConfirmRefund = async () => {
-      try {
-        const status = form.checked === 999 && !form.resion
-        console.log(form.checked)
-        if (!form.checked) {
-          showToast('请选择原因')
-          return
-        } else if (status) {
-          showToast('请输入原因')
-          return
-        }
+    // // 确认退费
+    // const onConfirmRefund = async () => {
+    //   try {
+    //     const status = form.checked === 999 && !form.resion
+    //     console.log(form.checked)
+    //     if (!form.checked) {
+    //       showToast('请选择原因')
+    //       return
+    //     } else if (status) {
+    //       showToast('请输入原因')
+    //       return
+    //     }
 
-        const refundReason = form.resionList.find((item: any) => item.value === form.checked)
+    //     const refundReason = form.resionList.find((item: any) => item.value === form.checked)
 
-        console.log({
-          merOrderNo: form.refundSelect.orderNo,
-          refundReason: form.checked === 999 ? form.resion : refundReason.text
-        })
+    //     console.log({
+    //       merOrderNo: form.refundSelect.orderNo,
+    //       refundReason: form.checked === 999 ? form.resion : refundReason.text
+    //     })
 
-        await request.post('/api-student/userPaymentOrder/refundPayment', {
-          data: {
-            merOrderNo: form.refundSelect.orderNo,
-            refundReason: form.checked === 999 ? form.resion : refundReason.text
-          }
-        })
-        form.refundStatus = false
-        onSearch()
-      } catch {
-        //
-      }
-    }
+    //     await request.post('/api-student/userPaymentOrder/refundPayment', {
+    //       data: {
+    //         merOrderNo: form.refundSelect.orderNo,
+    //         refundReason: form.checked === 999 ? form.resion : refundReason.text
+    //       }
+    //     })
+    //     form.refundStatus = false
+    //     onSearch()
+    //   } catch {
+    //     //
+    //   }
+    // }
 
-    const onSearch = () => {
-      form.params.page = 1
-      form.list = []
-      form.listState.dataShow = true // 判断是否有数据
-      form.listState.loading = false
-      form.listState.finished = false
-      getList()
-    }
+    // const onSearch = () => {
+    //   form.params.page = 1
+    //   form.list = []
+    //   form.listState.dataShow = true // 判断是否有数据
+    //   form.listState.loading = false
+    //   form.listState.finished = false
+    //   getList()
+    // }
 
     // 查看详情
     const onDetails = (item: any) => {
@@ -158,7 +158,7 @@ export default defineComponent({
     }
 
     onMounted(() => {
-      getDefaultParams()
+      // getDefaultParams()
       getList()
     })
 
@@ -215,27 +215,14 @@ export default defineComponent({
                     )
                   }}
                 </Cell>
-                {item.refundable && (
+                {/* {item.refundable && (
                   <Cell class={styles.btnGroup} center>
                     {{
                       title: () => (
-                        <span class={styles.btnPrice}>
-                          {/* ¥{moneyFormat(item.currentPrice)} */}
-                        </span>
+                        <span class={styles.btnPrice}>¥{moneyFormat(item.currentPrice)}</span>
                       ),
                       value: () => (
                         <div class={styles.btns}>
-                          {/* {item.status === 'WAIT_PAY' && (
-                          <>
-                            <Button round plain color="#AAAAAA">
-                              修改订单
-                            </Button>
-                            <Button round plain color="#FF8057">
-                              继续支付
-                            </Button>
-                          </>
-                        )} */}
-                          {/* 订单成功 订单金额大于0 */}
                           <Button
                             round
                             plain
@@ -252,7 +239,7 @@ export default defineComponent({
                       )
                     }}
                   </Cell>
-                )}
+                )} */}
               </CellGroup>
             ))}
           </List>
@@ -260,7 +247,7 @@ export default defineComponent({
           <OEmpty btnStatus={false} tips="暂无订单" />
         )}
 
-        <Popup v-model:show={form.refundStatus} round style={{ width: '90%' }}>
+        {/* <Popup v-model:show={form.refundStatus} round style={{ width: '90%' }}>
           <div class={styles.container}>
             <div class={[styles.dialogTitle, styles.dialogRefund]}>
               <i></i>
@@ -316,7 +303,7 @@ export default defineComponent({
               </Button>
             </div>
           </div>
-        </Popup>
+        </Popup> */}
       </div>
     )
   }

+ 3 - 1
src/student/music-group/pre-apply/order-detail.tsx

@@ -177,6 +177,8 @@ export default defineComponent({
           // console.log(data)
           if (data.status !== 'WAIT_PAY' && data.status !== 'PAYING') {
             clearInterval(orderTimer)
+            // 默认关闭支付二维码弹窗
+            state.showQrcode = false
             window.location.replace(
               window.location.origin +
                 '/orchestra-student/#/payment-result?orderNo=' +
@@ -282,7 +284,7 @@ export default defineComponent({
         return
       }
       const users = baseState.user.data
-
+      console.group(users)
       // 判断是否需要实名认证, 姓名,卡号
       if (!users?.account.realName || !users?.account.idCardNo) {
         state.authShow = true

+ 1 - 1
src/student/music-group/shop-address/index.tsx

@@ -3,9 +3,9 @@ import { defineComponent, onMounted, onUpdated, reactive } from 'vue'
 import styles from './index.module.less'
 import iconEdit from '../pre-apply/images/icon-edit.png'
 import OSticky from '@/components/o-sticky'
-import request from '../request-music'
 import OEmpty from '@/components/o-empty'
 import { useRouter } from 'vue-router'
+import request from '@/helpers/request'
 
 export default defineComponent({
   name: 'shop-address',

+ 64 - 1
src/student/payment-result/index.module.less

@@ -58,7 +58,8 @@
   .buyDetail {
     display: flex;
     align-items: center;
-    padding: 18px 0 0 18px;
+    justify-content: space-between;
+    padding: 18px 18px 0;
     i {
       display: inline-block;
       margin-right: 6px;
@@ -71,6 +72,16 @@
     font-weight: 500;
     color: #333333;
     line-height: 22px;
+
+    .buyDetailTitle {
+      display: flex;
+      align-items: center;
+    }
+    .refundBtn {
+      font-size: 16px;
+      color: #777777;
+      line-height: 22px;
+    }
   }
 
   .buyImg {
@@ -81,3 +92,55 @@
     margin-right: 9px;
   }
 }
+
+.container {
+  :global {
+    .van-button {
+      font-size: 18px;
+      font-weight: 500;
+    }
+  }
+}
+
+.dialogTitle {
+  i {
+    display: inline-block;
+    width: 4px;
+    height: 14px;
+    background: #ff8057;
+    border-radius: 2px;
+    margin-right: 6px;
+  }
+
+  text-align: left;
+  font-size: 18px;
+  font-weight: 500;
+  color: #333333;
+  line-height: 25px;
+  padding: 20px 0 15px 25px;
+}
+
+.refundContent {
+  padding: 0 20px 25px;
+  .tips {
+    font-size: 15px;
+    color: #333333;
+    line-height: 21px;
+  }
+}
+
+.refundTitle {
+  padding-top: 25px;
+  font-size: 16px;
+  font-weight: 600;
+  color: #333333;
+  line-height: 22px;
+  span {
+    color: #f44541;
+  }
+}
+
+.phoneName {
+  background: #f2f2f2;
+  border-radius: 6px;
+}

+ 147 - 2
src/student/payment-result/index.tsx

@@ -1,6 +1,18 @@
 import OHeader from '@/components/o-header'
 import { defineComponent, onMounted, reactive, ref } from 'vue'
-import { Button, Cell, CellGroup, Image, showConfirmDialog, Tag } from 'vant'
+import {
+  Button,
+  Cell,
+  CellGroup,
+  Field,
+  Image,
+  Popup,
+  Radio,
+  RadioGroup,
+  showConfirmDialog,
+  showToast,
+  Tag
+} from 'vant'
 import styles from './index.module.less'
 import iconRefunding from './images/icon_refunding.png'
 import icon_success from './images/icon_success.png'
@@ -24,6 +36,13 @@ export default defineComponent({
       color: '#fff',
       backIconColor: 'white' as any
     })
+    const form = reactive({
+      resionList: [] as any,
+      refundStatus: false,
+      resion: null,
+      refundSelect: {} as any,
+      checked: null as any
+    })
     const getDetails = async () => {
       try {
         if (!route.query.orderNo) return
@@ -85,8 +104,62 @@ export default defineComponent({
       return temp[status]
     }
 
+    const getDefaultParams = async () => {
+      try {
+        const { data } = await request.get('/api-student/sysParamConfig/queryByParamName', {
+          params: {
+            paramName: 'refund_reason'
+          }
+        })
+        const temp = data.paramValue.split('\n') || []
+        temp.forEach((item: any, index: number) => {
+          form.resionList.push({
+            text: item,
+            value: index + 1
+          })
+        })
+        form.resionList.push({
+          text: '其它原因',
+          value: 999
+        })
+        console.log(form.resionList, 'resionList')
+      } catch {
+        //
+      }
+    }
+
+    // 确认退费
+    const onConfirmRefund = async () => {
+      try {
+        const status = form.checked === 999 && !form.resion
+        console.log(form.checked)
+        if (!form.checked) {
+          showToast('请选择原因')
+          return
+        } else if (status) {
+          showToast('请输入原因')
+          return
+        }
+
+        const refundReason = form.resionList.find((item: any) => item.value === form.checked)
+
+        await request.post('/api-student/userPaymentOrder/refundPayment', {
+          data: {
+            merOrderNo: route.query.orderNo,
+            refundReason: form.checked === 999 ? form.resion : refundReason.text
+          }
+        })
+
+        form.refundStatus = false
+        getDetails()
+      } catch {
+        //
+      }
+    }
+
     onMounted(() => {
       getDetails()
+      getDefaultParams()
       useEventListener(document, 'scroll', () => {
         const { y } = useWindowScroll()
         if (y.value > 52) {
@@ -148,7 +221,21 @@ export default defineComponent({
 
         <CellGroup inset class={styles.cellGroup}>
           <div class={styles.buyDetail}>
-            <i></i> 购买详情
+            <div class={styles.buyDetailTitle}>
+              <i></i> 购买详情
+            </div>
+            {state.orders.refundable ? (
+              <div
+                class={styles.refundBtn}
+                onClick={() => {
+                  form.refundStatus = true
+                }}
+              >
+                申请退费
+              </div>
+            ) : (
+              ''
+            )}
           </div>
           {state.goodsInfos.map((goods: any) => (
             <Cell>
@@ -179,6 +266,64 @@ export default defineComponent({
             </Button>
           </div>
         )}
+
+        <Popup v-model:show={form.refundStatus} round style={{ width: '90%' }}>
+          <div class={styles.container}>
+            <div class={styles.dialogTitle}>
+              <i></i>
+              申请退款
+            </div>
+
+            <div class={styles.refundContent}>
+              <div class={styles.tips}>
+                您将要发起退款,退款需承担千分之六的手续费,确认退款后款项将原路返还到您的付款账户中。
+              </div>
+
+              <div class={styles.refundTitle}>
+                <span>*</span>请选择您的退款原因
+              </div>
+
+              <RadioGroup v-model={form.checked}>
+                {form.resionList &&
+                  form.resionList.map((item: any) => (
+                    <Cell style="padding: 16px 0;" onClick={() => (form.checked = item.value)}>
+                      {{
+                        icon: () => <Radio name={item.value} />,
+                        title: () => <span style={'padding-left: 6px'}>{item.text}</span>
+                      }}
+                    </Cell>
+                  ))}
+              </RadioGroup>
+              {form.checked === 999 && (
+                <Field
+                  class={styles.phoneName}
+                  v-model={form.resion}
+                  placeholder="请输入原因"
+                  maxlength={50}
+                  type="textarea"
+                  rows={2}
+                />
+              )}
+            </div>
+
+            <div class={['van-hairline--top van-dialog__footer']}>
+              <Button
+                onClick={onConfirmRefund}
+                class={['van-button van-button--default van-button--large van-dialog__cancel']}
+              >
+                确认退款
+              </Button>
+              <Button
+                onClick={() => (form.refundStatus = false)}
+                class={[
+                  'van-button van-button--default van-button--large van-dialog__confirm van-hairline--left'
+                ]}
+              >
+                取消
+              </Button>
+            </div>
+          </div>
+        </Popup>
       </div>
     )
   }

+ 7 - 118
src/student/trade-record/component/paid-list.tsx

@@ -74,11 +74,12 @@ export default defineComponent({
     // REFUNDING: '退款中',
     // REFUNDED: '已退款'
 
-    const getList = async () => {
+    const getList = async (hideLoading = false) => {
       try {
         if (form.isClick) return
         form.isClick = true
         const res = await request.post('/api-student/userPaymentOrder/page', {
+          hideLoading: hideLoading,
           data: {
             ...form.params,
             orderType: form.currentType === 'ALL' ? null : form.currentType,
@@ -105,13 +106,13 @@ export default defineComponent({
       }
     }
 
-    const onSearch = () => {
+    const onSearch = (hideLoading = false) => {
       form.params.page = 1
       form.list = []
       form.listState.dataShow = true // 判断是否有数据
       form.listState.loading = false
       form.listState.finished = false
-      getList()
+      getList(hideLoading)
     }
 
     const formatOrderType = (orderType: string) => {
@@ -124,59 +125,6 @@ export default defineComponent({
       return select.text
     }
 
-    const getDefaultParams = async () => {
-      try {
-        const { data } = await request.get('/api-student/sysParamConfig/queryByParamName', {
-          params: {
-            paramName: 'refund_reason'
-          }
-        })
-        const temp = data.paramValue.split('\n') || []
-        temp.forEach((item: any, index: number) => {
-          form.resionList.push({
-            text: item,
-            value: index + 1
-          })
-        })
-        form.resionList.push({
-          text: '其它原因',
-          value: 999
-        })
-        console.log(form.resionList, 'resionList')
-      } catch {
-        //
-      }
-    }
-
-    // 确认退费
-    const onConfirmRefund = async () => {
-      try {
-        const status = form.checked === 999 && !form.resion
-        console.log(form.checked)
-        if (!form.checked) {
-          showToast('请选择原因')
-          return
-        } else if (status) {
-          showToast('请输入原因')
-          return
-        }
-
-        const refundReason = form.resionList.find((item: any) => item.value === form.checked)
-
-        await request.post('/api-student/userPaymentOrder/refundPayment', {
-          data: {
-            merOrderNo: form.refundSelect.orderNo,
-            refundReason: form.checked === 999 ? form.resion : refundReason.text
-          }
-        })
-
-        form.refundStatus = false
-        onSearch()
-      } catch {
-        //
-      }
-    }
-
     const onDetails = (item: any) => {
       router.push({
         path: 'payment-result',
@@ -188,7 +136,6 @@ export default defineComponent({
 
     onMounted(() => {
       getList()
-      getDefaultParams()
 
       Object.keys(orderType).forEach((key) => {
         form.typeArray.push({
@@ -221,7 +168,7 @@ export default defineComponent({
         {form.listState.dataShow ? (
           <OFullRefresh
             v-model:modelValue={form.listState.refreshing}
-            onRefresh={onSearch}
+            onRefresh={() => onSearch(true)}
             style={{
               minHeight: `calc(100vh - ${form.listState.height}px)`
             }}
@@ -254,7 +201,7 @@ export default defineComponent({
                       )
                     }}
                   </Cell>
-                  <Cell style={'padding: 0'}>
+                  {/* <Cell style={'padding: 0'}>
                     {{
                       title: () =>
                         item.refundable && (
@@ -271,7 +218,7 @@ export default defineComponent({
                           </Button>
                         )
                     }}
-                  </Cell>
+                  </Cell> */}
                 </CellGroup>
               ))}
             </List>
@@ -304,64 +251,6 @@ export default defineComponent({
             }}
           />
         </Popup>
-
-        <Popup v-model:show={form.refundStatus} round style={{ width: '90%' }}>
-          <div class={styles.container}>
-            <div class={styles.dialogTitle}>
-              <i></i>
-              申请退款
-            </div>
-
-            <div class={styles.refundContent}>
-              <div class={styles.tips}>
-                您将要发起退款,退款需承担千分之六的手续费,确认退款后款项将原路返还到您的付款账户中。
-              </div>
-
-              <div class={styles.refundTitle}>
-                <span>*</span>请选择您的退款原因
-              </div>
-
-              <RadioGroup v-model={form.checked}>
-                {form.resionList &&
-                  form.resionList.map((item: any) => (
-                    <Cell style="padding: 16px 0;" onClick={() => (form.checked = item.value)}>
-                      {{
-                        icon: () => <Radio name={item.value} />,
-                        title: () => <span style={'padding-left: 6px'}>{item.text}</span>
-                      }}
-                    </Cell>
-                  ))}
-              </RadioGroup>
-              {form.checked === 999 && (
-                <Field
-                  class={styles.phoneName}
-                  v-model={form.resion}
-                  placeholder="请输入原因"
-                  maxlength={50}
-                  type="textarea"
-                  rows={2}
-                />
-              )}
-            </div>
-
-            <div class={['van-hairline--top van-dialog__footer']}>
-              <Button
-                onClick={onConfirmRefund}
-                class={['van-button van-button--default van-button--large van-dialog__cancel']}
-              >
-                确认退款
-              </Button>
-              <Button
-                onClick={() => (form.refundStatus = false)}
-                class={[
-                  'van-button van-button--default van-button--large van-dialog__confirm van-hairline--left'
-                ]}
-              >
-                取消
-              </Button>
-            </div>
-          </div>
-        </Popup>
       </div>
     )
   }

+ 5 - 4
src/student/trade-record/component/refund-list.tsx

@@ -42,11 +42,12 @@ export default defineComponent({
       }
     })
 
-    const getList = async () => {
+    const getList = async (hideLoading = false) => {
       try {
         if (form.isClick) return
         form.isClick = true
         const res = await request.post('/api-student/userPaymentOrder/page', {
+          hideLoading: hideLoading,
           data: {
             ...form.params,
             orderType: form.currentType === 'ALL' ? null : form.currentType,
@@ -73,13 +74,13 @@ export default defineComponent({
       }
     }
 
-    const onSearch = () => {
+    const onSearch = (hideLoading = false) => {
       form.params.page = 1
       form.list = []
       form.listState.dataShow = true // 判断是否有数据
       form.listState.loading = false
       form.listState.finished = false
-      getList()
+      getList(hideLoading)
     }
 
     const formatOrderType = (orderType: string) => {
@@ -134,7 +135,7 @@ export default defineComponent({
         {form.listState.dataShow ? (
           <OFullRefresh
             v-model:modelValue={form.listState.refreshing}
-            onRefresh={onSearch}
+            onRefresh={() => onSearch(true)}
             style={{
               minHeight: `calc(100vh - ${form.listState.height}px)`
             }}

+ 5 - 4
src/student/trade-record/component/wait-pay.tsx

@@ -54,11 +54,12 @@ export default defineComponent({
       }
     })
 
-    const getList = async () => {
+    const getList = async (hideLoading = false) => {
       try {
         if (form.isClick) return
         form.isClick = true
         const res = await request.post('/api-student/userPaymentOrder/page', {
+          hideLoading: hideLoading,
           data: {
             ...form.params,
             orderType: form.currentType === 'ALL' ? null : form.currentType,
@@ -85,13 +86,13 @@ export default defineComponent({
       }
     }
 
-    const onSearch = () => {
+    const onSearch = (hideLoading = false) => {
       form.params.page = 1
       form.list = []
       form.listState.dataShow = true // 判断是否有数据
       form.listState.loading = false
       form.listState.finished = false
-      getList()
+      getList(hideLoading)
     }
 
     const formatOrderType = (orderType: string) => {
@@ -184,7 +185,7 @@ export default defineComponent({
         {form.listState.dataShow ? (
           <OFullRefresh
             v-model:modelValue={form.listState.refreshing}
-            onRefresh={onSearch}
+            onRefresh={() => onSearch(false)}
             style={{
               minHeight: `calc(100vh - ${form.listState.height}px)`
             }}

+ 14 - 5
src/styles/index.less

@@ -193,20 +193,29 @@ body {
 }
 
 .appRootToast {
-  // .van-overlay {
-  //   background: rgba(0, 0, 0, 0.4);
-  // }
+  .van-overlay {
+    // background: rgba(0, 0, 0, 0.4);
+    background: #fff;
+    // transition: all 0 ease;
+  }
+  .van-fade-enter-from,
+  .van-fade-enter-active {
+    animation: none;
+  }
   .van-toast__text {
     width: 100px;
     height: 100px;
-    color: #333;
+    color: #fff;
     display: flex;
     align-items: center;
     flex-direction: column;
     justify-content: center;
   }
   .van-toast--text {
-    background-color: #fff;
+    // background-color: rgba(255, 255, 255, 1);
+    // background-color: rgba(0, 0, 0, 0.9);
+    background-color: transparent;
+    // box-shadow: 0px 8px 20px 2px #f0f0f0;
   }
   .toastAnimate {
     width: 70px;

+ 1 - 1
src/teacher/App.tsx

@@ -28,7 +28,7 @@ export default defineComponent({
               message: () => (
                 <>
                   <Vue3Lottie class={'toastAnimate'} animationData={AstronautJSON}></Vue3Lottie>
-                  <p>加载中...</p>
+                  {/* <p>加载中...</p> */}
                 </>
               )
             }}

+ 1 - 1
src/teacher/attendance/index.tsx

@@ -124,7 +124,7 @@ export default defineComponent({
     const getOrchestraList = async () => {
       try {
         const res = await request.post('/api-teacher/orchestra/page', {
-          data: { page: 1, rows: 9999 }
+          data: { page: 1, rows: 9999, status: 'DONE' }
         })
         state.actions = res.data.rows.map((item) => {
           return {

+ 2 - 1
src/views/404/index.tsx

@@ -8,6 +8,7 @@ import { browser } from '@/helpers/utils'
 export default defineComponent({
   name: 'NotFound',
   render() {
+    postMessage({ api: 'setBarStatus', content: { status: 0 } })
     return (
       <div class={styles.f404}>
         <Image src={img404} />
@@ -17,7 +18,7 @@ export default defineComponent({
           plain
           round
           onClick={() => {
-            if (browser().iPhone) {
+            if (browser().isApp) {
               postMessage({ api: 'back' })
             } else {
               this.$router.back()

+ 8 - 8
src/views/courseList/index.tsx

@@ -48,7 +48,6 @@ export default defineComponent({
             state.platformApi + '/courseSchedule/myCoursewareDetail/' + route.query.id
           )
           if (Array.isArray(res?.data)) {
-            // data.list = res.data
             data.list = browserInfo.isApp ? await checkCoursewareCache(res.data) : res.data
           }
         } catch (error) {}
@@ -64,18 +63,19 @@ export default defineComponent({
     })
 
     const handleClick = async (item: any) => {
+      if (!item.knowledgePointList) {
+        showConfirmDialog({
+          message: '该课件暂无知识点'
+        })
+        return
+      }
       if (route.query.code === 'select') {
         console.log('选择课时')
         setCoursewareDetail(item)
         return
       }
+
       if (!item.hasCache) {
-        if (!item.knowledgePointList) {
-          showConfirmDialog({
-            message: '该课件暂无知识点'
-          })
-          return
-        }
         if (browserInfo.isStudent || route.query.isdev) {
           try {
             await showConfirmDialog({
@@ -214,7 +214,7 @@ export default defineComponent({
                     <div class={styles.num}>选择</div>
                   )}
 
-                  {route.query.code == 'select' && !item.unlock && (
+                  {(route.query.code == 'select' || state.platformType == 'STUDENT') && !item.unlock && (
                     <div class={styles.look} onClick={(e: Event) => e.stopPropagation()}>
                       <Icon name={iconLook} /> 未解锁
                     </div>

+ 14 - 9
src/views/coursewarePlay/index.tsx

@@ -168,7 +168,7 @@ export default defineComponent({
         )
         if (res?.data) {
           data.isCourse =
-          res.data.status === 'ING' && state.platformType == 'TEACHER' ? true : false
+            res.data.status === 'ING' && state.platformType == 'TEACHER' ? true : false
           data.isRecordPlay = Date.now() > dayjs(res.data.startTime).valueOf()
         }
       } catch (e) {
@@ -240,14 +240,16 @@ export default defineComponent({
       }
       // console.log('🚀 ~ list', list)
       data.itemList = list
+      nextTick(() => {
+        postMessage({
+          api: 'courseLoading',
+          content: {
+            show: false,
+            type: 'fullscreen'
+          }
+        })
+      })
       // setTimeout(() => {
-      //   postMessage({
-      //     api: 'courseLoading',
-      //     content: {
-      //       show: false,
-      //       type: 'fullscreen'
-      //     }
-      //   })
       // }, 300)
     }
     const getDetail = async () => {
@@ -301,6 +303,7 @@ export default defineComponent({
       } catch (error) {}
       if (route.query.source == 'my-course') {
         router.back()
+        return
       }
       postMessage({ api: 'goBack' })
     }
@@ -641,7 +644,9 @@ export default defineComponent({
               返回
             </div>
             <div class={styles.menu}>{popupData.tabName}</div>
-            {data.isCourse && data.isRecordPlay && <PlayRecordTime ref={playRef} list={data.itemList} />}
+            {data.isCourse && data.isRecordPlay && (
+              <PlayRecordTime ref={playRef} list={data.itemList} />
+            )}
           </div>
 
           <Transition name="right">

+ 198 - 182
src/views/exercise-after-class/index.module.less

@@ -1,203 +1,219 @@
+.playContent {
+  width: 100vw;
+  height: 100vh;
+  background-color: #000;
+  overflow: hidden;
+}
 .coursewarePlay {
-    position: relative;
-    height: 100vh;
-    background-color: rgba(89, 98, 126, 0.2);
-  }
-  .playModel {
-    position: absolute;
-    left: 0;
-    top: 0;
-    right: 0;
-    bottom: 0;
-    box-shadow: inset 0px 0px 164px 0px rgba(0, 0, 0, 1);
-    pointer-events: none;
-  }
-  .headerContainer {
-    position: fixed;
-    top: 0;
-    left: 0;
-    right: 0;
-    z-index: 1;
-    padding: 10px 24px;
-    display: flex;
-    align-items: center;
-    color: #fff;
-    font-size: 12px;
-    background: linear-gradient(180deg, rgba(0, 0, 0, .6), transparent);
-  }
-  .backBtn {
-    color: #fff;
-    width: 40px;
-    height: 26px;
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
-    z-index: 10;
-  }
-  .menu {
-    flex: 1;
-    display: flex;
-    justify-content: center;
-    color: #fff;
-  }
-  .tabsContent {
-    width: 100vw;
-    height: 100vh;
-    :global {
-      .van-tabs__wrap {
-        display: none !important;
-      }
-      .van-tabs__content {
-        width: 100%;
-        height: 100%;
-      }
-    }
-  }
-  .itemDiv {
-    position: relative;
-    width: 100%;
-    height: 100%;
-    video {
-      width: 100%;
-      height: 100%;
+  position: relative;
+  height: 100vh;
+  margin: 0 auto;
+}
+.playModel {
+  position: absolute;
+  left: 0;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  box-shadow: inset 0px 0px 164px 0px rgba(0, 0, 0, 1);
+  pointer-events: none;
+}
+.headerContainer {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  z-index: 1;
+  padding: 10px 24px;
+  display: flex;
+  align-items: center;
+  color: #fff;
+  font-size: 12px;
+  background: linear-gradient(180deg, rgba(0, 0, 0, 0.6), transparent);
+}
+.backBtn {
+  color: #fff;
+  width: 40px;
+  height: 26px;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  z-index: 10;
+}
+.menu {
+  flex: 1;
+  display: flex;
+  justify-content: center;
+  color: #fff;
+}
+.tabsContent {
+  width: 100vw;
+  height: 100vh;
+  :global {
+    .van-tabs__wrap {
+      display: none !important;
     }
-    img {
-      display: block;
+    .van-tabs__content {
       width: 100%;
       height: 100%;
-      object-fit: contain;
     }
   }
-  .videoModel{
-    position: absolute;
-    top: 0;
-    left: 0;
+}
+.loadWrap {
+  position: absolute;
+  left: 0;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  background: linear-gradient(45deg, #21232a, #111218);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+.itemDiv {
+  position: relative;
+  width: 100%;
+  height: 100%;
+  video {
     width: 100%;
     height: 100%;
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    & > img{
-      width: 50px;
-      height: 50px;
-    }
   }
-  .rightFixedBtns {
-    position: fixed;
-    top: 50%;
-    transform: translateY(-50%);
-    right: 20px;
-    .point {
-      margin-top: 10px;
-      border-bottom-left-radius: 0;
-      border-bottom-right-radius: 0;
-    }
-    .point + .fullBtn {
-      border-top-left-radius: 0;
-      border-top-right-radius: 0;
-    }
+  img {
+    display: block;
+    width: 100%;
+    height: 100%;
+    object-fit: contain;
   }
-  .leftFixedBtns {
-    position: fixed;
-    top: 50%;
-    transform: translateY(-50%);
-    left: 20px;
-    .prePoint {
-      margin-bottom: 8px;
-    }
+}
+.videoModel {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  & > img {
+    width: 50px;
+    height: 50px;
+  }
+}
+.rightFixedBtns {
+  position: fixed;
+  top: 50%;
+  transform: translateY(-50%);
+  right: 20px;
+  .point {
+    margin-top: 10px;
+    border-bottom-left-radius: 0;
+    border-bottom-right-radius: 0;
   }
-  .fullBtn {
-    width: 38px;
-    height: 55px;
-    background: rgba(51, 51, 51, 0.15);
-    border-radius: 8px;
+  .point + .fullBtn {
+    border-top-left-radius: 0;
+    border-top-right-radius: 0;
+  }
+}
+.leftFixedBtns {
+  position: fixed;
+  top: 50%;
+  transform: translateY(-50%);
+  left: 20px;
+  .prePoint {
+    margin-bottom: 8px;
+  }
+}
+.fullBtn {
+  width: 38px;
+  height: 55px;
+  background: rgba(51, 51, 51, 0.15);
+  border-radius: 8px;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  color: #fff;
+  justify-content: space-evenly;
+  &:active {
+    opacity: 0.8;
+  }
+}
+.bottomFixedContainer {
+  position: absolute;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  z-index: 10;
+  background: linear-gradient(0deg, rgba(0, 0, 0, 0.5), transparent);
+  padding: 0 30px;
+  .time {
     display: flex;
-    flex-direction: column;
-    align-items: center;
+    justify-content: space-between;
     color: #fff;
-    justify-content: space-evenly;
-    &:active {
-      opacity: 0.8;
-    }
+    font-size: 10px;
+    padding: 4px 0;
   }
-  .bottomFixedContainer {
-    position: absolute;
-    left: 0;
-    right: 0;
-    bottom: 0;
-    z-index: 10;
-    background: linear-gradient(0deg, rgba(0, 0, 0, 0.5), transparent);
-    padding: 0 30px;
-    .time {
+  .slider {
+    padding: 10px 0;
+  }
+  .actions {
+    display: flex;
+    justify-content: space-between;
+    color: #fff;
+    font-size: 12px;
+    align-items: center;
+    .actionBtn {
       display: flex;
-      justify-content: space-between;
-      color: #fff;
-      font-size: 10px;
-      padding: 4px 0;
     }
-    .slider {
-      padding: 10px 0;
-    }
-    .actions {
-      display: flex;
-      justify-content: space-between;
-      color: #fff;
-      font-size: 12px;
-      align-items: center;
-      .actionBtn{
-        display: flex;
-      }
-      .actionBtn > img {
-        width: 26px;
-        height: 26px;
-        display: block;
-        padding: 8px 8px 14px 8px;
-      }
+    .actionBtn > img {
+      width: 26px;
+      height: 26px;
+      display: block;
+      padding: 8px 8px 14px 8px;
     }
   }
-  .popup {
-    background: rgba(0, 0, 0, 0.5);
+}
+.popup {
+  background: rgba(0, 0, 0, 0.5);
+}
+.overlayClass {
+  --van-overlay-background: transparent;
+}
+:global {
+  .top-enter-active,
+  .top-leave-active {
+    transition: transform 0.5s;
   }
-  .overlayClass {
-    --van-overlay-background: transparent;
+  .top-enter-from,
+  .top-leave-to {
+    transform: translateY(-100%);
   }
-  :global {
-    .top-enter-active,
-    .top-leave-active {
-      transition: transform 0.5s;
-    }
-    .top-enter-from,
-    .top-leave-to {
-      transform: translateY(-100%);
-    }
-  
-    .left-enter-active,
-    .left-leave-active {
-      transition: all 0.5s;
-    }
-    .left-enter-from,
-    .left-leave-to {
-      left: -60px;
-    }
-  
-    .right-enter-active,
-    .right-leave-active {
-      transition: all 0.5s;
-    }
-  
-    .right-enter-from,
-    .right-leave-to {
-      right: -60px;
-    }
-  
-    .bottom-enter-active,
-    .bottom-leave-active {
-      transition: transform 0.5s;
-    }
-  
-    .bottom-enter-from,
-    .bottom-leave-to {
-      transform: translateY(100%);
-    }
+
+  .left-enter-active,
+  .left-leave-active {
+    transition: all 0.5s;
+  }
+  .left-enter-from,
+  .left-leave-to {
+    left: -60px;
+  }
+
+  .right-enter-active,
+  .right-leave-active {
+    transition: all 0.5s;
+  }
+
+  .right-enter-from,
+  .right-leave-to {
+    right: -60px;
+  }
+
+  .bottom-enter-active,
+  .bottom-leave-active {
+    transition: transform 0.5s;
+  }
+
+  .bottom-enter-from,
+  .bottom-leave-to {
+    transform: translateY(100%);
   }
-  
+}

+ 213 - 206
src/views/exercise-after-class/index.tsx

@@ -1,10 +1,4 @@
-import {
-  Icon,
-  showConfirmDialog,
-  Slider,
-  Swipe,
-  SwipeItem
-} from 'vant'
+import { Icon, showConfirmDialog, Slider, Swipe, SwipeItem } from 'vant'
 import {
   defineComponent,
   onMounted,
@@ -13,6 +7,8 @@ import {
   ref,
   watch,
   Transition,
+  nextTick,
+  computed
 } from 'vue'
 import styles from './index.module.less'
 import 'plyr/dist/plyr.css'
@@ -28,6 +24,8 @@ import iconpause from '../coursewarePlay/image/icon-pause.svg'
 import iconVideobg from '../coursewarePlay/image/icon-videobg.png'
 import { browser, getSecondRPM } from '@/helpers/utils'
 import qs from 'query-string'
+import { Vue3Lottie } from 'vue3-lottie'
+import playLoadData from '../coursewarePlay/datas/data.json'
 
 const materialType = {
   视频: 'VIDEO',
@@ -38,7 +36,23 @@ const materialType = {
 export default defineComponent({
   name: 'exercise-after-class',
   setup() {
+    /** 设置播放容器 16:9 */
+    const parentContainer = reactive({
+      width: '100vw'
+    })
+    const setContainer = () => {
+      let min = Math.min(screen.width, screen.height)
+      let max = Math.max(screen.width, screen.height)
+      let width = min * (16 / 9)
+      if (width > max) {
+        parentContainer.width = '100vw'
+        return
+      } else {
+        parentContainer.width = width + 'px'
+      }
+    }
     const handleInit = (type = 0) => {
+      setContainer()
       // 横屏
       postMessage({
         api: 'setRequestedOrientation',
@@ -67,20 +81,13 @@ export default defineComponent({
     })
 
     const route = useRoute()
-    watch(
-      () => route.query,
-      () => {
-        getDetail()
-        trainingRecord()
-      }
-    )
     const router = useRouter()
     const query = route.query
     const browserInfo = browser()
     const headeRef = ref()
     const data = reactive({
       videoData: null as any,
-      details: [] as any,
+      trainings: [] as any[],
       trainingTimes: 0,
       itemList: [] as any,
       showHead: true,
@@ -93,71 +100,50 @@ export default defineComponent({
       timer: null as any,
       item: null as any
     })
-    const getDetail = async () => {
-      data.itemList = []
-      let details = []
-      try {
-        const res: any = await request.get(
-          state.platformApi + `/lessonTraining/courseSchedule/${route.query.courseScheduleId}`
-        )
-        if (Array.isArray(res?.data)) {
-          const studentLevel = state.user?.data?.studentLevel || 1
-          details = res.data.find((n: any) => n.studentLevel === studentLevel)?.details || []
-        }
-      } catch (error) {
-        console.log('error')
-      }
-      if (details.length) {
-        data.details = details
-        const videoData: any =
-          details.find((n: any) => n.materialId == route.query.materialId) || {}
-        try {
-          videoData.training = JSON.parse(videoData?.lessonTrainingTemp?.trainingConfigJson)
-        } catch (error) {}
-        data.itemList.push({
-          ...videoData,
-          id: videoData.materialId,
-          currentTime: 0,
-          duration: 100,
-          paused: true,
-          loop: false,
-          videoEle: null,
-          timer: null,
-          muted: true, // 静音
-          autoplay: true, //自动播放
-        })
-        popupData.itemActive = videoData.id
-        popupData.tabName = videoData.materialName
-        data.videoData = videoData
-        handleExerciseCompleted()
-      }
-    }
-    const getTrainingTimes = (res: any) => {
-      let trainingTimes = 0
-      if (Array.isArray(res?.trainings)) {
-        const train = res.trainings.find((n: any) => n.materialId === route.query?.materialId)
-        if (train) {
-          trainingTimes = train.trainingTimes
-        }
-      }
-      data.trainingTimes = trainingTimes
-    }
     // 获取课后练习记录
-    const trainingRecord = async () => {
+    const getTrainingRecord = async () => {
       try {
         const res: any = await request.post(
           state.platformApi +
-            `/studentLessonTraining/trainingRecord/${query.courseScheduleId}?userId=${state.user?.data?.id}`
+            `/studentLessonTraining/trainingRecord/${query.courseScheduleId}?userId=${state.user?.data?.id}`,
+          {
+            hideLoading: true
+          }
         )
-        if (res?.data) {
-          getTrainingTimes(res.data)
-          handleExerciseCompleted()
+        if (Array.isArray(res?.data?.trainings)) {
+          return res.data.trainings
         }
       } catch (error) {}
+      return []
     }
-    onMounted(() => {
-      getDetail()
-      trainingRecord()
+    const setRecord = async (trainings: any[]) => {
+      if (Array.isArray(trainings)) {
+        data.trainings = trainings.map((n: any) => {
+          try {
+            n.trainingContent = JSON.parse(n.trainingContent)
+          } catch (error) {
+            n.trainingContent = ''
+          }
+          return {
+            ...n,
+            currentTime: 0,
+            duration: 100,
+            paused: true,
+            loop: false,
+            videoEle: null,
+            timer: null,
+            muted: true, // 静音
+            autoplay: true //自动播放
+          }
+        })
+        data.itemList = data.trainings.filter((n: any) => n.materialId == route.query.materialId)
+        data.videoData = data.itemList[0]
+        handleExerciseCompleted()
+      }
+    }
+    onMounted(async () => {
+      const trainings = await getTrainingRecord()
+      setRecord(trainings)
     })
     // 返回
     const goback = () => {
@@ -197,12 +183,24 @@ export default defineComponent({
         const res: any = await request.post(
           state.platformApi + '/studentLessonTraining/lessonTrainingRecord',
           {
-            data: body
+            data: body,
+            hideLoading: true
           }
         )
-        trainingRecord()
+        
       } catch (error) {}
       data.recordLoading = false
+      
+      try {
+        const _res: any = await getTrainingRecord()
+        if (Array.isArray(_res?.data.trainings)){
+        const item  = _res.data.trainings.filter((n: any) => n.materialId == route.query.materialId)
+        data.videoData.trainingTimes = item.trainingTimes
+        handleExerciseCompleted()
+        }
+      } catch (error) {
+        
+      }
     }
     // 停止所有的播放
     const handleStopVideo = () => {
@@ -214,14 +212,15 @@ export default defineComponent({
     // 判断练习是否完成
     const handleExerciseCompleted = () => {
       if (
-        data.trainingTimes != 0 &&
-        data.trainingTimes == (data.videoData as any)?.training?.practiceTimes
+        data?.videoData.trainingTimes != 0 &&
+        data?.videoData.trainingTimes + '' === data.videoData?.trainingContent?.practiceTimes
       ) {
-        handleStopVideo()
-        const itemIndex = data.details.findIndex(
+        // handleStopVideo()
+        const itemIndex = data.trainings.findIndex(
           (n: any) => n.materialId == data.videoData?.materialId
-        )
-        const isLastIndex = itemIndex === data.details.length - 1
+          )
+          // console.log(itemIndex ,data.trainings, data.videoData?.materialId)
+        const isLastIndex = itemIndex === data.trainings.length - 1
         showConfirmDialog({
           title: '课后训练',
           message: '你已完成该练习~',
@@ -231,16 +230,11 @@ export default defineComponent({
         })
           .then(() => {
             if (!isLastIndex) {
-              const nextItem = data.details[itemIndex + 1]
+              const nextItem = data.trainings[itemIndex + 1]
               if (nextItem?.type === materialType.视频) {
-                // console.log('下一题视频', data.details[itemIndex].materialId, nextItem.materialId)
-                router.replace({
-                  path: '/exerciseAfterClass',
-                  query: {
-                    ...query,
-                    materialId: nextItem.materialId
-                  }
-                })
+                data.itemList = [nextItem]
+                data.videoData = nextItem
+                handleExerciseCompleted()
               }
               if (nextItem?.type === materialType.曲目) {
                 handleInit(1)
@@ -252,7 +246,6 @@ export default defineComponent({
                   materialId: nextItem.materialId
                 })
                 let src = `${location.origin}/orchestra-music-score/?` + parmas
-                // console.log("🚀 ~ src", src)
                 postMessage({
                   api: 'openAccompanyWebView',
                   content: {
@@ -264,140 +257,154 @@ export default defineComponent({
                   }
                 })
               }
+            } else {
+              postMessage({ api: 'goBack' })
             }
           })
           .catch(() => {
-            data.details[itemIndex].currentTime = 0
+            data.trainings[itemIndex].currentTime = 0
           })
       }
     }
 
     return () => (
-      <div class={styles.coursewarePlay}>
-        <Swipe
-          style={{ height: '100vh' }}
-          ref={swipeRef}
-          showIndicators={false}
-          loop={false}
-          vertical
-          lazyRender={true}
-          touchable={false}
-        >
-          {data.itemList.map((m: any, mIndex: number) => {
-            return (
-              <SwipeItem>
-                <>
-                  <div
-                    class={styles.itemDiv}
-                    onClick={() => {
-                      clearTimeout(m.timer)
-                      activeData.model = !activeData.model
-                    }}
-                  >
-                    <video
-                      playsinline="false"
-                      preload="auto"
-                      class="player"
-                      poster={iconVideobg}
-                      data-vid={m.id}
-                      src={m.content}
-                      loop={m.loop}
-                      autoplay={m.autoplay}
-                      muted={m.muted}
-                      onLoadedmetadata={async (e: Event) => {
-                        const videoEle = e.target as unknown as HTMLVideoElement
-                        m.duration = videoEle.duration
-                        m.videoEle = videoEle
+      <div class={styles.playContent}>
+        <div class={styles.coursewarePlay} style={{ width: parentContainer.width }}>
+          <Swipe
+            style={{ height: '100%' }}
+            ref={swipeRef}
+            showIndicators={false}
+            loop={false}
+            vertical
+            lazyRender={true}
+            touchable={false}
+            duration={0}
+          >
+            {data.itemList.map((m: any, mIndex: number) => {
+              return (
+                <SwipeItem>
+                  <>
+                    <div
+                      class={styles.itemDiv}
+                      onClick={() => {
+                        clearTimeout(m.timer)
+                        activeData.model = !activeData.model
                       }}
-                      onTimeupdate={(e: Event) => {
-                        const videoEle = e.target as unknown as HTMLVideoElement
-                        m.currentTime = videoEle.currentTime
-                      }}
-                      onPlay={() => {
-                        // 播放
-                        m.paused = false
-                        if (m.muted){
-                          m.muted = false
-                          m.videoEle.pause()
-                        }
-                      }}
-                      onPause={() => {
-                        //暂停
-                        m.paused = true
-                      }}
-                      onEnded={() => addTrainingRecord(m)}
                     >
-                      <source src={m.content} type="video/mp4" />
-                    </video>
-                  </div>
-                  <Transition name="bottom">
-                    {activeData.model && (
-                      <div class={styles.bottomFixedContainer}>
-                        <div class={styles.time}>
-                          <span>{getSecondRPM(m.currentTime)}</span>
-                          <span>{getSecondRPM(m.duration)}</span>
-                        </div>
-                        <div class={styles.slider}>
-                          {m.duration && (
-                            <Slider
-                              buttonSize={16}
-                              modelValue={m.currentTime}
-                              min={0}
-                              max={m.duration}
-                            />
-                          )}
-                        </div>
-
-                        <div class={styles.actions}>
-                          <div class={styles.actionBtn}>
-                            {m.paused ? (
-                              <img
-                                src={iconplay}
-                                onClick={(e: Event) => {
-                                  clearTimeout(m.timer)
-                                  m.videoEle?.play()
-                                  m.paused = false
-                                  m.timer = setTimeout(() => {
-                                    activeData.model = false
-                                  }, 4000)
-                                }}
-                              />
-                            ) : (
-                              <img
-                                src={iconpause}
-                                onClick={(e: Event) => {
-                                  clearTimeout(m.timer)
-                                  m.videoEle?.pause()
-                                  m.paused = true
-                                }}
+                      <video
+                        playsinline="false"
+                        preload="auto"
+                        class="player"
+                        poster={iconVideobg}
+                        data-vid={m.id}
+                        src={m.content}
+                        loop={m.loop}
+                        autoplay={m.autoplay}
+                        muted={m.muted}
+                        onLoadedmetadata={async (e: Event) => {
+                          const videoEle = e.target as unknown as HTMLVideoElement
+                          m.duration = videoEle.duration
+                          m.videoEle = videoEle
+                          m.loaded = true
+                        }}
+                        onTimeupdate={(e: Event) => {
+                          if (!m.loaded) return
+                          const videoEle = e.target as unknown as HTMLVideoElement
+                          m.currentTime = videoEle.currentTime
+                        }}
+                        onPlay={() => {
+                          console.log('播放')
+                          // 播放
+                          m.paused = false
+                          if (m.muted) {
+                            m.muted = false
+                            m.videoEle.pause()
+                          }
+                        }}
+                        onPause={() => {
+                          console.log('暂停')
+                          //暂停
+                          m.paused = true
+                        }}
+                        onEnded={() => addTrainingRecord(m)}
+                      >
+                        <source src={m.content} type="video/mp4" />
+                      </video>
+                    </div>
+                    <Transition name="bottom">
+                      {activeData.model && !m.muted && (
+                        <div class={styles.bottomFixedContainer}>
+                          <div class={styles.time}>
+                            <span>{getSecondRPM(m.currentTime)}</span>
+                            <span>{getSecondRPM(m.duration)}</span>
+                          </div>
+                          <div class={styles.slider}>
+                            {m.duration && (
+                              <Slider
+                                buttonSize={16}
+                                modelValue={m.currentTime}
+                                min={0}
+                                max={m.duration}
                               />
                             )}
                           </div>
+
+                          <div class={styles.actions}>
+                            <div class={styles.actionBtn}>
+                              {m.paused ? (
+                                <img
+                                  src={iconplay}
+                                  onClick={(e: Event) => {
+                                    clearTimeout(m.timer)
+                                    m.videoEle?.play()
+                                    m.paused = false
+                                    m.timer = setTimeout(() => {
+                                      activeData.model = false
+                                    }, 4000)
+                                  }}
+                                />
+                              ) : (
+                                <img
+                                  src={iconpause}
+                                  onClick={(e: Event) => {
+                                    clearTimeout(m.timer)
+                                    m.videoEle?.pause()
+                                    m.paused = true
+                                  }}
+                                />
+                              )}
+                            </div>
+                          </div>
                         </div>
+                      )}
+                    </Transition>
+                    {m.muted && (
+                      <div class={styles.loadWrap}>
+                        <Vue3Lottie animationData={playLoadData}></Vue3Lottie>
                       </div>
                     )}
-                  </Transition>
-                </>
-              </SwipeItem>
-            )
-          })}
-        </Swipe>
+                  </>
+                </SwipeItem>
+              )
+            })}
+          </Swipe>
 
-        <Transition name="top">
-          {activeData.model && (
-            <div class={styles.headerContainer} ref={headeRef}>
-              <div class={styles.backBtn} onClick={() => goback()}>
-                <Icon name={iconBack} />
-                返回
-              </div>
-              <div class={styles.menu}>{popupData.tabName}</div>
-              <div class={styles.nums}>
-                练习次数:{data.trainingTimes}/
-                {(data.videoData as any)?.training?.practiceTimes || 0}
+          <Transition name="top">
+            {activeData.model && (
+              <div class={styles.headerContainer} ref={headeRef}>
+                <div class={styles.backBtn} onClick={() => goback()}>
+                  <Icon name={iconBack} />
+                  返回
+                </div>
+                <div class={styles.menu}>{popupData.tabName}</div>
+                <div class={styles.nums}>
+                  练习次数:{data.videoData?.trainingTimes || 0}/
+                  {data.videoData?.trainingContent?.practiceTimes || 0}
+                </div>
               </div>
-            </div>
-          )}
-        </Transition>
+            )}
+          </Transition>
+        </div>
       </div>
     )
   }

+ 1 - 1
src/views/exercise-record/index.tsx

@@ -156,7 +156,7 @@ export default defineComponent({
       //   .join(',')
       try {
         const res = await request.post(`${platformApi.value}/orchestra/page`, {
-          data: { page: 1, rows: 9999 }
+          data: { page: 1, rows: 9999, status: 'DONE' }
         })
         state.actions = res.data.rows.map((item) => {
           return {

+ 1 - 0
src/views/information/help-center/index.module.less

@@ -34,6 +34,7 @@
       font-size: 12px;
       color: #777777;
       line-height: 17px;
+      word-break: break-all;
     }
     .time {
       padding-bottom: 5px;

+ 1 - 1
src/views/information/index.tsx

@@ -114,7 +114,7 @@ export default defineComponent({
                   title: () => (
                     <>
                       <div class={[styles.title, 'van-ellipsis']}>{item.title}</div>
-                      {/* <div class={[styles.content, 'van-multi-ellipsis--l2']}>{item.memo}</div> */}
+                      <div class={[styles.content, 'van-multi-ellipsis--l2']}>{item.memo}</div>
 
                       <div class={styles.time}>
                         {item.createTime ? dayjs(item.createTime).format('YYYY年MM月DD日') : ''}

+ 9 - 3
src/views/mine-orchestra/index.tsx

@@ -21,7 +21,8 @@ export default defineComponent({
     const tabActive = ref<'course' | 'photo' | 'deeds'>((route.query as any)?.tab || 'course')
     const data = reactive({
       orchestraList: [] as any[],
-      loading: true
+      loading: true,
+      reshLoading: false
     })
     const modelData = reactive({
       orchestra: {} as any,
@@ -31,7 +32,9 @@ export default defineComponent({
     const getStudentOrchestras = () => {
       data.loading = true
       request
-        .post(`${state.platformApi}/orchestra/studentOrchestra`)
+        .post(`${state.platformApi}/orchestra/studentOrchestra`, {
+          hideLoading: data.reshLoading
+        })
         .then((res: any) => {
           if (Array.isArray(res?.data)) {
             data.orchestraList = res.data.map((n: any) => {
@@ -53,7 +56,9 @@ export default defineComponent({
     const getTeacherOrchestras = async () => {
       data.loading = true
       request
-        .post(`${state.platformApi}/orchestra/teacherOrchestra`)
+        .post(`${state.platformApi}/orchestra/teacherOrchestra`, {
+          hideLoading: data.reshLoading
+        })
         .then((res: any) => {
           if (Array.isArray(res?.data)) {
             data.orchestraList = res.data.map((n: any) => {
@@ -125,6 +130,7 @@ export default defineComponent({
         <OFullRefresh
           v-model:modelValue={data.loading}
           onRefresh={() => {
+            data.reshLoading = true
             data.orchestraList = []
             nextTick(() => {
               getData()

+ 9 - 4
src/views/mine-orchestra/my-class/index.tsx

@@ -32,7 +32,8 @@ export default defineComponent({
       })
     }
     const openClassDetail = (item: any) => {
-      console.log("🚀 ~ item", item)
+      console.log('🚀 ~ item', item)
+      if (state.platformType == 'STUDENT') return
       postMessage({
         api: 'open_app_page',
         content: {
@@ -72,9 +73,13 @@ export default defineComponent({
                       ) : (
                         <>
                           <div class={styles.content}>
-                            <div class={['van-ellipsis', styles.teacherName]}>
-                              {item.teacherName}
-                            </div>
+                            {item.teacherName ? (
+                              <div class={['van-ellipsis', styles.teacherName]}>
+                                {item.teacherName}
+                              </div>
+                            ) : (
+                              <div style={{ color: 'rgba(178,178,178,1)' }}>暂无伴学指导</div>
+                            )}
                           </div>
                           <div class="van-cell__label">
                             <span class={styles.tag}>{item.classGroupName}</span>

+ 12 - 3
src/views/mine-orchestra/my-photo/index.tsx

@@ -3,7 +3,7 @@ import OHeader from '@/components/o-header'
 import request from '@/helpers/request'
 import { state } from '@/state'
 import { Grid, GridItem, Image, List, Loading, showImagePreview } from 'vant'
-import { defineComponent, onMounted, reactive } from 'vue'
+import { defineComponent, onMounted, reactive, watch } from 'vue'
 import { useRoute, useRouter } from 'vue-router'
 import styles from './index.module.less'
 import iconImage from '../images/icon-photo-default.png'
@@ -35,7 +35,8 @@ export default defineComponent({
           data: {
             ...data.pages,
             orchestraId: props.orchestraId
-          }
+          },
+          hideLoading: true
         })
         if (Array.isArray(res?.data?.rows)) {
           data.list = data.list.concat(res.data.rows)
@@ -44,9 +45,17 @@ export default defineComponent({
             data.finished = true
           }
         }
-      } catch {}
+      } catch {
+        data.finished = true
+      }
       data.loading = false
     }
+    watch(() => props.orchestraId, () => {
+      data.pages.page = 1
+      data.list = []
+      data.finished = false
+      getList()
+    })
 
     // 预览图片
     const onShowImage = (index: number) => {

+ 9 - 2
src/views/mine-orchestra/orchestra-deeds/index.tsx

@@ -12,7 +12,7 @@ import {
   Swipe,
   SwipeItem
 } from 'vant'
-import { defineComponent, onMounted, reactive } from 'vue'
+import { defineComponent, onMounted, reactive, watch } from 'vue'
 import { useRoute, useRouter } from 'vue-router'
 import styles from './index.module.less'
 import iconStep from './images/icon-step.png'
@@ -56,7 +56,8 @@ export default defineComponent({
         const res = await request.post(`${globalState.platformApi}/orchestraStory/page`, {
           data: {
             orchestraId: props.orchestraId
-          }
+          },
+          hideLoading: true
         })
         state.listState.loading = false
         state.listState.refreshing = false
@@ -77,6 +78,12 @@ export default defineComponent({
         state.isClick = false
       }
     }
+    watch(() => props.orchestraId, () => {
+      state.params.page = 1
+      state.list = []
+      state.listState.finished = false
+      getList()
+    })
 
     onMounted(() => {
       getList()

+ 2 - 2
src/views/mine-orchestra/photo-list/detail.tsx

@@ -35,7 +35,7 @@ export default defineComponent({
         const res = await request.post(`${state.platformApi}/orchestraPhoto/page`, {
           data: {
             ...data.pages,
-            orchestraPhotoAlbumId: route.query.orchestraPhotoAlbumId
+            orchestraPhotoAlbumId: route.query.photoId
           }
         })
         if (Array.isArray(res?.data?.rows)) {
@@ -73,7 +73,7 @@ export default defineComponent({
           <OHeader title={(route.query.name as string) || '我的乐团'} />
         </OSticky>
         <div class={styles.phoneDetail}>
-          {!data.loading && !!data.list.length && (
+          {!!data.list.length && (
             <List
               // v-model:loading={data.loading}
               finished={data.finished}

+ 46 - 38
src/views/mine-orchestra/photo-list/index.module.less

@@ -1,43 +1,51 @@
-.photoWrap{
-    display: flex;
-    flex-wrap: wrap;
-    padding: 12px;
+.photoWrap {
+  display: flex;
+  flex-wrap: wrap;
+  padding: 12px;
+  box-sizing: border-box;
+  justify-content: space-between;
+  div {
     box-sizing: border-box;
-    justify-content: space-between;
-    div{
-      box-sizing: border-box;
-    }
   }
-  .photoItem{
-    position: relative;
-    width: 49%;
-    margin-bottom: 12px;
-    .gridImg{
-      display: flex;
-      justify-content: center;
-      align-items: center;
-      width: 100%;
-      height: calc(100vw / 2);
-    }
-    .iconImage{
-      display: flex;
-      justify-content: center;
-    }
-    .gridName{
-      font-size: 16px;
-      color:#333;
-      padding: 8px 0 4px 0;
-    }
-    .gridDes {
-      color: #777;
-      font-size: 12px;
+}
+.photoItem {
+  position: relative;
+  width: 49%;
+  margin-bottom: 12px;
+  .gridImg {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    width: 100%;
+    height: calc(100vw / 2);
+  }
+  .iconImage {
+    display: flex;
+    justify-content: center;
+  }
+  .gridName {
+    font-size: 16px;
+    color: #333;
+    padding: 8px 0 4px 0;
+  }
+  .gridDes {
+    color: #777;
+    font-size: 12px;
+  }
+}
+
+.detailGrid {
+  :global {
+    .van-grid-item__content {
+      padding: 0;
     }
   }
-  
-  .detailGrid{
-    :global{
-      .van-grid-item__content{
-        padding: 0;
-      }
+}
+:global{
+  .van-image-preview{
+    .van-image-preview__close-icon,
+    .van-image-preview__index{
+      top: 50px
     }
-  }
+  }
+}

+ 1 - 1
src/views/mine-orchestra/photo-list/index.tsx

@@ -91,7 +91,7 @@ export default defineComponent({
                       router.push({
                         path: '/photo-list-detail',
                         query: {
-                          orchestraPhotoAlbumId: item.id
+                          photoId: item.id
                         }
                       })
                     }}

+ 34 - 9
src/views/unit-test/examination-mode/index.tsx

@@ -27,7 +27,7 @@ import PlayQuestion from '../model/play-question'
 import request from '@/helpers/request'
 import dayjs from 'dayjs'
 import ResultFinish from '../model/result-finish'
-import { QuestionType } from '../unit'
+import { eventUnit, QuestionType } from '../unit'
 import { useRect } from '@vant/use'
 
 export default defineComponent({
@@ -83,14 +83,16 @@ export default defineComponent({
     /**
      * @description 计算考试时间剩余时间
      */
-    const calcTime = () => {
+    const calcTime = async () => {
       const examDetail = state.examDetail || {}
       const startTime = examDetail.startTime
       const nowTime = examDetail.now
       const timeMinutes = examDetail.timeMinutes || 0 // 测验时间
       // 返回秒
       const minu = dayjs(startTime).add(timeMinutes, 'minute').diff(dayjs(nowTime))
+      // 时间到了考试结束
       if (minu <= 0) {
+        await onConfirmExam()
         state.visiableExam = true
       } else {
         state.time = Math.ceil(minu / 1000) * 1000
@@ -113,6 +115,7 @@ export default defineComponent({
     /**
      * @description 重置当前的题目高度
      */
+    let size = 0
     const resizeSwipeItemHeight = (scroll = true) => {
       nextTick(() => {
         scroll && window.scrollTo(0, 0)
@@ -121,9 +124,29 @@ export default defineComponent({
           //   document.querySelectorAll('.swipe-item-question')[state.currentIndex]
           const currentItemDom: any = document
             .querySelectorAll('.van-swipe-item')
-            [state.currentIndex].querySelector('.swipe-item-question')
-          const rect = useRect(currentItemDom)
+            [state.currentIndex]?.querySelector('.swipe-item-question')
+
+          const allImg = currentItemDom.querySelectorAll('.answerTitleImg img')
+          let status = true
+          // console.log(allImg)
+          allImg.forEach((img: any) => {
+            console.log(img.complete)
+            if (!img.complete) {
+              status = false
+            }
+          })
+          // 判断图片是否加载完了
+          if (!status && size < 3) {
+            setTimeout(() => {
+              size += 1
+              resizeSwipeItemHeight(scroll)
+            }, 300)
+          }
+          if (status) {
+            size = 0
+          }
 
+          const rect = useRect(currentItemDom)
           state.swipeHeight = rect.height
         }, 100)
       })
@@ -211,6 +234,7 @@ export default defineComponent({
             examName: state.examDetail.unitExaminationName
           }
         }
+        onAfter()
         state.visiableResult = true
       } catch {
         //
@@ -233,6 +257,7 @@ export default defineComponent({
 
     const onAfter = () => {
       window.removeEventListener('popstate', onBack, false)
+      router.back()
     }
 
     onMounted(async () => {
@@ -268,7 +293,8 @@ export default defineComponent({
                     v-model:time={state.time}
                     format={'mm:ss'}
                     autoStart={false}
-                    onFinish={() => {
+                    onFinish={async () => {
+                      await onConfirmExam()
                       state.visiableExam = true
                     }}
                   />
@@ -288,6 +314,7 @@ export default defineComponent({
           style={{ marginBottom: '12px' }}
           lazyRender
           onChange={(index: number) => {
+            eventUnit.emit('unitAudioStop')
             state.currentIndex = index
             resizeSwipeItemHeight()
           }}
@@ -401,13 +428,11 @@ export default defineComponent({
             cancelButtonText="我知道了"
             onClose={() => {
               state.visiableResult = false
-              onAfter()
               router.back()
               router.back()
             }}
             onConform={() => {
               state.visiableResult = false
-              onAfter()
               router.back()
               router.back()
             }}
@@ -429,7 +454,8 @@ export default defineComponent({
           v-model:show={state.visiableExam}
           message="考试已结束"
           messageAlign="center"
-          onConfirm={() => {
+          onConfirm={async () => {
+            onAfter()
             state.visiableResult = true
           }}
         />
@@ -441,7 +467,6 @@ export default defineComponent({
           confirmButtonText="确认完成"
           onConfirm={() => {
             onAfter()
-            router.back()
           }}
         />
       </div>

+ 6 - 5
src/views/unit-test/index.tsx

@@ -41,11 +41,12 @@ export default defineComponent({
       selectUnitExam: {} as any
     })
 
-    const getList = async () => {
+    const getList = async (status = false) => {
       try {
         if (form.isClick) return
         form.isClick = true
         const res = await request.post('/api-student/studentUnitExamination/queryPageByStudent', {
+          hideLoading: status,
           data: {
             ...form.params
           }
@@ -70,13 +71,13 @@ export default defineComponent({
       }
     }
 
-    const onSearch = () => {
+    const onSearch = (status = false) => {
       form.params.page = 1
       form.list = []
       form.listState.dataShow = true // 判断是否有数据
       form.listState.loading = false
       form.listState.finished = false
-      getList()
+      getList(status)
     }
 
     // 开始测验
@@ -182,7 +183,7 @@ export default defineComponent({
         {form.listState.dataShow ? (
           <OFullRefresh
             v-model:modelValue={form.listState.refreshing}
-            onRefresh={onSearch}
+            onRefresh={() => onSearch(true)}
             style={{
               minHeight: `calc(100vh - ${form.listState.height}px)`
             }}
@@ -204,7 +205,7 @@ export default defineComponent({
                 <CellGroup inset class={styles.cellGroup} border={false}>
                   <Cell
                     center
-                    isLink
+                    // isLink
                     clickable={false}
                     titleStyle={{ flex: '1 auto' }}
                     valueClass={[

+ 11 - 1
src/views/unit-test/model/anser-title/index.tsx

@@ -3,6 +3,7 @@ import { computed, defineComponent } from 'vue'
 import { QuestionType, QuestionTypeName } from '../../unit'
 import styles from './index.module.less'
 import iconPassCheck from '../../images/icon-pass-check.png'
+import UnitAudio from '../unit-audio'
 
 export default defineComponent({
   name: 'answer-title',
@@ -69,7 +70,16 @@ export default defineComponent({
             <div v-html={props.extra.questionDetail}></div>
             {mediaUrls.value &&
               mediaUrls.value.map(
-                (url: any) => url && <Image class={styles.unitTitleImg} src={url} />
+                (url: any) =>
+                  url && (
+                    <>
+                      {url.substr(-3) === 'mp3' ? (
+                        <UnitAudio src={url} class={styles.valueAudio} />
+                      ) : (
+                        <Image class={[styles.unitTitleImg, 'answerTitleImg']} src={url} />
+                      )}
+                    </>
+                  )
               )}
           </div>
         ) : (

+ 5 - 0
src/views/unit-test/model/drag-question/index.module.less

@@ -101,5 +101,10 @@
 
   .imgs {
     height: 56px;
+    :global {
+      .van-image__img {
+        width: auto;
+      }
+    }
   }
 }

+ 14 - 11
src/views/unit-test/model/drag-question/index.tsx

@@ -84,16 +84,17 @@ export default defineComponent({
 
     // 返回选中的结果
     const onSelect = () => {
-      const options = state.options || []
+      // const options = state.options || []
       const list = state.list || []
       const result: any = []
 
+      console.log(list, '1212')
       list.forEach((item: any, index: number) => {
-        const rightOption = options[index]
+        console.log(index, '测试返回')
         result.push({
           answerId: item.index,
           answer: item.leftValue,
-          answerExtra: rightOption.rightValue
+          answerExtra: index + 1
         })
       })
       emit('update:value', result)
@@ -104,21 +105,17 @@ export default defineComponent({
       // 判断是否已经选中了
       if (item.checked) return
       const result: any = []
-      state.options.forEach((option: any) => {
-        const originOption = answers.value.find(
-          (child: any) => child.examinationQuestionAnswerId === option.rightIndex
-        )
+      state.options.forEach((option: any, index: any) => {
         result.push({
           answerId: option.index,
           answer: option.leftValue,
-          answerExtra: originOption.questionAnswer
+          answerExtra: index + 1
         })
       })
-      const rightOption = answers.value[state.options.length]
       result.push({
         answerId: item.examinationQuestionAnswerId,
         answer: item.questionAnswer,
-        answerExtra: rightOption.questionExtra
+        answerExtra: state.options.length + 1
       })
       emit('update:value', result)
 
@@ -142,6 +139,7 @@ export default defineComponent({
     const initOptions = () => {
       const answers = props.data.answers || []
       const userAnswer = props.data.userAnswer || [] // 用户填写的答案
+      console.log(answers, userAnswer)
       state.options = []
       if (userAnswer.length > 0) {
         userAnswer.forEach((answer: any, index: any) => {
@@ -243,6 +241,11 @@ export default defineComponent({
                     true
                   )
 
+                  // state.options.forEach((item: any) => {
+                  //   item.checked = false
+                  // })
+                  // state.list = []
+
                   onSelect()
                 }}
               >
@@ -261,7 +264,7 @@ export default defineComponent({
                     <Image
                       src={item.leftValue}
                       data-id={item.index}
-                      class={styles.imgs}
+                      class={[styles.imgs, 'van-hairline--surround']}
                       fit="cover"
                     />
                   )}

+ 78 - 27
src/views/unit-test/model/play-question/index.tsx

@@ -12,6 +12,7 @@ import iconSong from '../../images/icon-song.png'
 import AnserTitle from '../anser-title'
 import { QuestionType } from '../../unit'
 import AnswerAnalysis from '../answer-analysis'
+import { browser } from '@/helpers/utils'
 
 // 单选和多选题
 export default defineComponent({
@@ -82,8 +83,8 @@ export default defineComponent({
       postMessage({
         api: 'openAccompanyWebView',
         content: {
-          url: `https://ponline.colexiu.com/orchestra-music-score/?id=${info.musicSheetId}&modelType=evaluation&unitId=${props.unitId}&questionId=${props.data.id}`,
-          // url: `${location.origin}/orchestra-music-score/?id=${info.musicSheetId}&modelType=evaluation&unitId=${props.unitId}`,
+          // url: `https://ponline.colexiu.com/orchestra-music-score/?id=${info.musicSheetId}&modelType=evaluation&unitId=${props.unitId}&questionId=${props.data.id}`,
+          url: `${location.origin}/orchestra-music-score/?id=${info.musicSheetId}&modelType=evaluation&unitId=${props.unitId}&questionId=${props.data.id}`,
           orientation: 0,
           isHideTitle: true,
           statusBarTextColor: false,
@@ -93,36 +94,86 @@ export default defineComponent({
 
       // 打开页面监听
       listenerMessage('webViewOnResume', () => {
-        promisefiyPostMessage({ api: 'getCache', content: { key: 'h5-orchestra-unit' } }).then(
-          (res: any) => {
-            const content = res.content
-            if (content.value) {
-              const result = content.value ? JSON.parse(content.value) : {}
-              console.log('🚀 ~ listenerMessage ~ result', result, props.data.questionId)
+        if (browser().android) {
+          const instance: any =
+            (window as any).ORCHESTRA || (window as any).webkit?.messageHandlers?.ORCHESTRA
 
-              if (result.questionId === props.data.id) {
-                const tempScore = result.score || 0
-                // 跟上一次分数对比
-                if (state.score < tempScore) {
-                  state.score = result.score || 0
+          console.log(instance, '-------------')
+          const result = instance.getCache2('h5-orchestra-unit')
+          if (result.questionId === props.data.id) {
+            const tempScore = result.score || 0
+            // 跟上一次分数对比
+            if (state.score < tempScore) {
+              state.score = result.score || 0
+            }
+          }
+          emit('update:value', [
+            {
+              answerId: '',
+              answer: state.score,
+              answerExtra: ''
+            }
+          ])
+
+          // 置空,存的缓存
+          promisefiyPostMessage({
+            api: 'setCache',
+            content: {
+              key: 'h5-orchestra-unit',
+              value: ''
+            }
+          })
+
+          // 关闭页面监听
+          removeListenerMessage('webViewOnResume', () => {
+            //
+          })
+        } else {
+          promisefiyPostMessage({ api: 'getCache', content: { key: 'h5-orchestra-unit' } }).then(
+            (res: any) => {
+              const content = res.content
+              if (content.value) {
+                console.log(
+                  '🚀 ~ listenerMessage ~ content.value',
+                  content.value,
+                  '---------------'
+                )
+                const result = content.value ? JSON.parse(content.value) : {}
+                console.log('🚀 ~ listenerMessage ~ result', result, props.data.questionId)
+
+                if (result.questionId === props.data.id) {
+                  const tempScore = result.score || 0
+                  // 跟上一次分数对比
+                  if (state.score < tempScore) {
+                    state.score = result.score || 0
+                  }
                 }
+
+                emit('update:value', [
+                  {
+                    answerId: '',
+                    answer: state.score,
+                    answerExtra: ''
+                  }
+                ])
+
+                // 置空,存的缓存
+                promisefiyPostMessage({
+                  api: 'setCache',
+                  content: {
+                    key: 'h5-orchestra-unit',
+                    value: ''
+                  }
+                })
               }
 
-              emit('update:value', [
-                {
-                  answerId: '',
-                  answer: state.score,
-                  answerExtra: ''
-                }
-              ])
+              // 关闭页面监听
+              removeListenerMessage('webViewOnResume', () => {
+                //
+              })
             }
-
-            // 关闭页面监听
-            removeListenerMessage('webViewOnResume', () => {
-              //
-            })
-          }
-        )
+          )
+        }
       })
     }
 

BIN
src/views/unit-test/model/unit-audio/images/icon-pause.png


BIN
src/views/unit-test/model/unit-audio/images/icon-play.png


+ 1 - 1
src/views/unit-test/model/unit-audio/index.module.less

@@ -36,6 +36,6 @@
   }
 
   .audioStatus {
-    font-size: 18px;
+    font-size: 14px;
   }
 }

+ 5 - 7
src/views/unit-test/model/unit-audio/index.tsx

@@ -3,6 +3,8 @@ import { defineComponent, onUnmounted, reactive, watch } from 'vue'
 import styles from './index.module.less'
 import { Howl } from 'howler'
 import iconAudio from './images/icon-audio.png'
+import iconPlay from './images/icon-play.png'
+import iconPause from './images/icon-pause.png'
 import { eventUnit } from '../../unit'
 
 // 音频播放
@@ -29,17 +31,12 @@ export default defineComponent({
       //   winner: [6000, 5000]
       // }
     })
-    console.log(htick)
+    // console.log(htick)
 
     htick.on('load', (val: any) => {
-      console.log('111')
       console.log(htick.duration())
       state.duration = Math.ceil(htick.duration())
     })
-    // 播放结束
-    // htick.on('end', () => {
-    //   console.log('1')
-    // })
 
     eventUnit.on('unitAudioStop', () => {
       htick.stop()
@@ -58,8 +55,9 @@ export default defineComponent({
           </div>
 
           {/* pause-circle */}
+          {/* 'play-circle' : 'pause-circle' */}
           <Icon
-            name={state.audioStatus === 'stopped' ? 'play-circle' : 'pause-circle'}
+            name={state.audioStatus === 'stopped' ? iconPause : iconPlay}
             class={styles.audioStatus}
             onClick={(e: any) => {
               e.stopPropagation()

+ 27 - 6
src/views/unit-test/practice-mode/index.tsx

@@ -27,7 +27,7 @@ import KeepLookQuestion from '../model/keep-look-question'
 import PlayQuestion from '../model/play-question'
 import ErrorMode from '../model/error-mode'
 import ResultFinish from '../model/result-finish'
-import { QuestionType } from '../unit'
+import { eventUnit, QuestionType } from '../unit'
 import request from '@/helpers/request'
 import { useRect } from '@vant/use'
 import OHeader from '@/components/o-header'
@@ -128,8 +128,9 @@ export default defineComponent({
         })
 
         const { data } = await request.post(
-          '/api-school/studentUnitExamination/submitTrainingAnswer',
+          '/api-student/studentUnitExamination/submitTrainingAnswer',
           {
+            hideLoading: true,
             data: result
           }
         )
@@ -187,16 +188,35 @@ export default defineComponent({
      * @description 重置当前的题目高度
      * @param {any} scroll 是否滚动到顶部
      */
+    let size = 0
     const resizeSwipeItemHeight = (scroll = true) => {
       nextTick(() => {
         scroll && window.scrollTo(0, 0)
         setTimeout(() => {
-          // const currentItemDom: Element =
-          //   document.querySelectorAll('.swipe-item-question')[state.currentIndex]
-          // console.log(document.querySelectorAll('.van-swipe-item'), state.currentIndex)
           const currentItemDom: any = document
             .querySelectorAll('.van-swipe-item')
-            [state.currentIndex].querySelector('.swipe-item-question')
+            [state.currentIndex]?.querySelector('.swipe-item-question')
+          console.log('🚀 ~ setTimeout ~ currentItemDom', currentItemDom)
+
+          const allImg = currentItemDom.querySelectorAll('.answerTitleImg img')
+          let status = true
+          // console.log(allImg)
+          allImg.forEach((img: any) => {
+            console.log(img.complete)
+            if (!img.complete) {
+              status = false
+            }
+          })
+          // 判断图片是否加载完了
+          if (!status && size < 3) {
+            setTimeout(() => {
+              size += 1
+              resizeSwipeItemHeight(scroll)
+            }, 300)
+          }
+          if (status) {
+            size = 0
+          }
           const rect = useRect(currentItemDom)
           state.swipeHeight = rect.height
         }, 100)
@@ -347,6 +367,7 @@ export default defineComponent({
           lazyRender
           height={state.swipeHeight}
           onChange={(index: number) => {
+            eventUnit.emit('unitAudioStop')
             state.currentIndex = index
             resizeSwipeItemHeight()
           }}

+ 3 - 3
src/views/unit-test/unit-create/modals/newspaper-item.tsx

@@ -24,21 +24,21 @@ export default defineComponent({
               <div class={styles.itemBottomDot}>
                 <p class={styles.dotMain}>
                   {props.item?.totalScore || 0}
-                  <span>分</span>
+                  {/* <span>分</span> */}
                 </p>
                 <p class={styles.dotSub}> 总分</p>
               </div>
               <div class={styles.itemBottomDot}>
                 <p class={styles.dotMain} style={{ color: '#F67146' }}>
                   {props.item?.passScore || 0}
-                  <span>分</span>
+                  {/* <span>分</span> */}
                 </p>
                 <p class={styles.dotSub}>合格分 </p>
               </div>
               <div class={styles.itemBottomDot}>
                 <p class={styles.dotMain}>
                   {props.item?.questionNum || 0}
-                  <span>分</span>{' '}
+                  {/* <span>分</span>{' '} */}
                 </p>
                 <p class={styles.dotSub}>题目数量 </p>
               </div>

+ 79 - 32
src/views/unit-test/unit-create/uni-last.tsx

@@ -20,61 +20,103 @@ import styles from './uni-last.module.less'
 import { useRoute, useRouter } from 'vue-router'
 import NewspaperItem from './modals/newspaper-item'
 import questIcon from '@/school/images/quest-icon.png'
-import { browser } from '@/helpers/utils'
+import { postMessage } from '@/helpers/native-message'
+// import { browser } from '@/helpers/utils'
 export default defineComponent({
   name: 'uni-test',
   setup() {
     const route = useRoute()
     const router = useRouter()
-    const browserInfo = browser()
+    // const browserInfo = browser()
     const activeName = ref('one')
     // const catchList = store
     const forms = ref({} as any)
-    const data = reactive({
+    const datas = reactive({
       loading: true,
       list: [] as any,
       uniDetail: {} as any
     })
     const showTip = ref(false)
-    const getList = async () => {
-      data.loading = true
+    // const getList = async () => {
+    //   data.loading = true
+    //   try {
+    //     const res: any = await request.post(
+    //       state.platformApi + '/courseSchedule/queryUnitExamination',
+    //       {
+    //         requestType: 'form',
+    //         data: {
+    //           lessonCoursewareId: route.query.lessonCoursewareId,
+    //           classGroupId: forms.value.classGroupId
+    //         }
+    //       }
+    //     )
+    //     //      classGroupId: forms.value.classGroupId
+    //     data.list = res.data || []
+    //   } catch (error) {}
+
+    //   data.loading = false
+    // }
+
+    const getClassDetail = async () => {
+      try {
+        const { data } = await request.get(
+          state.platformApi + `/classGroup/detail/${forms.value.classGroupId}`
+        )
+        forms.value.preStudentNum = data.preStudentNum || 0
+      } catch (e) {
+        console.log(e)
+      }
+    }
+
+    // 获取详情
+    const getCourseLessonDetail = async () => {
       try {
-        const res: any = await request.post(
-          state.platformApi + '/courseSchedule/queryUnitExamination',
+        //   const query = route.query
+        // // api-teacher/lessonCoursewareExaminationMapper/detailByCourseId
+        // // 判断是从课程结束后,还是正常创建
+        const { data } = await request.post(
+          state.platformApi + `/lessonCoursewareExaminationMapper/detailByCourseId`,
           {
             requestType: 'form',
             data: {
-              lessonCoursewareId: route.query.lessonCoursewareId,
-              classGroupId: forms.value.classGroupId
+              courseScheduleId: route.query.courseScheduleId
             }
           }
         )
-        //      classGroupId: forms.value.classGroupId
-        data.list = res.data || []
-      } catch (error) {}
 
-      data.loading = false
-    }
+        forms.value.classGroupId = route.query.courseScheduleId
+        forms.value.classGroupName = data.classGroupName
+        forms.value.testName = data.lessonCoursewareExaminationMapperName
+        forms.value.orchestraName = data.orchestraName
+        forms.value.coursewareName = data.LessonCoursewareName
+        forms.value.lessonCoursewareId = data.lessonCoursewareExaminationMapper.lessonCoursewareId
+        forms.value.preStudentNum = data.studentNum || 0
 
-    const getClassDetail = async () => {
-      try {
-        const res = await request.get(
-          state.platformApi + `/classGroup/detail/${forms.value.classGroupId}`
-        )
-        forms.value.preStudentNum = res.data.preStudentNum
+        const details = data.lessonCoursewareExaminationMapper.details || []
+        details.forEach((item: any) => {
+          datas.uniDetail[item.level] = item
+        })
       } catch (e) {
         console.log(e)
       }
     }
+
     onMounted(() => {
       forms.value = { ...JSON.parse(sessionStorage.getItem('unit-create') || '{}') } as any
-      if (!forms.value.classGroupId) {
-        showToast('请选择班级')
-        return
+      console.log(forms.value)
+      const query = route.query
+      // api-teacher/lessonCoursewareExaminationMapper/detailByCourseId
+      // 判断是从课程结束后,还是正常创建
+      if (query.courseScheduleId) {
+        getCourseLessonDetail()
+      } else {
+        if (!forms.value.classGroupId) {
+          showToast('请选择班级')
+          return
+        }
+        getClassDetail()
+        getStudentUni()
       }
-      getClassDetail()
-      getList()
-      getStudentUni()
     })
     const getStudentUni = async () => {
       try {
@@ -88,7 +130,7 @@ export default defineComponent({
           }
         )
         res.data.details.forEach((item: any) => {
-          data.uniDetail[item.level] = item
+          datas.uniDetail[item.level] = item
         })
       } catch (e) {
         console.log(e)
@@ -100,7 +142,7 @@ export default defineComponent({
         return
       }
       try {
-        const res = await request.post(
+        await request.post(
           state.platformApi + `/classGroupUnitExamination/publishUnitExamination`,
           {
             data: {
@@ -113,7 +155,12 @@ export default defineComponent({
         )
         showToast('创建成功')
         sessionStorage.removeItem('unit-create')
-        router.replace('/unit-list')
+        // 如果连接上面有班级编号,说明当前页面是从原生来的
+        if (route.query.classGroupId) {
+          postMessage({ api: 'back' })
+        } else {
+          router.replace('/unit-list')
+        }
       } catch (e) {
         console.log(e)
       }
@@ -166,13 +213,13 @@ export default defineComponent({
               shrink
             >
               <Tab name="one" title="I类学生">
-                <NewspaperItem item={data.uniDetail[1]}></NewspaperItem>
+                <NewspaperItem item={datas.uniDetail[1]}></NewspaperItem>
               </Tab>
               <Tab name="two" title="II类学生">
-                <NewspaperItem item={data.uniDetail[2]}></NewspaperItem>
+                <NewspaperItem item={datas.uniDetail[2]}></NewspaperItem>
               </Tab>
               <Tab name="three" title="III类学生">
-                <NewspaperItem item={data.uniDetail[3]}></NewspaperItem>
+                <NewspaperItem item={datas.uniDetail[3]}></NewspaperItem>
               </Tab>
             </Tabs>
           </div>

+ 26 - 4
src/views/unit-test/unit-detail/index.tsx

@@ -11,7 +11,7 @@ import DragQuestion from '../model/drag-question'
 import KeepLookQuestion from '../model/keep-look-question'
 import PlayQuestion from '../model/play-question'
 import request from '@/helpers/request'
-import { QuestionType } from '../unit'
+import { eventUnit, QuestionType } from '../unit'
 import { useRect } from '@vant/use'
 import { state as baseState } from '@/state'
 
@@ -152,13 +152,34 @@ export default defineComponent({
     /**
      * @description 重置当前的题目高度
      */
-    const resizeSwipeItemHeight = () => {
+    let size = 0
+    const resizeSwipeItemHeight = (scroll = true) => {
       nextTick(() => {
-        window.scrollTo(0, 0)
+        scroll && window.scrollTo(0, 0)
         setTimeout(() => {
           const currentItemDom: any = document
             .querySelectorAll('.van-swipe-item')
-            [state.currentIndex].querySelector('.swipe-item-question')
+            [state.currentIndex]?.querySelector('.swipe-item-question')
+
+          const allImg = currentItemDom.querySelectorAll('.answerTitleImg img')
+          let status = true
+          // console.log(allImg)
+          allImg.forEach((img: any) => {
+            console.log(img.complete)
+            if (!img.complete) {
+              status = false
+            }
+          })
+          // 判断图片是否加载完了
+          if (!status && size < 3) {
+            setTimeout(() => {
+              size += 1
+              resizeSwipeItemHeight(scroll)
+            }, 300)
+          }
+          if (status) {
+            size = 0
+          }
           const rect = useRect(currentItemDom)
           console.log('🚀 ~ setTimeout ~ currentItemDom', currentItemDom)
           console.log('🚀 ~ setTimeout ~ rect', rect, state.currentIndex)
@@ -226,6 +247,7 @@ export default defineComponent({
           style={{ paddingBottom: '12px' }}
           height={state.swipeHeight}
           onChange={(index: number) => {
+            eventUnit.emit('unitAudioStop')
             state.currentIndex = index
             // .swipe-item-question
             // const t = setInterval(() => {