Explorar o código

Merge branch 'feature-tianyong' into gym-dev

TIANYONG hai 6 meses
pai
achega
c281faee14

BIN=BIN
public/favicon.ico


+ 12 - 19
src/page-instrument/api.ts

@@ -14,11 +14,8 @@ export const studentQueryUserInfo = async () => {
         instrumentId: "",
         phone:data.phone,
         clientType:"TEACHER",
-        username:"",
-        subjectNames:"",
-        avatar:"",
         id:data.id,
-        vipMember: true,
+        vipMember: true, // 管乐迷 会员现在在外面判断的 所以这里默认不开启会员验证
         gender:""
       }
       return res
@@ -36,12 +33,9 @@ export const studentQueryUserInfo = async () => {
       res.data = {
         instrumentId: "",
         phone:data.phone,
-        clientType:"STUDENT",
-        username:"",
-        subjectNames:"",
-        avatar:"",
+        clientType:"web",
         id:data.id,
-        vipMember: true,
+        vipMember: true, // 管乐迷 会员现在在外面判断的 所以这里默认不开启会员验证
         gender:""
       }
       return res
@@ -50,14 +44,11 @@ export const studentQueryUserInfo = async () => {
       const res = await request.get(`/student/queryUserInfo`);
       const data = res.data.student
       res.data = {
-        instrumentId: "",
+        instrumentId: res.data.instrumentId,
         phone:data.phone,
         clientType:"STUDENT",
-        username:"",
-        subjectNames:"",
-        avatar:"",
         id:data.id,
-        vipMember: true,
+        vipMember: true, // 管乐迷 会员现在在外面判断的 所以这里默认不开启会员验证
         gender:""
       }
       return res
@@ -76,13 +67,15 @@ export const sysMusicScoreAccompanimentQueryPage = (sysMusicScoreId: string) =>
 export const api_musicPracticeRecordSave = (data: any) => {
   return request.post("/musicPracticeRecord/save", { requestType: "json", data });
 };
-/** 添加作业记录 */
-export const api_lessonTrainingSubmitTraining = (data: any) => {
-  return request.post("/lessonTraining/submitTraining", { requestType: "json", data });
+/** 添加作业记录(练习或评测) */
+export const api_lessonTrainingSubmitTraining = (data: any, type?: string) => {
+  const url = type === 'homeWork' ? `/studentCourseHomework/addStudentHomeworkRecord` : `/lessonExamination/submit`;
+  return request.post("/studentCourseHomework/addStudentHomeworkRecord", { requestType: "json", data });
 };
 /** 获取作业详情 */
-export const api_lessonTrainingTrainingStudentDetail = (id: any) => {
-  return request.get(`/lessonTraining/trainingContentStudentDetail?id=${id}`);
+export const api_lessonTrainingTrainingStudentDetail = (id: any, type: string) => {
+  const url = type === 'homeWork' ? `/studentCourseHomework/homeworkDetail?id=${id}` : `/lessonExamination/getDetail?studentLessonExaminationDetailId=${id}`;
+  return request.get(url);
 };
 /** 上传评测视频 */
 export const api_musicPracticeRecordVideoUpload = (data: any) => {

+ 9 - 15
src/page-instrument/custom-plugins/work-ealuating/index.tsx

@@ -36,19 +36,13 @@ export default defineComponent({
 		};
 		/** 获取作业详情 */
 		const getWorkData = async () => {
-			let trainingContent: any = {};
-			try {
-				trainingContent = JSON.parse(props.workeData.trainingContent);
-			} catch (error) {
-				console.log("🚀 ~ error:", error);
-			}
-			if (["BEGINNER", "ADVANCED", "PERFORMER"].includes(trainingContent.evaluateDifficult)) {
-				evaluatingWorkData.difficulty = trainingContent.evaluateDifficult;
-				state.setting.evaluationDifficulty = trainingContent.evaluateDifficult;
-
-				evaluatingWorkData.evaluateSpeed = trainingContent.evaluateSpeed;
-				evaluatingWorkData.start = Number(trainingContent.practiceChapterBegin);
-				evaluatingWorkData.end = Number(trainingContent.practiceChapterEnd);
+			const workeData = props.workeData;
+			if (workeData.id) {
+				evaluatingWorkData.difficulty = workeData.heardLevel;
+				state.setting.evaluationDifficulty = workeData.heardLevel;
+				evaluatingWorkData.evaluateSpeed = state.originSpeed;
+				evaluatingWorkData.start = Number(workeData.start);
+				evaluatingWorkData.end = Number(workeData.end);
 				state.userChooseEndIndex = evaluatingWorkData.end
 				// 设置小节
 				setSection(evaluatingWorkData.start, evaluatingWorkData.end, evaluatingWorkData.evaluateSpeed);
@@ -58,8 +52,8 @@ export default defineComponent({
 		const addEvaluatingWorkRecored = async (data: any) => {
 			try {
 				const res = await api_lessonTrainingSubmitTraining({
-					id: evaluatingWorkData.evaluatingRecord,
-					trainingTimes: data?.score || 0,
+					studentLessonExaminationDetailId: evaluatingWorkData.evaluatingRecord,
+					score: data?.score || 0,
 					recordId: evaluatingData.resultData.recordId
 				});
 			} catch (error) {

+ 12 - 17
src/page-instrument/custom-plugins/work-home/index.tsx

@@ -3,6 +3,7 @@ import styles from "./index.module.less";
 // import { verifyMembershipServices } from "../vip-verify";
 import { api_lessonTrainingSubmitTraining, api_lessonTrainingTrainingStudentDetail } from "../../api";
 import state, { handleSetSpeed, hanldeDirectSelection, setSection } from "/src/state";
+import { getQuery } from "/src/utils/queryString";
 
 export default defineComponent({
 	name: "HomeWork",
@@ -14,6 +15,7 @@ export default defineComponent({
 	},
 	emits: ["change"],
 	setup(props, {expose}) {
+		const query = getQuery();
 		const training = reactive({
 			trainingTimes: "",
 			trainingSpeed: 0,
@@ -40,17 +42,11 @@ export default defineComponent({
 		const getWorkData = async () => {
 			const workeData = props.workeData;
 			if (workeData.id) {
-				let trainingContent: any = {};
-				try {
-					trainingContent = JSON.parse(workeData.trainingContent);
-				} catch (error) {
-					console.log("🚀 ~ error:", error);
-				}
-				training.times = trainingContent.trainingTimes || 0;
-				training.trainingTimes = (workeData.trainingTimes / 60).toFixed(1) || "0";
-				training.trainingSpeed = trainingContent.practiceSpeed;
-				training.start = Number(trainingContent.practiceChapterBegin);
-				training.end = Number(trainingContent.practiceChapterEnd);
+				training.times = workeData.times || 0;
+				training.trainingTimes = workeData.trainingTimes || 0;
+				training.trainingSpeed = workeData.trainingSpeed;
+				training.start = Number(workeData.start);
+				training.end = Number(workeData.end);
 				state.userChooseEndIndex = training.end
 				if (training.isAddOk === 0) {
 					// 设置小节
@@ -60,9 +56,9 @@ export default defineComponent({
 		};
 
 		const getWorkDetail = async () => {
-			const res = await api_lessonTrainingTrainingStudentDetail(props.workeData.id);
+			const res = await api_lessonTrainingTrainingStudentDetail(props.workeData.id, 'homeWork');
 			if (res?.code === 200) {
-				training.trainingTimes = (res.data.trainingTimes / 60).toFixed(1) || "0";
+				training.trainingTimes = res.data.trainingTimes || 0;
 			}
 		};
 
@@ -71,9 +67,8 @@ export default defineComponent({
 			let total = Math.ceil((Date.now() - training.starTime) / 1000);
 			try {
 				const res = await api_lessonTrainingSubmitTraining({
-					id: props.workeData.id,
-					trainingTimes: total,
-				});
+					id: props.workeData.id
+				}, 'homeWork');
 				if (res?.code == 200) {
 					getWorkDetail();
 				}
@@ -107,7 +102,7 @@ export default defineComponent({
 		})
 		return () => (
 			<div class={styles.homework}>
-				{training.trainingTimes} / {training.times} 分钟
+				{training.trainingTimes} / {training.times} 
 			</div>
 		);
 	},

+ 3 - 2
src/page-instrument/custom-plugins/work-index/index.tsx

@@ -45,9 +45,10 @@ export default defineComponent({
 			headTopData.handleChangeModeType(type);
 		};
 		const getWorkDetail = async () => {
-			const res = await api_lessonTrainingTrainingStudentDetail(query.workRecord);
+			const workId = query.workRecord ? query.workRecord : query.evaluatingRecord;
+			const res = await api_lessonTrainingTrainingStudentDetail(workId, query.workRecord ? 'homeWork' : '');
 			if (res?.code === 200) {
-				data.trainingType = res.data.trainingType;
+				data.trainingType = query.workRecord ? 'PRACTICE' : 'EVALUATION';
 				data.worke = res.data;
 				setModelType();
 			}

+ 7 - 29
src/page-instrument/header-top/index.tsx

@@ -355,7 +355,7 @@ export default defineComponent({
       //if (headTopData.modeType !== "show" || ["follow"].includes(state.modeType)) return { display: false, disabled: true };
       if (["follow"].includes(state.modeType)) return { display: false, disabled: true };
       // 音频播放中 禁用
-      if (state.playState === "play" || query.workRecord) return { display: true, disabled: true };
+      if (state.playState === "play" || state.isHomeWork) return { display: true, disabled: true };
 
       return {
         disabled: false,
@@ -399,8 +399,8 @@ export default defineComponent({
     /** 播放类型按钮 */
     const playTypeBtn = computed(() => {
       // 选择模式,跟练模式,评测模式 不显示
-      //if (headTopData.modeType !== "show" || state.modeType === "follow" || state.modeType === "evaluating" || query.workRecord) return { display: false, disabled: false };
-      if (state.modeType === "follow" || state.modeType === "evaluating" || query.workRecord) return { display: false, disabled: false };
+      //if (headTopData.modeType !== "show" || state.modeType === "follow" || state.modeType === "evaluating" || state.isHomeWork) return { display: false, disabled: false };
+      if (state.modeType === "follow" || state.modeType === "evaluating" || state.isHomeWork) return { display: false, disabled: false };
       if (!state.isAppPlay) {
         let index = 0;
         state.music && index++;
@@ -484,36 +484,14 @@ export default defineComponent({
     /** 重置按钮 */
     const restoreBtn = computed(() => {
       // 播放中 禁用
-      if (state.playState === "play" || evaluatingData.startBegin || followData.start) return { display: true, disabled: true };
+      if (state.playState === "play" || evaluatingData.startBegin || followData.start || state.isHomeWork) return { display: true, disabled: true };
 
       return {
         disabled: false,
         display: true,
       };
     });
-
-    const isAllBtns = computed(() => {
-      const flag = converBtn.value.display && speedBtn.value.display && selectBtn.value.display && originBtn.value.display && toggleBtn.value.display && showGuide.value;
-      return flag;
-    });
-
-    const isAllBtnsStudent = computed(() => {
-      const flag = converBtn.value.display && speedBtn.value.display && selectBtn.value.display && originBtn.value.display && toggleBtn.value.display && showStudentGuide.value;
-
-      return flag;
-    });
-
-    const showGuideIndex = computed(() => {
-      // 从课堂乐器学生端课件预览默认不显示会员
-      if (storeData.user.vipMember || state.paymentType === "FREE" || query.showCourseMember === "true") {
-        // 学生端
-        return true;
-      } else {
-        // vip
-        return false;
-      }
-    });
-
+    
     const browInfo = browser();
     /** 返回 */
     const handleBack = () => {
@@ -523,7 +501,7 @@ export default defineComponent({
         window.close();
         return;
       }
-      if ((browInfo.iPhone || browInfo.ios) && query.workRecord) {
+      if ((browInfo.iPhone || browInfo.ios) && state.isHomeWork) {
         setTimeout(() => {
           api_back();
         }, 550);
@@ -535,7 +513,7 @@ export default defineComponent({
     /** 根据参数设置模式 */
     const getQueryModelSetModelType = () => {
       /** 作业模式 start, 如果为作业模式不处理,让作业模块处理 */
-      if (query.workRecord) {
+      if (state.isHomeWork) {
         return;
       }
       /** 作业模式 end */

+ 2 - 7
src/page-instrument/header-top/modeView.tsx

@@ -26,8 +26,6 @@ export default defineComponent({
   setup() {
     const query = getQuery();
     const data = reactive({
-      showPC: false,
-      showStudent: false,
       showVip: false,
     });
     // const modeImgDom1 = ref();
@@ -36,15 +34,12 @@ export default defineComponent({
     const openGuid = () => {
       // 加载后 判断 端口号 加载对应的引导
       if (storeData.platformType !== "STUDENT" || storeData.user.clientType !== "STUDENT") {
-        // PC
-        data.showPC = true;
       } else {
         // 从课堂乐器学生端课件预览默认不显示会员
         if (storeData.user.vipMember || state.paymentType === "FREE" || query.showCourseMember === "true") {
-          // 学生端
-          data.showStudent = true;
+
         } else {
-          // vip
+          // 不是vip
           data.showVip = true;
           state.isVip = true;
         }

+ 5 - 0
src/page-instrument/header-top/settting/index.module.less

@@ -171,6 +171,11 @@
                         }
                     }
                 }
+                .speBox {
+                    >div {
+                        width: 48px;
+                    }
+                }                
                 .frequency{
                     display: flex;
                     align-items: center;

+ 26 - 1
src/page-instrument/header-top/settting/index.tsx

@@ -26,6 +26,7 @@ export default defineComponent({
 			screenModelShow: false, // 投屏帮助
 			recommendationShow: false, // 建议
 		});
+        const zoomList = [{name:'默认',value: 0.8},{name:'1.25x',value: 1.25},{name:'1.5x',value: 1.5},{name:'1.75x',value: 1.75}] 
 		const parentClassName = "recommenBoxClass_drag";
 		const userId = storeData.user?.id ? String(storeData.user?.id) : "";
 		const positionInfo =
@@ -273,7 +274,31 @@ export default defineComponent({
                                 </div>
                             </div> : null
                         }
-
+                        {
+                            <div class={styles.cellBox}>
+                                <div class={styles.tit}>谱面大小</div>
+                                <div class={[styles.radioBox, styles.speBox]}>
+                                    {
+                                        zoomList.map(item=>{
+                                            return <div class={ state.zoom===item.value && styles.active } onClick={ async ()=>{ 
+                                                if(state.zoom === item.value){
+                                                    return
+                                                }
+                                                await checkMoveNoSave();
+                                                headTopData.settingMode = false
+                                                // resetRenderMusicScore(state.musicRenderType)
+                                                const _time = setTimeout(() => {
+                                                    state.zoom = item.value as any
+                                                    localStorage.setItem('scoreZoom',String(state.zoom))
+                                                    clearTimeout(_time)
+                                                    refreshMusicSvg();
+                                                }, 100);
+                                            } }>{item.name}</div>
+                                        })
+                                    }
+                                </div>
+                            </div>
+                        }
                         <div class={styles.cellBtnBox}>
                             <img  src={headImg("tpbz.png")} onClick={() => (helperData.screenModelShow = true)} />
                             {

+ 2 - 1
src/page-instrument/view-detail/index.tsx

@@ -146,6 +146,7 @@ export default defineComponent({
       (window as any).appName = "colexiu";
       const id = query.id || "43554";
       state.isCbsView = query.isCbs;
+      state.isHomeWork = query.workRecord || query.evaluatingRecord;
       // 如果是纯预览模式,0.65倍缩放谱面
       state.isPreView = query.isPreView;
       if (state.isPreView) {
@@ -606,7 +607,7 @@ export default defineComponent({
             {/* 今日练习统计 */}
             {state.systemType === "student" && <ExerciseStatistics />}
             {/* 作业 */}
-            {query.workRecord && <WorkIndex />}
+            {state.isHomeWork && <WorkIndex />}
             {/* 曲谱列表 */}
             {isMusicList.value && <TheMusicList />}
           </>

+ 2 - 2
src/page-instrument/view-detail/smoothAnimation/index.ts

@@ -443,8 +443,8 @@ function getPointsPosByBatePos(): pointsPosType {
    }
    extendPoint.MeasureNumberXML += 100 // 防止MeasureNumberXML重复
    extendPoint.noteId += 100 // 防止noteId重复
-   // 当总长度减30小于最后一个音符时候,取最后一个音符加15
-   extendPoint.x = smoothAnimationState.canvasDomWith - 30 > extendPoint.x ? smoothAnimationState.canvasDomWith - 30 : extendPoint.x + 15
+   // 当总长度减20 和 最后一个音符加 10 取最大值 34是一倍的边距
+   extendPoint.x = Math.max(smoothAnimationState.canvasDomWith - 34 * state.zoom - 20, extendPoint.x + 10)
    pointsPos.push(extendPoint)
    return pointsPos
 }

+ 15 - 11
src/state.ts

@@ -581,6 +581,8 @@ const state = reactive({
   evxmlAddPartName: false, // 妙极客的部分曲子没有part-name,需要自行添加的part-name
   /** 乐器id */
   instrumentId: null,
+  /** 是否是作业模式(包含练习和评测) */
+  isHomeWork: false,
 });
 const browserInfo = browser();
 let offset_duration = 0;
@@ -677,7 +679,7 @@ const dynamicShowPlaySpeed = (index: number) => {
 export const initSetPlayRate = () => {
   const item: any = (state.sectionStatus && state.section.length === 2) ? state.sectionFirst || state.section[0] : state.times[state.activeNoteIndex];
   if (item && item.measureSpeed) {
-    const ratio = state.speed / item.measureSpeed
+    const ratio = state.speed / Math.floor(item.measureSpeed)
     // state.audiosInstance?.setSpeed(ratio)
     state.basePlayRate = ratio || 1;
     console.log('播放倍率',state.basePlayRate)
@@ -773,7 +775,9 @@ const handlePlaying = () => {
 };
 /** 跳转到指定音符开始播放 */
 export const skipNotePlay = async (itemIndex: number, isStart = false, handType?: string) => {
+  // 纯预览模式,练习、评测作业模式,禁止手动点击跳转音符
   if (state.isPreView) return;
+  if (handType === 'manual' && (query.workRecord || query.evaluatingRecord)) return;
   const item = state.times[itemIndex];
   // 如果是选段状态,可以点击段落范围内的音符,从当前音符开始播放,如果不是段落内的音符,直接return
   if (handType === 'manual' && state.section.length === 2 && !(item.MeasureNumberXML >= state.section[0].MeasureNumberXML && item.MeasureNumberXML <= state.section[1].MeasureNumberXML)) {
@@ -1286,7 +1290,7 @@ export const hanldeDirectSelection = (list: any[]) => {
     state.section = formateSelectMearure(list);
     // 选段完成后,需要根据预报小节的速度,设置右下角显示的速度
     const currentItem: any = (state.sectionStatus && state.section.length === 2) ? state.sectionFirst || state.section[0] : state.times[state.activeNoteIndex];
-    if (currentItem.measureSpeed && query.workRecord === undefined) {
+    if (currentItem.measureSpeed && query.workRecord === undefined && query.evaluatingRecord === undefined) {
       handleSetSpeed(currentItem.measureSpeed);
     }
     console.log('选段小节', state.section)
@@ -1388,14 +1392,7 @@ const getMusicInfo = async (res: any) => {
     partIndex = state.partIndex;
   }
   // 布置作业 取作业的乐器id
-  const workRecord = query.workRecord
   let workRecordInstrumentId:undefined | string
-  if(workRecord){
-    const res = await api_lessonTrainingTrainingStudentDetail(workRecord);
-    if (res?.code === 200) {
-      workRecordInstrumentId = res.data?.instrumentId
-    }
-  }
   /* 获取声轨列表 */
   let xmlString = await fetch(res.data.xmlFileUrl).then((response) => response.text());
   xmlString = xmlAddPartName(xmlString);
@@ -1726,11 +1723,18 @@ const setState = (data: any, index: number) => {
   // 如果是PC端,放大曲谱
   state.platform = query.platform?.toLocaleUpperCase() || "";
   if (state.platform === IPlatform.PC) {
+    // pc端,谱面默认初始大小设置为1.5
+    state.zoom = 1.5;
     if (query.zoom <= 1) {
-      state.zoom = query.zoom || state.zoom;
+      state.zoom = query.zoom ? Number(query.zoom) : state.zoom;
+    } else {
+      state.zoom = localStorage.getItem('scoreZoom') ? Number(localStorage.getItem('scoreZoom')) : state.zoom
     }
     state.enableEvaluation = false;
   }
+  if (storeData.isApp) {
+    state.zoom = localStorage.getItem('scoreZoom') ? Number(localStorage.getItem('scoreZoom')) : state.zoom
+  }
   /**
    * 默认渲染什么谱面类型 & 能否转谱逻辑
    * 渲染类型:首先取url参数musicRenderType,没有该参数则取musicalInstruments字段匹配的当前分轨的defaultScore,没有匹配到则取默认值('firstTone')
@@ -2162,7 +2166,7 @@ export const refreshMusicSvg = () => {
   clearSelection();
   resetBaseRate();
   state.activeMeasureIndex = -1;
-  if (query.workRecord) {
+  if (query.workRecord || query.evaluatingRecord) {
     state.workSectionNeedReset = true;
   }
   // 销毁旋律线

BIN=BIN
src/view/abnormal-pop/icon_btn.png


+ 30 - 0
src/view/abnormal-pop/index.module.less

@@ -130,4 +130,34 @@
             opacity: 0.8;
         }
     }
+}
+
+.loadingCssBox{
+    width: 27px;
+    height: 27px;
+    display: flex;
+    justify-content: space-between;
+    flex-wrap: wrap;
+    align-content: space-between;
+    margin-bottom: 24px;
+    animation: rotate 1.5s linear infinite;
+    .loadingCssItem{
+        width: 11px;
+        height: 11px;
+        border-radius: 50%;
+        background: #11FFD4;
+        opacity: 0.5;
+        &:nth-child(2){
+            opacity:1;
+        }
+    }
+}
+
+@keyframes rotate {
+    from {
+        transform: rotate(0deg);
+    }
+    to {
+        transform: rotate(360deg);
+    }
 }

+ 6 - 4
src/view/abnormal-pop/index.tsx

@@ -3,9 +3,6 @@ import styles from "./index.module.less";
 import state from "/src/state";
 import { popImgs } from "/src/view/evaluating";
 import { evaluatingData } from "/src/view/evaluating";
-import { Vue3Lottie } from "vue3-lottie";
-import loading from "./loading.json";
-import animBg from "/src/page-instrument/view-detail/images/refresh_anim.gif";
 
 export default defineComponent({
   name: "abnormal-pop",
@@ -33,7 +30,12 @@ export default defineComponent({
           // 	<p>正在连接服务器,请稍后…</p>
           // </div>
           <div class={styles.loadingPop}>
-            <img class={styles.loadingIcon} src={animBg} />
+            <div class={styles.loadingCssBox}>
+                <div class={styles.loadingCssItem}></div>
+                <div class={styles.loadingCssItem}></div>
+                <div class={styles.loadingCssItem}></div>
+                <div class={styles.loadingCssItem}></div>
+            </div>            
             {/* <Vue3Lottie animationData={animBg} class={styles.loadingIcon}></Vue3Lottie> */}
             <div class={styles.loadingTip}>正在连接中,请稍等…</div>
             <div class={styles.loadingClose} onClick={() => emit("close")}>

+ 1 - 1
src/view/selection/index.tsx

@@ -381,7 +381,7 @@ export default defineComponent({
 						sectionPosData.value.map((item,index) =>{
 							return (
 								item && <div class={styles.selectBox} style={item}>
-									<div class={[styles.selectHandle,index>0&&styles.selectHandleRight,(state.playState==="play" || query.workRecord)&&styles.playIng]} onClick={()=>{
+									<div class={[styles.selectHandle,index>0&&styles.selectHandleRight,(state.playState==="play" || state.isHomeWork)&&styles.playIng]} onClick={()=>{
 										// 如果选择了2个 删除左边的时候
 										if(state.section.length===2&&index === 0){
 											state.section = []