Browse Source

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

mo 2 years ago
parent
commit
05d07af24a

+ 9 - 0
src/school/approval-manage/batch-adjust.tsx

@@ -3,6 +3,7 @@ import OPopup from '@/components/o-popup'
 import OSticky from '@/components/o-sticky'
 import { postMessage } from '@/helpers/native-message'
 import request from '@/helpers/request'
+import { verifiyNumberInteger } from '@/helpers/toolsValidate'
 import { browser } from '@/helpers/utils'
 import router from '@/router'
 import { state } from '@/state'
@@ -73,6 +74,13 @@ export default defineComponent({
       }
     }
 
+    const onFormatterInt = (val: any) => {
+      if (val && val >= 1) {
+        return verifiyNumberInteger(val)
+      } else {
+        return ''
+      }
+    }
     onMounted(() => {
       getOrchestra()
     })
@@ -167,6 +175,7 @@ export default defineComponent({
             type="number"
             v-model={forms.adjustDay}
             placeholder="请输入调整天数"
+            formatter={onFormatterInt}
             v-slots={{ extra: () => <span style={{ paddingLeft: '6px' }}>天</span> }}
           />
         </CellGroup>

+ 6 - 1
src/school/companion-teacher/companion-teacher-register.tsx

@@ -200,6 +200,12 @@ export default defineComponent({
 
       // t: route.query.t, // 过期时间
       try {
+        // await request.post('/api-school/open/schoolTeacherStudent/queryQrCodeStatus', {
+        //   data: {
+        //     schoolId: state.id,
+        //     qrCodeEffectiveStartTime: state.t ? dayjs(state.t).format('YYYY-MM-DD HH:mm:ss') : null
+        //   }
+        // })
         if (state.t) {
           const { data } = await request.get('/api-school/open/paramConfig/queryByParamName', {
             requestType: 'form',
@@ -207,7 +213,6 @@ export default defineComponent({
               paramName: 'qr_code_expire_hours'
             }
           })
-
           if (dayjs(Number(state.t)).add(data.paramValue, 'hour').isBefore(dayjs())) {
             showDialog({
               title: '提示',

+ 3 - 3
src/school/train-planning/component/practice/index.module.less

@@ -4,13 +4,13 @@
   margin: 12px 13px;
   background: #ffebdd;
   border-radius: 10px;
-  padding: 7px 19px;
-  font-size: 14px;
+  padding: 7px 12px;
+  font-size: 13px;
   color: #f67146;
   line-height: 20px;
 
   .icon {
-    font-size: 24px;
+    font-size: 20px;
     margin-right: 6px;
   }
 }

+ 1 - 1
src/school/train-planning/component/practice/index.tsx

@@ -124,7 +124,7 @@ export default defineComponent({
       <div class={styles.practice}>
         <div class={styles.tips}>
           <Icon name="warning" class={styles.icon} />
-          乐团加练可对任意班级进行排课
+          乐团加练可对任意班级进行排课,课程类型可多选
         </div>
 
         <CellGroup inset class={styles.cellGroup}>

+ 2 - 2
src/school/train-planning/component/standard/index.module.less

@@ -8,13 +8,13 @@
   margin: 12px 13px;
   background: #ffebdd;
   border-radius: 10px;
-  padding: 7px 19px;
+  padding: 7px 12px;
   font-size: 13px;
   color: #f67146;
   line-height: 20px;
 
   .icon {
-    font-size: 24px;
+    font-size: 20px;
     margin-right: 6px;
   }
 }

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

@@ -5,6 +5,7 @@
 
   .orderType {
     padding-top: 35px;
+    padding-bottom: 90px;
     display: flex;
     align-items: center;
     justify-content: center;

+ 17 - 3
src/student/payment-result/index.tsx

@@ -1,5 +1,5 @@
 import OHeader from '@/components/o-header'
-import { defineComponent, onMounted, reactive } from 'vue'
+import { defineComponent, onMounted, reactive, ref } from 'vue'
 import { Button, Cell, CellGroup, Image, showConfirmDialog, Tag } from 'vant'
 import styles from './index.module.less'
 import iconRefunding from './images/icon_refunding.png'
@@ -11,6 +11,7 @@ import { useRoute } from 'vue-router'
 import { orderStatus } from '@/constant'
 import { browser, moneyFormat } from '@/helpers/utils'
 import { useEventListener, useWindowScroll } from '@vueuse/core'
+import { useRect } from '@vant/use'
 
 export default defineComponent({
   name: 'payment-result',
@@ -19,7 +20,9 @@ export default defineComponent({
     const state = reactive({
       orders: {} as any,
       goodsInfos: [] as any,
-      background: 'transparent'
+      background: 'transparent',
+      color: '#fff',
+      backIconColor: 'white' as any
     })
     const getDetails = async () => {
       try {
@@ -88,15 +91,26 @@ export default defineComponent({
         const { y } = useWindowScroll()
         if (y.value > 52) {
           state.background = '#fff'
+          state.color = '#323333'
+          state.backIconColor = 'black'
         } else {
           state.background = 'transparent'
+          state.color = '#fff'
+          state.backIconColor = 'white'
         }
       })
     })
     return () => (
       <div class={styles.paymentResult}>
         <div class={styles.paymentTitle}>
-          {browser().isApp && <OHeader border={false} background={state.background} />}
+          {browser().isApp && (
+            <OHeader
+              border={false}
+              background={state.background}
+              color={state.color}
+              backIconColor={state.backIconColor}
+            />
+          )}
 
           {state.orders.id && (
             <>

+ 146 - 32
src/views/unit-test/examination-mode/index.tsx

@@ -47,12 +47,14 @@ export default defineComponent({
       examDetail: {} as any,
       visiableAnswer: false,
       currentIndex: 0,
-      questionList: [5],
-      answerList: {},
+      questionList: [],
       time: 0,
       visiableSure: false,
       visiableResult: false,
-      visiableExam: false // 考试已结束
+      resultInfo: {} as any,
+      resultStatusType: 'SUCCESS', // 'SUCCESS' | 'FAIL'
+      visiableExam: false, // 考试已结束
+      nextStatus: false
     })
 
     const getExamDetails = async () => {
@@ -66,21 +68,25 @@ export default defineComponent({
             }
           }
         )
-
         const { questionJson, studentAnswerJson, ...res } = data
-        ;(questionJson || []).forEach((item: any) => {
-          if (item.questionTypeCode === 'RADIO') {
-          }
+        const temp = questionJson || []
+        temp.forEach((item: any) => {
+          item.userAnswer = formatUserAnswers(item, studentAnswerJson)
         })
-        state.questionList = state.examDetail = { ...res } || {}
+        console.log(temp)
+        state.questionList = temp
+
+        state.examDetail = { ...res } || {}
 
         calcTime()
       } catch {
         //
-        state.visiableExam = true
       }
     }
 
+    /**
+     * @description 计算考试时间剩余时间
+     */
     const calcTime = () => {
       const examDetail = state.examDetail || {}
       const startTime = examDetail.startTime
@@ -88,11 +94,8 @@ export default defineComponent({
       const timeMinutes = examDetail.timeMinutes || 0 // 测验时间
       // 返回秒
       const minu = dayjs(startTime).add(timeMinutes, 'minute').diff(dayjs(nowTime))
-
-      // console.log(dayjs(startTime).add(timeMinutes, 'minute').valueOf() - dayjs(nowTime).valueOf())
-      // console.log(minu, dayjs(startTime).add(timeMinutes, 'minute'), dayjs(nowTime))
       if (minu <= 0) {
-        console.log('考试已结束')
+        state.visiableExam = true
       } else {
         state.time = Math.ceil(minu / 1000) * 1000
         setTimeout(() => {
@@ -101,6 +104,95 @@ export default defineComponent({
       }
     }
 
+    /**
+     * @description 初始化用户答案
+     */
+    const formatUserAnswers = (item: any, userAnswer: any) => {
+      // 判断是否有结果
+      if (!userAnswer) return []
+      const answers = JSON.parse(userAnswer) || []
+
+      const questionItem = answers.find((child: any) => child.questionId === item.id)
+      return questionItem ? questionItem.details : []
+    }
+
+    /**
+     * @description 下一题 | 测试完成
+     */
+    const onNextQuestion = async () => {
+      try {
+        const questionList = state.questionList || []
+        const userAnswerList: any = [] // 所有题目的答案
+
+        let currentResult = false // 当前题目是否已经答题
+
+        questionList.forEach((question: any, index: number) => {
+          // 格式化所有题目的答案
+          if (question.userAnswer && question.userAnswer.length > 0) {
+            userAnswerList.push({
+              questionId: question.id,
+              details: question.userAnswer
+            })
+          }
+
+          if (index === state.currentIndex) {
+            currentResult = question.userAnswer && question.userAnswer.length > 0 ? true : false
+          }
+        })
+
+        // 判断是否答题了
+        if (!currentResult) {
+          swipeRef.value?.next()
+          return
+        }
+
+        state.nextStatus = true
+        // 判断是否是最后一题
+        if (state.questionList.length === state.currentIndex + 1) {
+          // api-student/studentUnitExamination/completionExamination
+          const { data } = await request.post(
+            '/api-student/studentUnitExamination/completionExamination',
+            {
+              data: {
+                answers: userAnswerList,
+                studentUnitExaminationId: state.id
+              }
+            }
+          )
+          if (data.score >= state.examDetail.passScore) {
+            state.resultStatusType = 'SUCCESS'
+            state.resultInfo = {
+              tips: '恭喜你,测验通过!',
+              score: data.score,
+              examName: data.unitExaminationName
+            }
+          } else {
+            state.resultStatusType = 'FAIL'
+            state.resultInfo = {
+              tips: '本次测验不合格!',
+              score: data.score,
+              examName: data.unitExaminationName
+            }
+          }
+          state.visiableResult = true
+        } else {
+          await request.post('/api-student/studentUnitExamination/submitAnswer', {
+            hideLoading: true,
+            data: {
+              answers: userAnswerList,
+              studentUnitExaminationId: state.id
+            }
+          })
+          swipeRef.value?.next()
+        }
+
+        state.nextStatus = false
+      } catch {
+        //
+        state.nextStatus = false
+      }
+    }
+
     onMounted(() => {
       getExamDetails()
     })
@@ -114,8 +206,11 @@ export default defineComponent({
               <div class={styles.unitCount}>
                 <div class={styles.qNums}>
                   <Icon class={styles.icon} name={iconQuestionNums} />
-                  题目数量 <span class={styles.num}>{state.currentIndex + 1}</span>/
-                  {state.examDetail.questionNum}
+                  题目数量{' '}
+                  <span class={styles.num} style={{ paddingLeft: '6px' }}>
+                    {state.currentIndex + 1}
+                  </span>
+                  /{state.examDetail.questionNum}
                 </div>
                 <div class={styles.qNums}>
                   <Icon class={styles.icon} name={iconCountDown} />
@@ -145,14 +240,33 @@ export default defineComponent({
           }}
         >
           {state.questionList.map((item: any, index: number) => (
+            // item.questionTypeCode === QuestionType.LINK && (
+            //   <SwipeItem>
+            //     <KeepLookQuestion v-model:value={item.userAnswer} data={item} index={index + 1} />
+            //   </SwipeItem>
+            // )
             <SwipeItem>
               {item.questionTypeCode === QuestionType.RADIO && (
-                <ChoiceQuestion index={index + 1} data={item} type="radio" />
+                <ChoiceQuestion
+                  v-model:value={item.userAnswer}
+                  index={index + 1}
+                  data={item}
+                  type="radio"
+                />
               )}
-              {item.questionTypeCode === 'CHECKBOX' && <ChoiceQuestion type="checkbox" />}
-              {item.questionTypeCode === 'SORT' && <DragQuestion />}
-              {item.questionTypeCode === 'LINK' && <KeepLookQuestion />}
-              {item.questionTypeCode === 'PLAY' && <PlayQuestion />}
+              {item.questionTypeCode === QuestionType.CHECKBOX && (
+                <ChoiceQuestion
+                  v-model:value={item.userAnswer}
+                  index={index + 1}
+                  data={item}
+                  type="checkbox"
+                />
+              )}
+              {item.questionTypeCode === QuestionType.SORT && <DragQuestion />}
+              {item.questionTypeCode === QuestionType.LINK && (
+                <KeepLookQuestion v-model:value={item.userAnswer} data={item} index={index + 1} />
+              )}
+              {item.questionTypeCode === QuestionType.PLAY && <PlayQuestion />}
             </SwipeItem>
           ))}
         </Swipe>
@@ -176,16 +290,11 @@ export default defineComponent({
               block
               round
               type="primary"
-              onClick={() => {
-                // if (state.questionList.length - 1 === state.currentIndex) {
-                //   state.visiableSure = true
-                // } else {
-                swipeRef.value?.next()
-                // }
-              }}
+              onClick={onNextQuestion}
+              loading={state.nextStatus}
+              disabled={state.nextStatus}
             >
-              下一题
-              {/* {state.questionList.length === state.currentIndex + 1 ? '测试完成' : '下一题'} */}
+              {state.questionList.length === state.currentIndex + 1 ? '测试完成' : '下一题'}
             </Button>
             <Image
               src={iconButtonList}
@@ -198,7 +307,7 @@ export default defineComponent({
         {/* 题目集合 */}
         <ActionSheet v-model:show={state.visiableAnswer} title="题目列表" safeAreaInsetBottom>
           <AnswerList
-            value={[1, 3, 4]}
+            value={state.questionList}
             onSelect={(item: any) => {
               // 跳转,并且跳过动画
               swipeRef.value?.swipeTo(item, {
@@ -215,13 +324,18 @@ export default defineComponent({
           style={{ background: 'transparent', width: '96%' }}
         >
           <ResultFinish
-            // status="FAIL"
+            status={state.resultStatusType as any}
+            result={state.resultInfo}
             confirmButtonText="我知道了"
             cancelButtonText="去练习"
-            onClose={() => (state.visiableResult = false)}
+            onClose={() => {
+              state.visiableResult = false
+              router.back()
+            }}
             onConform={() => {
               console.log('Success')
               state.visiableResult = false
+              router.back()
             }}
           />
         </Popup>

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

@@ -9,10 +9,6 @@ export default defineComponent({
       type: Array,
       default: () => []
     },
-    answerList: {
-      type: Array,
-      default: () => []
-    },
     statusList: {
       type: Array,
       default: () => [
@@ -42,9 +38,11 @@ export default defineComponent({
         </div>
 
         <Grid class={styles.aList} columnNum={6} border={false}>
-          {[1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 10].map((item: any) => (
-            <GridItem onClick={() => emit('select', item)}>
-              <span class={props.value.includes(item) && styles.answered}>{item}</span>
+          {props.value.map((item: any, index: number) => (
+            <GridItem onClick={() => emit('select', index)}>
+              <span class={item.userAnswer && item.userAnswer.length > 0 && styles.answered}>
+                {index + 1}
+              </span>
             </GridItem>
           ))}
         </Grid>

+ 27 - 19
src/views/unit-test/model/choice-question/index.tsx

@@ -8,8 +8,8 @@ export default defineComponent({
   name: 'choice-question',
   props: {
     value: {
-      type: [String, Number, Array],
-      default: ''
+      type: Array,
+      default: () => []
     },
     type: {
       type: String as PropType<'radio' | 'checkbox'>,
@@ -33,22 +33,38 @@ export default defineComponent({
   setup(props, { emit }) {
     const onSelect = (item: any) => {
       if (props.readOnly) return
+      const value: any = props.value || []
+      const result = {
+        answerId: item.examinationQuestionAnswerId,
+        answer: item.questionAnswer,
+        extra: item.questionExtra
+      }
       if (props.type === 'checkbox') {
-        // 判断是否已选过
-        const value: any = props.value
-        if (value.includes(item.index)) {
-          const index = value.findIndex((v: any) => v === item.index)
-          value.splice(index, 1)
+        const tempIndex = value.findIndex(
+          (c: any) => c.answerId === item.examinationQuestionAnswerId
+        )
+        if (tempIndex >= 0) {
+          value.splice(tempIndex, 1)
           emit('update:value', [...value])
         } else {
-          emit('update:value', [item.index, ...value])
+          emit('update:value', [...value, result])
         }
       } else {
-        emit('update:value', item.index)
+        emit('update:value', [result])
       }
     }
 
-    const answers = computed(() => props.data.answers || [])
+    const answers = computed(() => {
+      const list: any = props.data.answers || []
+      const value: any = props.value || []
+      list.forEach((item: any) => {
+        const tempIndex = value.findIndex(
+          (c: any) => c.answerId === item.examinationQuestionAnswerId
+        )
+        item.checked = tempIndex !== -1 ? true : false
+      })
+      return list
+    })
     const mediaUrls = computed(() => (props.data.mediaUrls ? props.data.mediaUrls.split(',') : ''))
 
     return () => (
@@ -68,15 +84,7 @@ export default defineComponent({
           {/* styles.active */}
           {answers.value.map((item: any, index: number) => (
             <div
-              class={[
-                styles.unitAnswer,
-                props.type === 'radio' &&
-                  props.value === item.examinationQuestionAnswerId &&
-                  styles.active,
-                props.type === 'checkbox' &&
-                  (props.value as any).includes(item.examinationQuestionAnswerId) &&
-                  styles.active
-              ]}
+              class={[styles.unitAnswer, item.checked && styles.active]}
               onClick={() => onSelect(item)}
             >
               <span class={styles.option}>{labelOptions[index + 1]}.</span>

+ 1 - 0
src/views/unit-test/model/keep-look-question/index.module.less

@@ -63,6 +63,7 @@
     font-weight: 500;
     color: #333333;
     line-height: 22px;
+    text-align: center;
   }
 
   .active {

+ 55 - 63
src/views/unit-test/model/keep-look-question/index.tsx

@@ -8,16 +8,17 @@ export default defineComponent({
   name: 'keep-look-question',
   props: {
     value: {
-      type: [String, Number, Array],
-      default: ''
+      type: Array,
+      default: () => []
     },
-    type: {
-      type: String as PropType<'radio' | 'checkbox'>,
-      default: 'radio'
+    index: {
+      // 题目是第几道
+      type: Number,
+      default: 1
     },
-    answers: {
+    data: {
       type: Object,
-      default: {}
+      default: () => ({})
     },
     /* 只读 */
     readOnly: {
@@ -31,43 +32,9 @@ export default defineComponent({
     const state = reactive({
       answerDomId: 'answer' + +new Date(),
       answerRect: {} as any,
-
       sortable: null as any,
       list: [] as any,
-      options: [
-        {
-          index: 1,
-          value: 'Sol',
-          left: false,
-          right: false,
-          leftLocked: false, // 是否已经连线
-          rightLocked: false // 是否已经连线
-        },
-        {
-          index: 2,
-          value: 'Sal',
-          left: false,
-          right: false,
-          leftLocked: false, // 是否已经连线
-          rightLocked: false // 是否已经连线
-        },
-        {
-          index: 3,
-          value: 'La',
-          left: false,
-          right: false,
-          leftLocked: false, // 是否已经连线
-          rightLocked: false // 是否已经连线
-        },
-        {
-          index: 4,
-          value: 'Si',
-          left: false,
-          right: false,
-          leftLocked: false, // 是否已经连线
-          rightLocked: false // 是否已经连线
-        }
-      ],
+      options: [] as any,
       drawLineList: [] as any,
       selectItem: [] as any
     })
@@ -133,6 +100,8 @@ export default defineComponent({
           renderDrawLine(canvasRef.value)
         }
       }
+
+      onSelect()
     }
 
     const onRightClick = (e: any, item: any) => {
@@ -196,6 +165,8 @@ export default defineComponent({
           renderDrawLine(canvasRef.value)
         }
       }
+
+      onSelect()
     }
 
     /**
@@ -292,23 +263,46 @@ export default defineComponent({
       ctx.stroke()
     }
 
-    // const onSelect = (item: any) => {
-    //   if (props.type === 'checkbox') {
-    //     // 判断是否已选过
-    //     const value: any = props.value
-    //     if (value.includes(item.index)) {
-    //       const index = value.findIndex((v: any) => v === item.index)
-    //       value.splice(index, 1)
-    //       emit('update:value', [...value])
-    //     } else {
-    //       emit('update:value', [item.index, ...value])
-    //     }
-    //   } else {
-    //     emit('update:value', item.index)
-    //   }
-    // }
+    // 返回选中的结果
+    const onSelect = () => {
+      const options = state.options || []
+      const drawLineList = state.drawLineList || []
+      const result: any = []
+      drawLineList.forEach((item: any) => {
+        const leftOption = options.find((child: any) => child.index === item.leftIndex)
+        const rightOption = options.find((child: any) => child.index === item.rightIndex)
+        result.push({
+          answerId: leftOption.index,
+          answer: leftOption.leftValue,
+          extra: rightOption.rightValue
+        })
+      })
+      emit('update:value', result)
+    }
+
+    const initOptions = () => {
+      const answers = props.data.answers || []
+      answers.forEach((answer: any) => {
+        const tmp = {
+          index: answer.examinationQuestionAnswerId,
+          leftValue: answer.questionAnswer,
+          rightValue: answer.questionExtra,
+          leftType: answer.questionAnswerTypeCode || 'TXT',
+          rightType: answer.questionExtraTypeCode || 'TXT',
+          left: false,
+          right: false,
+          leftLocked: false, // 是否已经连线
+          rightLocked: false // 是否已经连线
+        }
+
+        state.options.push(tmp)
+      })
+
+      console.log(state.options)
+    }
 
     onMounted(() => {
+      initOptions()
       // 获取canvas 对象
       nextTick(() => {
         // 获取canvas元素定位
@@ -343,17 +337,15 @@ export default defineComponent({
                 class={[styles.unitItem, item.left && styles.active]}
                 onClick={(e: any) => onLeftClick(e, item)}
               >
-                <Image
-                  src="https://lanhu-dds-backend.oss-cn-beijing.aliyuncs.com/merge_image/imgs/dbb27307d428424c8efb9f26032cfa1a_mergeImage.png"
-                  class={styles.img}
-                />
+                {item.leftType === 'TXT' && item.leftValue}
+                {item.leftType === 'IMAGE' && <Image src={item.leftValue} class={styles.img} />}
               </div>
               <div
                 class={[styles.unitItem, item.right && styles.active]}
                 onClick={(e: any) => onRightClick(e, item)}
               >
-                {item.value}
-                {item.index}
+                {item.rightType === 'TXT' && item.rightValue}
+                {item.rightType === 'IMAGE' && <Image src={item.rightValue} class={styles.img} />}
               </div>
             </div>
           ))}

+ 11 - 6
src/views/unit-test/model/result-finish/index.tsx

@@ -18,9 +18,13 @@ export default defineComponent({
       type: String as PropType<'SUCCESS' | 'FAIL'>,
       default: 'SUCCESS'
     },
-    resultString: {
-      type: String,
-      default: '恭喜你,测验通过!'
+    result: {
+      type: Object,
+      default: () => ({
+        tips: '恭喜你,测验通过!',
+        score: 0,
+        examName: ''
+      })
     }
   },
   emits: ['close', 'conform'],
@@ -30,10 +34,11 @@ export default defineComponent({
         <div class={styles.finishContainer}>
           <div class={styles.finishContent}>
             <div class={styles.scoreNums}>
-              98<span>分</span>
+              {props.result.score}
+              <span>分</span>
             </div>
-            <div class={styles.scoreName}>《长笛level上册测验一》</div>
-            <div class={styles.scoreResult}>{props.resultString}</div>
+            <div class={styles.scoreName}>{props.result.examName}</div>
+            <div class={styles.scoreResult}>{props.result.tips}</div>
           </div>
         </div>