瀏覽代碼

Merge branch 'feature-tianyong-newVersion' into ktyq-online-new

TIANYONG 1 月之前
父節點
當前提交
d4525085b7
共有 100 個文件被更改,包括 745 次插入201 次删除
  1. 5 0
      src/helpers/communication.ts
  2. 2 4
      src/helpers/customMusicScore.ts
  3. 1 1
      src/helpers/metronome.ts
  4. 4 0
      src/page-instrument/api.ts
  5. 2 2
      src/page-instrument/component/authorName/index.module.less
  6. 二進制
      src/page-instrument/custom-plugins/guide-driver/images/evaluating/r3-2.png
  7. 二進制
      src/page-instrument/custom-plugins/guide-driver/images/practise/d777.png
  8. 24 0
      src/page-instrument/custom-plugins/guide-driver/index.less
  9. 41 4
      src/page-instrument/custom-plugins/guide-driver/index.tsx
  10. 30 0
      src/page-instrument/custom-plugins/work-ealuating/index.module.less
  11. 46 3
      src/page-instrument/custom-plugins/work-ealuating/index.tsx
  12. 65 6
      src/page-instrument/custom-plugins/work-home/index.module.less
  13. 96 14
      src/page-instrument/custom-plugins/work-home/index.tsx
  14. 6 1
      src/page-instrument/custom-plugins/work-index/index.tsx
  15. 二進制
      src/page-instrument/evaluat-model/countdown/imgs/step1.png
  16. 二進制
      src/page-instrument/evaluat-model/countdown/imgs/step2.png
  17. 二進制
      src/page-instrument/evaluat-model/countdown/imgs/step3.png
  18. 二進制
      src/page-instrument/evaluat-model/evaluat-result/img/tjzy.png
  19. 6 1
      src/page-instrument/evaluat-model/evaluat-result/index.tsx
  20. 二進制
      src/page-instrument/evaluat-model/icons/confirm.png
  21. 二進制
      src/page-instrument/evaluat-model/icons/lanya_erji.png
  22. 二進制
      src/page-instrument/evaluat-model/icons/no_erji.png
  23. 二進制
      src/page-instrument/evaluat-model/icons/tip_btn.png
  24. 二進制
      src/page-instrument/evaluat-model/icons/tip_erji.png
  25. 二進制
      src/page-instrument/evaluat-model/icons/youxian_erji.png
  26. 61 6
      src/page-instrument/evaluat-model/index.tsx
  27. 26 0
      src/page-instrument/evaluat-model/submit-nodone/index.module.less
  28. 25 0
      src/page-instrument/evaluat-model/submit-nodone/index.tsx
  29. 二進制
      src/page-instrument/follow-model/microphone/images/microBg.png
  30. 二進制
      src/page-instrument/follow-model/microphone/images/micro_cancel.png
  31. 二進制
      src/page-instrument/follow-model/microphone/images/micro_confirm.png
  32. 二進制
      src/page-instrument/header-top/image/background.png
  33. 二進制
      src/page-instrument/header-top/image/background1.png
  34. 二進制
      src/page-instrument/header-top/image/background1Act.png
  35. 二進制
      src/page-instrument/header-top/image/backgroundAct.png
  36. 二進制
      src/page-instrument/header-top/image/bg.png
  37. 二進制
      src/page-instrument/header-top/image/icon_menu.png
  38. 二進制
      src/page-instrument/header-top/image/icon_menuAct.png
  39. 二進制
      src/page-instrument/header-top/image/icon_pause.png
  40. 二進制
      src/page-instrument/header-top/image/icon_play.png
  41. 二進制
      src/page-instrument/header-top/image/icon_reset.png
  42. 二進制
      src/page-instrument/header-top/image/mingsong.png
  43. 二進制
      src/page-instrument/header-top/image/mingsongAct.png
  44. 二進制
      src/page-instrument/header-top/image/mode.png
  45. 二進制
      src/page-instrument/header-top/image/music.png
  46. 二進制
      src/page-instrument/header-top/image/music1.png
  47. 二進制
      src/page-instrument/header-top/image/music1Act.png
  48. 二進制
      src/page-instrument/header-top/image/musicAct.png
  49. 二進制
      src/page-instrument/header-top/image/perform.png
  50. 二進制
      src/page-instrument/header-top/image/perform1.png
  51. 二進制
      src/page-instrument/header-top/image/performAct.png
  52. 二進制
      src/page-instrument/header-top/image/radio.png
  53. 二進制
      src/page-instrument/header-top/image/radioActive.png
  54. 二進制
      src/page-instrument/header-top/image/rhythm.png
  55. 二進制
      src/page-instrument/header-top/image/rhythmAct.png
  56. 二進制
      src/page-instrument/header-top/image/section0.png
  57. 二進制
      src/page-instrument/header-top/image/section1.png
  58. 二進制
      src/page-instrument/header-top/image/section2.png
  59. 二進制
      src/page-instrument/header-top/image/shenggui.png
  60. 二進制
      src/page-instrument/header-top/image/shengguiAct.png
  61. 二進制
      src/page-instrument/header-top/image/sing.png
  62. 二進制
      src/page-instrument/header-top/image/sing1.png
  63. 二進制
      src/page-instrument/header-top/image/singAct.png
  64. 二進制
      src/page-instrument/header-top/image/sj.png
  65. 二進制
      src/page-instrument/header-top/image/submit.png
  66. 二進制
      src/page-instrument/header-top/image/submitWorkAgain.png
  67. 二進制
      src/page-instrument/header-top/image/submitWorkConfirm.png
  68. 二進制
      src/page-instrument/header-top/image/submitWorkNoDoneBg.png
  69. 二進制
      src/page-instrument/header-top/image/tickoff.png
  70. 二進制
      src/page-instrument/header-top/image/tickoffAct.png
  71. 二進制
      src/page-instrument/header-top/image/tickon.png
  72. 二進制
      src/page-instrument/header-top/image/tickonAct.png
  73. 二進制
      src/page-instrument/header-top/image/workCameraBg.png
  74. 二進制
      src/page-instrument/header-top/image/workCameraCancel.png
  75. 二進制
      src/page-instrument/header-top/image/workCameraConfirm.png
  76. 二進制
      src/page-instrument/header-top/image/workDoneBtn.png
  77. 二進制
      src/page-instrument/header-top/image/workDonePop.png
  78. 二進制
      src/page-instrument/header-top/image/workNoBack.png
  79. 二進制
      src/page-instrument/header-top/image/workNoContinue.png
  80. 二進制
      src/page-instrument/header-top/image/workNoDoneBg.png
  81. 二進制
      src/page-instrument/header-top/image/zt.png
  82. 40 17
      src/page-instrument/header-top/index.module.less
  83. 126 77
      src/page-instrument/header-top/index.tsx
  84. 16 5
      src/page-instrument/header-top/settting/index.module.less
  85. 3 3
      src/page-instrument/header-top/settting/index.tsx
  86. 27 0
      src/page-instrument/header-top/workHomePop/index.module.less
  87. 16 9
      src/page-instrument/header-top/workHomePop/index.tsx
  88. 1 1
      src/page-instrument/simple-detail/index.tsx
  89. 二進制
      src/page-instrument/view-detail/images/bg2_left_zs.png
  90. 二進制
      src/page-instrument/view-detail/images/bg2_right_zs.png
  91. 0 0
      src/page-instrument/view-detail/images/index.json
  92. 1 24
      src/page-instrument/view-detail/index.module.less
  93. 72 20
      src/page-instrument/view-detail/index.tsx
  94. 1 1
      src/page-instrument/view-detail/intonationLine/index.tsx
  95. 0 0
      src/page-instrument/view-detail/smoothAnimation/bird/imgs/fly.json
  96. 0 0
      src/page-instrument/view-detail/smoothAnimation/bird/imgs/note.json
  97. 0 0
      src/page-instrument/view-detail/smoothAnimation/bird/imgs/stilln.json
  98. 2 2
      src/page-instrument/view-detail/smoothAnimation/index.ts
  99. 二進制
      src/page-instrument/view-evaluat-report/component/share-top/image/audioBg.png
  100. 0 0
      src/page-instrument/view-evaluat-report/component/share-top/image/audioBga.json

+ 5 - 0
src/helpers/communication.ts

@@ -111,6 +111,11 @@ export const api_videoUpdate = (callback: CallBack) => {
 	);
 };
 
+/** 保存作业 */
+export const api_workUpdate = (): Promise<IPostMessage | undefined> => {
+	return promisefiyPostMessage({ api: "videoUpdate" });
+};
+
 /** 分享 */
 export const api_shareAchievements = (content: any): Promise<IPostMessage | undefined> => {
 	if (!storeData.isApp) return Promise.resolve({} as any);

+ 2 - 4
src/helpers/customMusicScore.ts

@@ -613,16 +613,14 @@ export const resetFormate = () => {
 					}
 				} catch (error) {}
 				const bbox = stave?.getBBox() || {};
-				const bgColor = state.isEvaluatReport ? '#132D4C' : state.isCbsView ? 'transparent' : '#609FCF';
-				const botColor = state.isEvaluatReport ? '#040D1E' : state.isCbsView ? 'transparent' : '#2B70A5';
+				const bgColor = 'transparent';
 				const rect = `<rect class="vf-custom-bg" x="${bbox.x}" y="${bbox.y}" width="${bbox.width}" height="${bbox.height}" fill=${bgColor} />`
-				const rectBottom = `<rect class="vf-custom-bot" x="${bbox.x}" y="${bbox.y+bbox.height}" width="${bbox.width}" height="7.5" fill=${botColor} />`
 				// const filterDom = `<defs>
 				// 						<filter id="shadow">
 				// 						<feDropShadow dx="5" dy="5" stdDeviation="3" flood-color="black" />
 				// 						</filter>
 				// 					</defs>`
-				const customG = `<g>${rect}${rectBottom}</g>`
+				const customG = `<g>${rect}</g>`
 				try {
 					if (list.length) {
 						for(const _el of list) {

+ 1 - 1
src/helpers/metronome.ts

@@ -192,7 +192,7 @@ class Metronome {
 			if(state.playType === "sing" && state.playSource === "background" && audioDataState.songCollection.beatBanSongEle){
 				return
 			}			
-			if(state.playType === "sing" && state.playSource === "mingSong" && audioDataState.songCollection.beatMingSongEle){
+			if(state.playSource === "mingSong" && audioDataState.songCollection.beatMingSongEle){
 				return
 			}			
 		}

+ 4 - 0
src/page-instrument/api.ts

@@ -18,6 +18,10 @@ export const api_musicPracticeRecordSave = (data: any) => {
 export const api_lessonTrainingSubmitTraining = (data: any) => {
   return request.post("/lessonTraining/submitTraining", { requestType: "json", data });
 };
+/** 保存练习时长 */
+export const api_submitTrainingTime = (data: any) => {
+  return request.post("/lessonTraining/submitTrainingTime", { requestType: "json", data });
+};
 /** 获取作业详情 */
 export const api_lessonTrainingTrainingStudentDetail = (id: any) => {
   return request.get(`/lessonTraining/trainingContentStudentDetail?id=${id}`);

+ 2 - 2
src/page-instrument/component/authorName/index.module.less

@@ -18,7 +18,7 @@
             padding: 0;
             font-weight: 600;
             font-size: 22px;
-            color: #FFFFFF;
+            color: #333333;
             .van-notice-bar__wrap{
                 justify-content: center;
             }
@@ -37,7 +37,7 @@
                 padding: 0;
                 font-weight: 400;
                 font-size: 13px;
-                color: #FFFFFF;
+                color: #333333;
                 line-height: 20px;
                 .van-notice-bar__wrap{
                     justify-content: flex-end;

二進制
src/page-instrument/custom-plugins/guide-driver/images/evaluating/r3-2.png


二進制
src/page-instrument/custom-plugins/guide-driver/images/practise/d777.png


+ 24 - 0
src/page-instrument/custom-plugins/guide-driver/index.less

@@ -124,6 +124,18 @@
   }
 }
 
+.popoverClass777 {
+  width: 265px;
+  height: 245px;
+  background: url("./images/practise/d777.png") no-repeat center;
+  background-size: contain;
+
+  .driver-popover-next-btn {
+    right: 25px;
+    bottom: 23px;
+  }
+}
+
 .popoverClass5 {
   width: 264px;
   height: 245px;
@@ -482,6 +494,18 @@
   }
 }
 
+.popoverClassER3-2 {
+  width: 261px;
+  height: 249px;
+  background: url("./images/evaluating/r3-2.png") no-repeat center;
+  background-size: contain;
+
+  .driver-popover-next-btn {
+    bottom: 15px;
+    left: 17px;
+  }
+}
+
 .popoverClassER4 {
   width: 327px;
   height: 246px;

+ 41 - 4
src/page-instrument/custom-plugins/guide-driver/index.tsx

@@ -3,6 +3,7 @@ import { Config, DriveStep, PopoverDOM, State, driver } from "driver.js";
 import "driver.js/dist/driver.css";
 import state, { IPlatform } from "/src/state";
 import { getGuidance, setGuidance } from "../guide-page/api";
+import { getQuery } from "/src/utils/queryString";
 
 const endGuide = (guideInfo: any) => {
   try {
@@ -58,7 +59,7 @@ export const PractiseDriver = defineComponent({
     };
 
     const driverOptions = (): Config => {
-      let length = 10;
+      let length = 11;
 
       if (!props.statusAll.playBtnStatus) {
         length -= 1;
@@ -169,6 +170,21 @@ export const PractiseDriver = defineComponent({
       }
       options.steps?.push(
         {
+          element: ".driver-777",
+          popover: {
+            title: "",
+            description: "",
+            popoverClass: "popoverClass popoverClass777",
+            align: "start",
+            side: "top",
+            nextBtnText: `下一步 (${options.steps.length + 1}/${length})`,
+            showButtons: ["next"],
+            onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
+              driverInitialPosition(popover, options);
+            },
+          },
+        },
+        {
           element: ".driver-4",
           popover: {
             title: "",
@@ -176,7 +192,7 @@ export const PractiseDriver = defineComponent({
             popoverClass: "popoverClass popoverClass4",
             align: "start",
             side: "top",
-            nextBtnText: `下一步 (${options.steps.length + 1}/${length})`,
+            nextBtnText: `下一步 (${options.steps.length + 2}/${length})`,
             showButtons: ["next"],
             onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
               driverInitialPosition(popover, options);
@@ -191,7 +207,7 @@ export const PractiseDriver = defineComponent({
             popoverClass: "popoverClass popoverClass5",
             align: "start",
             side: "top",
-            nextBtnText: `下一步 (${options.steps.length + 2}/${length})`,
+            nextBtnText: `下一步 (${options.steps.length + 3}/${length})`,
             showButtons: ["next"],
             onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
               driverInitialPosition(popover, options);
@@ -1007,6 +1023,7 @@ export const EvaluatingResultDriver = defineComponent({
     },
   },
   setup(props) {
+    const query = getQuery();
     let length = 4;
     if (!props.saveBtn) {
       length -= 1;
@@ -1078,7 +1095,8 @@ export const EvaluatingResultDriver = defineComponent({
         ],
       };
 
-      if (props.saveBtn) {
+      // 非作业是保存作品
+      if (props.saveBtn && !query.workRecord) {
         driverOptions.steps?.push({
           element: ".evaluting-result-3",
           popover: {
@@ -1096,6 +1114,25 @@ export const EvaluatingResultDriver = defineComponent({
         });
       }
 
+      // 作业是提交作业
+      if (query.workRecord) {
+        driverOptions.steps?.push({
+          element: ".evaluting-result-3",
+          popover: {
+            title: "",
+            description: "",
+            popoverClass: "popoverClass popoverClassER3-2",
+            align: "end",
+            side: "top",
+            nextBtnText: `下一步 (3/${length})`,
+            showButtons: ["next"],
+            onPopoverRender: (popover: PopoverDOM, options: { config: Config; state: State }) => {
+              driverInitialPosition(popover, options, -1);
+            },
+          },
+        });
+      }
+
       driverOptions.steps?.push({
         element: ".evaluting-result-4",
         popover: {

+ 30 - 0
src/page-instrument/custom-plugins/work-ealuating/index.module.less

@@ -0,0 +1,30 @@
+.microBox {
+    position: fixed;
+    width: 100vw;
+    height: 100vh;
+    left: 0;
+    top: 0;
+    z-index: 999;
+    background: rgba(0,0,0,0.7);
+    .microBg {
+        position: absolute;
+        left: 50%;
+        top: 20%;
+        height: 60%;
+        transform: translateX(-50%);
+    }
+    .microBtn {
+        position: absolute;
+        bottom: 23.5%;
+        left: 50%;
+        transform: translate(-50%);
+    }
+    .microCancel {
+        width: 11.2vw;
+        margin-right: 2px;
+    }
+    .microConfirm {
+        width: 11.2vw;
+        margin-left: 2px;
+    }
+}

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

@@ -5,6 +5,9 @@ import { api_lessonTrainingSubmitTraining } from "../../api";
 import state, { IDifficulty, handleSetSpeed, hanldeDirectSelection, setSection } from "/src/state";
 import { getQuery } from "/src/utils/queryString";
 import { evaluatingData } from "/src/view/evaluating";
+import styles from "./index.module.less";
+import { headImg } from "/src/page-instrument/header-top/image";
+import { api_openCamera } from "/src/helpers/communication";
 
 export default defineComponent({
 	name: "EvaluatingWork",
@@ -23,6 +26,7 @@ export default defineComponent({
 			end: "" as any,
 			evaluateSpeed: 0,
 			score: 0, // 评测作业及格分数
+			openCameraTipDone: false, // 打开摄像头弹窗是否出现过
 		});
 		/** 隐藏评测功能 */
 		const handleHide = () => {
@@ -69,12 +73,24 @@ export default defineComponent({
 				console.log(error);
 			}
 		};
+
+		const openCamera = async () => {
+			evaluatingData.showOpenCameraPop = false
+			const res = await api_openCamera();
+			// 没有授权
+			if (res?.content?.reson) {
+				state.setting.camera = false
+			} else {
+				state.setting.camera = true
+			}
+		}
 		watch(
 			() => evaluatingData.resultData.recordId,
 			() => {
 				// 评测作业,完整评测才调用保存作业接口
 				if (evaluatingData.resulstMode && evaluatingData.resultData.recordId && evaluatingData.isComplete) {
-					addEvaluatingWorkRecored(evaluatingData.resultData);
+					// 评测的提交作业接口改为用户手动点击“提交作业”按钮来提交
+					// addEvaluatingWorkRecored(evaluatingData.resultData);
 					// 完整评测,判断当前的评测分数是否已达标,没有达标,点击返回按钮需要给出弹窗提示
 					if (!state.isWorkDone) {
 						state.isWorkDone = Number(evaluatingData.resultData?.score) >= evaluatingWorkData.score;
@@ -82,14 +98,41 @@ export default defineComponent({
 				}
 			}
 		);
+		watch(
+			() => state.isLoading,
+			(val) => {
+				if (!val && !evaluatingWorkData.openCameraTipDone) {
+					evaluatingWorkData.openCameraTipDone = true
+					// 如果没有打开摄像头,提醒用户打开摄像头
+					if (!state.setting.camera) {
+						evaluatingData.showOpenCameraPop = true
+					}
+				}
+			}
+		);
 		onMounted(() => {
 			handleHide();
 			getWorkData();
 			// verifyMembershipServices();
 		});
 		expose({
-			getWorkData
+			getWorkData,
+			addEvaluatingWorkRecored
 		})		
-		return () => <div></div>;
+		return () => (
+			<>
+				<div></div>
+				{
+					evaluatingData.showOpenCameraPop && 
+					<div class={styles.microBox}>
+						<img class={styles.microBg} src={headImg("workCameraBg.png")} />
+						<div class={styles.microBtn}>
+							<img class={styles.microCancel} src={headImg("workCameraCancel.png")} onClick={() => evaluatingData.showOpenCameraPop = false } />
+							<img class={styles.microConfirm} src={headImg("workCameraConfirm.png")} onClick={() => openCamera() } />
+						</div>
+					</div>						
+				}
+			</>
+		);
 	},
 });

+ 65 - 6
src/page-instrument/custom-plugins/work-home/index.module.less

@@ -1,13 +1,72 @@
 .homework{
     position: fixed;
-    left: 14px;
+    left: 46px;
     top: 64px;
-    background-color: rgba(0, 0, 0, .6);
-    border-radius: 20px;
+    background-color: #C5E6F7;
+    border-radius: 12px;
     font-size: 14px;
-    color: #fff;
-    padding: 5px 8px;
+    color: #080808;
+    width: 106px;
+    text-align: center;
+    padding: 5px 0;
     line-height: 1;
-    font-weight: 300;
     z-index: 100;
+    span {
+        margin-left: 8px;
+    }
+    .blinkDot {
+        position: absolute;
+        left: 8px;
+        top: 50%;
+        transform: translateY(-50%);
+        width: 3px;
+        height: 3px;
+        border-radius: 50%;
+        background: #FF5A56;
+        animation: blink 1s infinite; /* 定义动画,周期 2 秒,永远重复 */
+    }
+    .grayDot {
+        position: absolute;
+        left: 8px;
+        top: 50%;
+        width: 3px;
+        height: 3px;
+        border-radius: 50%;
+        background: #aaaaaa;
+        transform: translateY(-50%);
+    }
+}
+
+@keyframes blink {
+    0% {
+      opacity: 1; /* 完全可见 */
+    }
+    50% {
+      opacity: 0; /* 完全透明 */
+    }
+    100% {
+      opacity: 1; /* 完全可见 */
+    }
+}
+
+.workDonePop {
+    position: fixed;
+    left: 0;
+    top: 0;
+    width: 100%;
+    height: 100%;
+    background: rgba(0, 0, 0, 0.7);
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    z-index: 999;
+    .doneBg {
+        width: 520px;
+    }
+    .doneBtn {
+        width: 113px;
+        margin-top: -50px;
+        cursor: pointer;
+    }
 }

+ 96 - 14
src/page-instrument/custom-plugins/work-home/index.tsx

@@ -1,8 +1,10 @@
 import { defineComponent, onMounted, reactive, watch } from "vue";
 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 { api_lessonTrainingSubmitTraining, api_lessonTrainingTrainingStudentDetail, api_submitTrainingTime } from "../../api";
+import state, { handleSetSpeed, hanldeDirectSelection, setSection, togglePlay } from "/src/state";
+import { getSecondRPM } from "/src/utils";
+import { headImg } from "/src/page-instrument/header-top/image";
 
 export default defineComponent({
 	name: "HomeWork",
@@ -15,14 +17,18 @@ export default defineComponent({
 	emits: ["change"],
 	setup(props, {expose}) {
 		const training = reactive({
-			trainingTimes: "",
-			trainingSpeed: 0,
-			times: 0,
+			trainingTimes: "", // 已经练习的时长,单位分钟
+			trainingSpeed: 0, // 作业规定的速度
+			times: 0, // 作业规定的练习时长,单位分钟
+			trainingTimeSecond: 0, // 实时更新的练习时长,单位秒
 			workRecord: "",
 			isAddOk: 0,
 			starTime: 0,
 			start: "" as any,
 			end: "" as any,
+			timer: null as any, // 定时器
+			realThisTimeTotal: 0, // 达标的本次练习时长
+			trainingStatus: "UNSUBMITTED" as any, // 作业状态
 		});
 
 		/** 隐藏评测功能 */
@@ -37,7 +43,7 @@ export default defineComponent({
 			}
 		};
 		/** 获取作业详情 */
-		const getWorkData = async () => {
+		const getWorkData = async (resourceType?: string) => {
 			const workeData = props.workeData;
 			if (workeData.id) {
 				let trainingContent: any = {};
@@ -46,8 +52,12 @@ export default defineComponent({
 				} catch (error) {
 					console.log("🚀 ~ error:", error);
 				}
+				training.trainingStatus = workeData.trainingStatus || "UNSUBMITTED";
 				training.times = trainingContent.trainingTimes || 0;
 				training.trainingTimes = (workeData.trainingTimes / 60).toFixed(1) || "0";
+				if (!resourceType) {
+					training.trainingTimeSecond = workeData.trainingTimes || 0;
+				}
 				training.trainingSpeed = trainingContent.practiceSpeed;
 				training.start = Number(trainingContent.practiceChapterBegin);
 				training.end = Number(trainingContent.practiceChapterEnd);
@@ -57,6 +67,10 @@ export default defineComponent({
 					// 设置小节
 					setSection(training.start, training.end, training.trainingSpeed);
 				}
+				// 来自刷新谱面
+				if (resourceType === 'refresh') {
+					getWorkDetail()
+				}
 			}
 		};
 
@@ -64,31 +78,86 @@ export default defineComponent({
 			const res = await api_lessonTrainingTrainingStudentDetail(props.workeData.id);
 			if (res?.code === 200) {
 				training.trainingTimes = (res.data.trainingTimes / 60).toFixed(1) || "0";
-				state.isWorkDone = Number(training.trainingTimes) >= Number(training.times);
+				training.trainingTimeSecond = res.data.trainingTimes || 0;
+				training.trainingStatus = res.data.trainingStatus;
+				state.isWorkDone = Number(training.trainingTimes) >= Number(training.times) && res.data.trainingStatus === 'TARGET';
 			}
 		};
 
 		/** 添加作业记录 */
-		const addHomeworkRecored = async () => {
-			let total = Math.ceil((Date.now() - training.starTime) / 1000);
+		const addHomeworkRecored = async (extraType?: string) => {
+			let total = extraType === 'save' ? training.realThisTimeTotal : Math.floor((Date.now() - training.starTime) / 1000);
 			try {
-				const res = await api_lessonTrainingSubmitTraining({
+				let params: any = {
 					id: props.workeData.id,
 					trainingTimes: total,
-				});
+				}
+				// 如果已达标,手动保存作业时,需要添加submitFlag参数
+				if (extraType === 'save') {
+					params = {
+						id: props.workeData.id,
+						submitFlag: true
+					}
+				}
+				const res = extraType === 'save' ? await api_lessonTrainingSubmitTraining(params) : await api_submitTrainingTime(params);
 				if (res?.code == 200) {
 					getWorkDetail();
+					training.starTime = Date.now();
 				}
 			} catch (error) {}
 		};
 
+		const handleStart = () => {
+			training.timer = setInterval(() => {
+				training.trainingTimeSecond += 1;
+				// console.log('练习时长',training.trainingTimeSecond)
+			}, 1000);
+		};
+        const handleStop = () => {
+            clearInterval(training.timer)
+        }
+
 		watch(
 			() => state.playState,
 			() => {
 				if (state.playState === "play") {
 					training.starTime = Date.now();
+					handleStart();
 				} else {
+					// 没有达标停止播放时,需要自动提交练习时长
+					// if (!state.showWorkDonePop) {
+					// 	addHomeworkRecored();
+					// }
 					addHomeworkRecored();
+					handleStop();
+				}
+			}
+		);
+		watch(
+			() => state.showWorkDonePop,
+			() => {
+				if (state.showWorkDonePop && state.playState === "play") {
+					togglePlay("paused")
+				}
+			}
+		);
+		watch(
+			() => training.trainingTimeSecond,
+			() => {
+				// console.log('累积时间',111,state.isWorkDone,training.trainingTimeSecond,training.times * 60)
+				// 如果播放中,作业从未达标到达标状态,需要暂停播放,并且弹窗提示作业已达标
+				if (training.trainingStatus !== 'TARGET' && (!state.isWorkDone && training.trainingTimeSecond >= training.times * 60 || (state.isWorkDone && training.trainingTimeSecond === training.times * 60)) ) {
+					// training.realThisTimeTotal = state.isWorkDone && training.trainingTimeSecond === training.times * 60 ? 0 : Math.ceil((Date.now() - training.starTime) / 1000);
+					training.realThisTimeTotal = Math.floor((Date.now() - training.starTime) / 1000);
+					state.isWorkDone = true
+					togglePlay("paused")
+					if (training.starTime === 0) {
+						setTimeout(() => {
+							state.showWorkDonePop = true
+						}, 1500);
+					} else {
+						state.showWorkDonePop = true
+					}
 				}
 			}
 		);
@@ -108,9 +177,22 @@ export default defineComponent({
 			getWorkData
 		})
 		return () => (
-			<div class={styles.homework}>
-				{training.trainingTimes} / {training.times} 分钟
-			</div>
+			<>
+				<div class={styles.homework}>
+					<i class={state.playState === "play" ? styles.blinkDot : styles.grayDot}></i>
+					<span>{getSecondRPM(training.trainingTimeSecond)} / {getSecondRPM(training.times*60)}</span>
+				</div>
+				{
+					state.showWorkDonePop && 
+					<div class={styles.workDonePop}>
+						<img class={styles.doneBg} src={headImg("workDonePop.png")} />
+						<img class={styles.doneBtn} src={headImg("workDoneBtn.png")} onClick={() => {
+							state.showWorkDonePop = false
+                			addHomeworkRecored('save');
+              			}} />
+					</div>
+				}
+			</>
 		);
 	},
 });

+ 6 - 1
src/page-instrument/custom-plugins/work-index/index.tsx

@@ -26,7 +26,7 @@ export const HANDLE_WORK_ADD = () => {
 export const resetSection = () => {
 	console.log('重新设置选段1111')
 	if (data.trainingType === "PRACTICE"){
-		workHomeRef.value?.getWorkData();
+		workHomeRef.value?.getWorkData('refresh');
 	}
 	if (data.trainingType === "EVALUATION") {
 		workEvaluatRef.value?.getWorkData();
@@ -34,6 +34,11 @@ export const resetSection = () => {
 	state.workSectionNeedReset = false;
 };
 
+// 手动提交评测作业
+export const selfSubmitWorkHome = () => {
+	workEvaluatRef.value?.addEvaluatingWorkRecored(evaluatingData.resultData);
+}
+
 export default defineComponent({
 	name: "workIndex",
 	setup(props) {

二進制
src/page-instrument/evaluat-model/countdown/imgs/step1.png


二進制
src/page-instrument/evaluat-model/countdown/imgs/step2.png


二進制
src/page-instrument/evaluat-model/countdown/imgs/step3.png


二進制
src/page-instrument/evaluat-model/evaluat-result/img/tjzy.png


+ 6 - 1
src/page-instrument/evaluat-model/evaluat-result/index.tsx

@@ -16,6 +16,7 @@ import iconBadge from "./img/icon-badge.png";
 import yzImg from "./img/yz.png";
 import jzImg from "./img/jz.png";
 import wzxImg from "./img/wzx.png";
+import tjzyImg from "./img/tjzy.png";
 import closeImg from "./img/close.png";
 import { getQuery } from "/src/utils/queryString";
 import { browser, getBehaviorId } from "/src/utils";
@@ -167,7 +168,11 @@ export default defineComponent({
               <div class={styles.tips}>{evaluatingData.resultData.clxtip}</div>
               <div class={styles.ctrls}>
                 <img src={zlycImg} class={[styles.ctrlsBtn, "evaluting-result-2"]} onClick={() => emit("close", "tryagain")} />
-                {evaluatingData.resultData.recordId ? (
+                {
+                  query.workRecord && 
+                  <img src={tjzyImg} class={[styles.ctrlsBtn, "evaluting-result-3", data.saveLoading ? styles.disablued : ""]} onClick={() => emit("close", "submitWork")} />
+                }
+                {evaluatingData.resultData.recordId && !query.workRecord ? (
                   <div class={styles.saveBtn}>
                     <img
                       src={noSaveTips.value ? bczpJzImg : bczpImg}

二進制
src/page-instrument/evaluat-model/icons/confirm.png


二進制
src/page-instrument/evaluat-model/icons/lanya_erji.png


二進制
src/page-instrument/evaluat-model/icons/no_erji.png


二進制
src/page-instrument/evaluat-model/icons/tip_btn.png


二進制
src/page-instrument/evaluat-model/icons/tip_erji.png


二進制
src/page-instrument/evaluat-model/icons/youxian_erji.png


+ 61 - 6
src/page-instrument/evaluat-model/index.tsx

@@ -10,7 +10,7 @@ import { getNoteByMeasuresSlursStart } from "/src/helpers/formateMusic";
 import { Icon, Popup, showToast, closeToast, showLoadingToast } from "vant";
 import EvaluatResult from "./evaluat-result";
 import EvaluatAudio from "./evaluat-audio";
-import { api_getDeviceDelay, api_openAdjustRecording, api_proxyServiceMessage, api_videoUpdate, getEarphone, api_back, api_startDelayCheck, api_cancelDelayCheck, api_remove_cancelDelayCheck, api_closeDelayCheck, api_finishDelayCheck, api_retryEvaluating, api_remove_finishDelayCheck } from "/src/helpers/communication";
+import { api_getDeviceDelay, api_openAdjustRecording, api_proxyServiceMessage, api_videoUpdate, getEarphone, api_back, api_startDelayCheck, api_cancelDelayCheck, api_remove_cancelDelayCheck, api_closeDelayCheck, api_finishDelayCheck, api_retryEvaluating, api_remove_finishDelayCheck, api_workUpdate } from "/src/helpers/communication";
 import EvaluatShare from "./evaluat-share";
 import { Vue3Lottie } from "vue3-lottie";
 import startData from "./data/start.json";
@@ -25,6 +25,8 @@ import Countdown from "./countdown";
 import { IPostMessage } from "/src/utils/native-message";
 import tipErjiBg from "./icons/tip_erji.png"
 import tipErjiBtn from "./icons/tip_btn.png"
+import SubmitNoDonePop from "./submit-nodone";
+import { selfSubmitWorkHome } from "../custom-plugins/work-index";
 
 // const DelayCheck = defineAsyncComponent(() =>
 //   import('./delay-check')
@@ -59,6 +61,7 @@ export default defineComponent({
       evaluatUpdateAudio: false,
       isSaveVideo: state.setting.camera && state.setting.saveToAlbum,
       shareMode: false,
+      showNoDonePop: false, // 提交作业显示未达标确认弹窗
     });
     /**
      * 检测返回
@@ -196,7 +199,7 @@ export default defineComponent({
         // 妙极客的曲子,选择的第一小节,beatLength需要传递fixtime
         if (state.isEvxml && startIndex == 0) {
           actualBeatLength = Math.round((state.times[0].fixtime * 1000) / 1);
-        }        
+        }          
         selectTimes = state.times.filter((n: any, index: number) => {
           return index >= startIndex && index <= endIndex;
         });
@@ -329,7 +332,7 @@ export default defineComponent({
     };
 
     /** 评测结果按钮处理 */
-    const handleEvaluatResult = (type: "practise" | "tryagain" | "look" | "share" | "update" | "selfCancel") => {
+    const handleEvaluatResult = (type: "practise" | "tryagain" | "look" | "share" | "update" | "selfCancel" | "submitWork") => {
       if (type === "update") {
         if (state.isAppPlay) {
           evaluatModel.evaluatUpdateAudio = true;
@@ -362,7 +365,10 @@ export default defineComponent({
         // 去练习
         handleStartEvaluat();
       } else if (type === "tryagain") {
-        startBtnHandle();
+        /**
+         * TODO: 2025.01.20 再来一次改为只是关闭结果弹窗,需要用户手动点击评测按钮触发评测,不自动进行评测,故注释掉下方自动评测的方法
+         */
+        // startBtnHandle();
       } else if (type === "selfCancel") {
         // 再来一次,需要手动取消评测,不生成评测记录,不显示评测结果弹窗
         evaluatingData.oneselfCancleEvaluating = true;
@@ -371,11 +377,56 @@ export default defineComponent({
         // evaluatingData.isBeginMask = true;
         evaluatingData.evaluatings = {};
         state.playState = "paused";
+      } else if (type === "submitWork") {
+        // 作业模式,提交作业,作业没有达标时,提交作业需要弹窗提醒
+        if (!state.isWorkDone) {
+          evaluatModel.showNoDonePop = true;
+          return;
+        } else {
+          submitWorkHome();
+        }
       }
       resetPlaybackToStart();
       evaluatingData.resulstMode = false;
     };
 
+    // 关闭提交作业确认弹窗
+    const handleCloseSubmitPop = (type: "again" | "confirm") => {
+      evaluatModel.showNoDonePop = false;
+      if (type === "again") {
+        handleEvaluatResult("tryagain");
+      } else {
+        submitWorkHome();
+        resetPlaybackToStart();
+        evaluatingData.resulstMode = false;
+      }
+    }
+    // 提交作业
+    const submitWorkHome = async () => {
+      // 分为开了摄像头和没开摄像头的情况
+      if (state.setting.camera) {
+        const res = await api_workUpdate();
+        console.log('提交作业回调',res)
+        if (res) {
+          if (res?.content?.type === "success") {
+            handleSaveResult({
+              id: evaluatingData.resultData?.recordId,
+              videoFilePath: res?.content?.filePath,
+            });
+            // 手动提交评测作业
+            selfSubmitWorkHome();
+          } else if (res?.content?.type === "error") {
+            showToast({
+              message: res.content?.message || "上传失败",
+            });
+          }
+        }
+      } else {
+        // 手动提交评测作业
+        selfSubmitWorkHome();
+      }
+    }
+
     /** 上传音视频 */
     const hanldeUpdateVideoAndAudio = async (update = false) => {
       if (!update) {
@@ -489,11 +540,11 @@ export default defineComponent({
     };
 
     const earPhonePopShow = computed(() => {
-			return evaluatingData.earphoneMode && !state.isLoading && !state.hasDriverPop;
+			return evaluatingData.earphoneMode && !state.isLoading && !state.hasDriverPop && !evaluatingData.showOpenCameraPop;
 		});
 
     const tipErjiPopShow = computed(() => {
-			return evaluatingData.tipErjiShow && !state.isLoading && !state.hasDriverPop;
+			return evaluatingData.tipErjiShow && !state.isLoading && !state.hasDriverPop && !evaluatingData.showOpenCameraPop;
 		});
 
     // watch(
@@ -640,6 +691,10 @@ export default defineComponent({
         <Popup teleport="body" class={["popup-custom", "van-scale"]} transition="van-scale" v-model:show={evaluatModel.shareMode}>
           <EvaluatShare onClose={() => (evaluatModel.shareMode = false)} />
         </Popup>
+        
+        <Popup teleport="body" class={["popup-custom", "van-scale"]} transition="van-scale" v-model:show={evaluatModel.showNoDonePop}>
+          <SubmitNoDonePop onClose={handleCloseSubmitPop} />
+        </Popup>
       </div>
     );
   },

+ 26 - 0
src/page-instrument/evaluat-model/submit-nodone/index.module.less

@@ -0,0 +1,26 @@
+.microBox {
+    position: relative;
+    width: 100vw;
+    height: 100vh;
+    .microBg {
+        position: absolute;
+        left: 50%;
+        top: 50%;
+        width: 520px;
+        transform: translate(-50%,-50%);
+    }
+    .microBtn {
+        position: absolute;
+        bottom: 20%;
+        left: 50%;
+        transform: translate(-50%);
+    }
+    .microCancel {
+        width: 90px;
+        margin-right: 2px;
+    }
+    .microConfirm {
+        width: 90px;
+        margin-left: 2px;
+    }
+}

+ 25 - 0
src/page-instrument/evaluat-model/submit-nodone/index.tsx

@@ -0,0 +1,25 @@
+import { defineComponent } from "vue";
+import styles from "./index.module.less";
+import { headImg } from "/src/page-instrument/header-top/image";
+
+export default defineComponent({
+	name: "submitNoDonePop",
+	props: {
+		tip: {
+			type: String,
+			default: () => ''
+		}
+	},
+	emits: ["close"],
+	setup(props, { emit }) {
+		return () => (
+			<div class={styles.microBox}>
+				<img class={styles.microBg} src={headImg("submitWorkNoDoneBg.png")} />
+				<div class={styles.microBtn}>
+					<img class={styles.microCancel} src={headImg("submitWorkAgain.png")} onClick={() => emit("close", "again")} />
+					<img class={styles.microConfirm} src={headImg("submitWorkConfirm.png")} onClick={() => emit("close", "confirm")} />
+				</div>
+			</div>
+		);
+	},
+});

二進制
src/page-instrument/follow-model/microphone/images/microBg.png


二進制
src/page-instrument/follow-model/microphone/images/micro_cancel.png


二進制
src/page-instrument/follow-model/microphone/images/micro_confirm.png


二進制
src/page-instrument/header-top/image/background.png


二進制
src/page-instrument/header-top/image/background1.png


二進制
src/page-instrument/header-top/image/background1Act.png


二進制
src/page-instrument/header-top/image/backgroundAct.png


二進制
src/page-instrument/header-top/image/bg.png


二進制
src/page-instrument/header-top/image/icon_menu.png


二進制
src/page-instrument/header-top/image/icon_menuAct.png


二進制
src/page-instrument/header-top/image/icon_pause.png


二進制
src/page-instrument/header-top/image/icon_play.png


二進制
src/page-instrument/header-top/image/icon_reset.png


二進制
src/page-instrument/header-top/image/mingsong.png


二進制
src/page-instrument/header-top/image/mingsongAct.png


二進制
src/page-instrument/header-top/image/mode.png


二進制
src/page-instrument/header-top/image/music.png


二進制
src/page-instrument/header-top/image/music1.png


二進制
src/page-instrument/header-top/image/music1Act.png


二進制
src/page-instrument/header-top/image/musicAct.png


二進制
src/page-instrument/header-top/image/perform.png


二進制
src/page-instrument/header-top/image/perform1.png


二進制
src/page-instrument/header-top/image/performAct.png


二進制
src/page-instrument/header-top/image/radio.png


二進制
src/page-instrument/header-top/image/radioActive.png


二進制
src/page-instrument/header-top/image/rhythm.png


二進制
src/page-instrument/header-top/image/rhythmAct.png


二進制
src/page-instrument/header-top/image/section0.png


二進制
src/page-instrument/header-top/image/section1.png


二進制
src/page-instrument/header-top/image/section2.png


二進制
src/page-instrument/header-top/image/shenggui.png


二進制
src/page-instrument/header-top/image/shengguiAct.png


二進制
src/page-instrument/header-top/image/sing.png


二進制
src/page-instrument/header-top/image/sing1.png


二進制
src/page-instrument/header-top/image/singAct.png


二進制
src/page-instrument/header-top/image/sj.png


二進制
src/page-instrument/header-top/image/submit.png


二進制
src/page-instrument/header-top/image/submitWorkAgain.png


二進制
src/page-instrument/header-top/image/submitWorkConfirm.png


二進制
src/page-instrument/header-top/image/submitWorkNoDoneBg.png


二進制
src/page-instrument/header-top/image/tickoff.png


二進制
src/page-instrument/header-top/image/tickoffAct.png


二進制
src/page-instrument/header-top/image/tickon.png


二進制
src/page-instrument/header-top/image/tickonAct.png


二進制
src/page-instrument/header-top/image/workCameraBg.png


二進制
src/page-instrument/header-top/image/workCameraCancel.png


二進制
src/page-instrument/header-top/image/workCameraConfirm.png


二進制
src/page-instrument/header-top/image/workDoneBtn.png


二進制
src/page-instrument/header-top/image/workDonePop.png


二進制
src/page-instrument/header-top/image/workNoBack.png


二進制
src/page-instrument/header-top/image/workNoContinue.png


二進制
src/page-instrument/header-top/image/workNoDoneBg.png


二進制
src/page-instrument/header-top/image/zt.png


+ 40 - 17
src/page-instrument/header-top/index.module.less

@@ -6,8 +6,13 @@
     flex-shrink: 0;
     margin-left: calc(-1 * var(--detailDataPaddingLeft));
     padding: 0 30px;
-    background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.6) 100%);
-
+    background: linear-gradient( 180deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0.7) 19%, rgba(255,255,255,0.7) 100%);
+    &.follow{
+        background: linear-gradient( 180deg, rgba(255,255,255,0) 0%, rgba(240,250,252,0.7) 19%, rgba(255,255,255,0.7) 100%);
+    }
+    &.evaluating{
+        background: linear-gradient( 180deg, rgba(255,255,255,0) 0%, rgba(221,248,254,0.7) 19%, rgba(225,242,251,0.7) 100%);
+    }
     &.headerTopRight {
         justify-content: flex-end;
     }
@@ -26,7 +31,7 @@
     left: 30px;
     bottom: 20px;
     border-radius: 16px;
-    background-color: rgba(12, 51, 107, 0.61);
+    background-color: rgba(0, 0, 0, 0.3);
     padding: 6px 11px;
     align-items: center;
     display: flex;
@@ -38,7 +43,7 @@
         font-weight: 500;
         font-size: 14px;
         line-height: 20px;
-        color: rgba(255, 255, 255, 0.7);
+        color: #ffffff;
     }
 
     &>img {
@@ -94,7 +99,7 @@
                 padding: 0;
                 font-weight: 600;
                 font-size: 18px;
-                color: #FFFFFF;
+                color: #333333;
             }
         }
     }
@@ -117,9 +122,11 @@
     position: fixed;
     top: 20px;
     right: 30px;
-    height: 32px;
-    background: rgba(0, 0, 0, .4);
+    height: 36px;
+    border-radius: 16px;
+    background: #FFFFFF;
     border-radius: 16px;
+    border: 3px solid #B5ECF1;
     display: flex;
     align-items: center;
     padding: 0 10px;
@@ -133,7 +140,7 @@
         margin-left: 6px;
         font-weight: 500;
         font-size: 14px;
-        color: #FFFFFF;
+        color: #1E6B98;
     }
 }
 
@@ -164,13 +171,13 @@
             margin-top: 3px;
             font-weight: 500;
             font-size: 12px;
-            color: #FFFFFF;
+            color: #333333;
             line-height: 17px;
         }
 
         &:active {
             >span {
-                color: #34D6FF
+                color: #0EA7FF
             }
 
             ;
@@ -218,7 +225,7 @@
 
         &.isSection {
             >span {
-                color: #34D6FF
+                color: #0EA7FF
             }
 
             ;
@@ -244,7 +251,7 @@
             }
 
             >span {
-                color: #34D6FF
+                color: #0EA7FF
             }
 
             ;
@@ -262,7 +269,7 @@
             }
 
             >span {
-                color: #34D6FF
+                color: #0EA7FF
             }
 
             ;
@@ -280,7 +287,23 @@
             }
 
             >span {
-                color: #34D6FF
+                color: #0EA7FF
+            }
+
+            ;
+        }      
+        &.rhythmMode:active {
+            >img {
+                content: url("./image/rhythmAct.png");
+            }
+        }  
+        &.isrhythmMode {
+            >img {
+                content: url("./image/rhythmAct.png");
+            }
+
+            >span {
+                color: #0EA7FF
             }
 
             ;
@@ -313,7 +336,7 @@
                 margin-left: 1px;
                 font-weight: 600;
                 font-size: 12px;
-                color: #673207;
+                color: #333333;
                 line-height: 16px;
             }
         }
@@ -360,8 +383,8 @@
         left: 50%;
         top: 50%;
         transform: translate(-50%, -50%);
-        width: 43px;
-        height: 43px;
+        width: 36px;
+        height: 38px;
     }
 }
 

+ 126 - 77
src/page-instrument/header-top/index.tsx

@@ -48,6 +48,10 @@ export const headTopData = reactive({
   showBack: true,
   /** 设置弹窗 */
   settingMode: false,
+  /* 节奏律动 */
+  rhythmMode: false,
+  // 节奏律动方向
+  rhythmModeDirection: computed(()=> state.fingeringInfo.direction === "transverse" ? "vertical" : "transverse"),
   /** 切换模式 */
   handleChangeModeType(value: "practise" | "follow" | "evaluating") {
     // 后台设置为不能评测
@@ -59,6 +63,15 @@ export const headTopData = reactive({
       metronomeData.cursorMode = 1;
     }
     if (value === "practise") {
+      // 切回当前的时值
+      const isModeChange = modeChangeHandleTimes("play", "music")
+      // 没有切换的时候 不处理下面的
+      if (isModeChange) {
+        try {
+          metronomeData.metro.calculation(state.times);
+        } catch (error) {}
+        console.log("重新之后的times", state.times, state.fixtime);
+      }
       // state.playIngSpeed = state.speed
     }
     if (value === "evaluating") {
@@ -83,6 +96,19 @@ export const headTopData = reactive({
       //   state.isSingleLine = true;
       //   refreshMusicSvg();
       // }
+      /* 当前是唱名的模式 */
+      if(state.playSource === "mingSong") {
+        const isModeChange = modeChangeHandleTimes("play","mingSong","play","music")
+        // 没有切换的时候 不处理下面的
+        if (isModeChange) {
+          try {
+            metronomeData.metro.calculation(state.times);
+          } catch (error) {}
+          console.log("重新之后的times", state.times, state.fixtime);
+        }
+      }
+      // 关闭节奏律动
+      headTopData.rhythmMode = false
       smoothAnimationState.isShow.value = false; // 隐藏旋律线
       state.playIngSpeed = state.originSpeed;
       handleStartEvaluat();
@@ -91,6 +117,8 @@ export const headTopData = reactive({
       // evaluatingData.rendered = true;
       // evaluatingData.soundEffectMode = true;
     } else if (value === "follow") {
+      // 关闭节奏律动
+      headTopData.rhythmMode = false
       // 跟练模式,只有一行谱模式
       if (!state.isSingleLine) {
         state.isSingleLine = true;
@@ -154,45 +182,34 @@ export async function handlerModeChange(oldPlayType: "play" | "sing", oldPlaySou
   }
 }
 // 模式切换之后重新给times赋值
-function modeChangeHandleTimes(oldPlayType: "play" | "sing", oldPlaySource: IPlayState) {
-  const playType = state.playType;
-  const playSource = state.playSource;
+function modeChangeHandleTimes(oldPlayType: "play" | "sing", oldPlaySource: IPlayState, nowPlayType?:"play" | "sing", nowPlaySource?: IPlayState) {
+  const playType = nowPlayType || state.playType;
+  const playSource = nowPlaySource || state.playSource;
   const { notBeatFixtime, xmlMp3BeatFixTime, difftime } = state.times[0];
   const { isOpenMetronome, isSingOpenMetronome } = state;
-  // 演奏向演唱切
-  if (oldPlayType === "play" && playType === "sing") {
-    if (playSource === "mingSong") {
-      // 唱名文件也要加上弱起时间  他们制作曲子加了弱起时间  注意这修改了之后给总控平台的时值也需要改
-      state.fixtime = difftime;
-      state.times.map((item) => {
-        item.time = item.xmlNoteTime + difftime;
-        item.endtime = item.xmlNoteEndTime + difftime;
-        item.fixtime = difftime;
-      });
-      return true;
-    } else {
-      //演奏开了节拍器,演唱没开节拍器
-      if (isOpenMetronome && !isSingOpenMetronome) {
-        state.fixtime = notBeatFixtime;
-        state.times.map((item) => {
-          item.time = item.notBeatTime;
-          item.endtime = item.notBeatEndTime;
-          item.fixtime = notBeatFixtime;
-        });
-        return true;
-      } else if (!isOpenMetronome && isSingOpenMetronome) {
-        state.fixtime = notBeatFixtime + xmlMp3BeatFixTime;
-        state.times.map((item) => {
-          item.time = item.notBeatTime + xmlMp3BeatFixTime;
-          item.endtime = item.notBeatEndTime + xmlMp3BeatFixTime;
-          item.fixtime = notBeatFixtime + xmlMp3BeatFixTime;
-        });
-        return true;
-      }
-    }
-  } else if (oldPlayType === "sing" && playType === "play") {
-    // 演唱向演奏切
-    if (oldPlaySource === "mingSong") {
+  // 跟练模式不切换时值  因为演奏加了唱名,所以往跟练模式切换的时候,刷新谱面的时候需要更新时值,这时候调用handleRessetState 会回到练习模式
+  if(state.modeType === "follow") {
+    return false
+  }
+  // 当相同时候也不处理
+  if(oldPlayType === playType && oldPlaySource === playSource) {
+    return false
+  }
+  // 原声向伴奏和伴奏向原声不处理  范唱向伴唱和伴唱向范唱切不处理
+  if((oldPlaySource==="music"&&playSource==="background")||(oldPlaySource==="background"&&playSource==="music")){
+    return false
+  }
+  // 唱名到唱名时候不处理
+  if(oldPlaySource === "mingSong" && playSource === "mingSong"){
+    return false
+  }
+  // 原生伴奏向范唱伴唱,范唱伴唱向原生伴奏时候,isSingOpenMetronome和isOpenMetronome相等时候不处理
+  if(["music","background"].includes(oldPlaySource)&&["music","background"].includes(playSource)&&isOpenMetronome===isSingOpenMetronome){
+    return false
+  }
+  // 当切为 原生伴奏,或者范唱伴唱 时候
+  if(playSource==="music" || playSource ==="background"){
+    if(playType === "play"){
       // 有节拍器
       if (isOpenMetronome) {
         state.fixtime = notBeatFixtime + xmlMp3BeatFixTime;
@@ -212,37 +229,7 @@ function modeChangeHandleTimes(oldPlayType: "play" | "sing", oldPlaySource: IPla
         return true;
       }
     }
-    // 演奏开了节拍器,演唱没开节拍器
-    if (isOpenMetronome && !isSingOpenMetronome) {
-      state.fixtime = notBeatFixtime + xmlMp3BeatFixTime;
-      state.times.map((item) => {
-        item.time = item.notBeatTime + xmlMp3BeatFixTime;
-        item.endtime = item.notBeatEndTime + xmlMp3BeatFixTime;
-        item.fixtime = notBeatFixtime + xmlMp3BeatFixTime;
-      });
-      return true;
-    } else if (!isOpenMetronome && isSingOpenMetronome) {
-      state.fixtime = notBeatFixtime;
-      state.times.map((item) => {
-        item.time = item.notBeatTime;
-        item.endtime = item.notBeatEndTime;
-        item.fixtime = notBeatFixtime;
-      });
-      return true;
-    }
-  } else if (oldPlayType === "sing" && playType === "sing") {
-    // 演唱之间切换
-    // 切到唱名时候
-    if (playSource === "mingSong") {
-      // 唱名文件也要加上弱起时间  他们制作曲子加了弱起时间  注意这修改了之后给总控平台的时值也需要改
-      state.fixtime = difftime;
-      state.times.map((item) => {
-        item.time = item.xmlNoteTime + difftime;
-        item.endtime = item.xmlNoteEndTime + difftime;
-        item.fixtime = difftime;
-      });
-      return true;
-    } else if (oldPlaySource === "mingSong") {
+    if(playType==="sing"){
       // 有节拍器
       if (isSingOpenMetronome) {
         state.fixtime = notBeatFixtime + xmlMp3BeatFixTime;
@@ -263,6 +250,17 @@ function modeChangeHandleTimes(oldPlayType: "play" | "sing", oldPlaySource: IPla
       }
     }
   }
+  // 当切为唱名时候
+  if(playSource==="mingSong"){
+      // 唱名文件也要加上弱起时间  他们制作曲子加了弱起时间  注意这修改了之后给总控平台的时值也需要改
+      state.fixtime = difftime;
+      state.times.map((item) => {
+        item.time = item.xmlNoteTime + difftime;
+        item.endtime = item.xmlNoteEndTime + difftime;
+        item.fixtime = difftime;
+      });
+      return true;
+  }
   return false;
 }
 
@@ -385,8 +383,13 @@ export default defineComponent({
           return { display: true, disabled: true };
         }
         if (state.playType === "play") {
-          // 原声, 伴奏 少一个,就不能切换
-          if (state.music && state.accompany) return { display: true, disabled: false };
+          let index = 0;
+          state.music && index++;
+          state.accompany && index++;
+          state.mingSong && index++;
+          if (index > 1) {
+            return { display: true, disabled: false };
+          }
         } else {
           // 范唱
           let index = 0;
@@ -468,6 +471,33 @@ export default defineComponent({
       };
     });
 
+    /** 节奏律动 */
+    const rhythmBtn = computed(() => {
+      // 跟练和评测显示
+      if (["evaluating", "follow"].includes(state.modeType)) return { display: false, disabled: false, playIng: false };
+      // 播放过程中不让切换
+      if (state.playState == "play") {
+        if(headTopData.rhythmMode) {
+          return { 
+            display: true, 
+            disabled: true,
+            playIng: true 
+          }
+        }else{
+          return { 
+            display: true, 
+            disabled: true,
+            playIng: false
+          }
+        }
+      };
+      return {
+        display: true,
+        disabled: false,
+        playIng: false
+      };
+    });
+
     /** 重播按钮 */
     resetBtn = computed(() => {
       // 没有音源不显示
@@ -709,7 +739,7 @@ export default defineComponent({
     return () => (
       <>
         <div
-          class={[styles.headerTop, state.platform === IPlatform.PC && state.musicScoreBtnDirection === "left" ? styles.headerTopRight : ""]}
+          class={[styles.headerTop, styles[state.modeType] ,state.platform === IPlatform.PC && state.musicScoreBtnDirection === "left" ? styles.headerTopRight : ""]}
           onClick={(e: Event) => {
             e.stopPropagation();
             if (state.platform === IPlatform.PC) {
@@ -778,7 +808,7 @@ export default defineComponent({
           }
 
           {/* 模式提醒 */}
-          {state.modeType === "practise" && (
+          {state.modeType === "practise" && !rhythmBtn.value.playIng && (
             <div class={[styles.modeWarn, "practiseModeWarn", state.platform === IPlatform.PC && state.musicScoreBtnDirection === "left" ? styles.modeWarnRight : ""]}>
               <img src={state.playType === "play" ? headImg("perform1.png") : headImg("sing1.png")} />
               <div>{state.playType === "play" ? "演奏场景" : "演唱场景"}</div>
@@ -830,7 +860,7 @@ export default defineComponent({
                   state.playSource = state.fanSong ? "music" : state.banSong ? "background" : "mingSong";
                 } else {
                   state.playType = "play";
-                  state.playSource = state.music ? "music" : "background";
+                  state.playSource =  state.music ? "music" : state.accompany ? "background" : "mingSong";
                 }
                 isClickMode = true;
                 // 有指法并且显示指法的时候 切换到演唱模式 需要影藏指法
@@ -868,7 +898,13 @@ export default defineComponent({
                 const oldPlayType = state.playType;
                 const oldPlaySource = state.playSource;
                 if (state.playType === "play") {
-                  state.playSource = state.playSource === "music" ? "background" : "music";
+                  if (state.playSource === "music") {
+                    state.playSource = state.accompany ? "background" : "mingSong";
+                  } else if (state.playSource === "background") {
+                    state.playSource = state.mingSong ? "mingSong" : "music";
+                  } else {
+                    state.playSource = state.music ? "music" : "background";
+                  }
                 } else {
                   if (state.playSource === "music") {
                     state.playSource = state.banSong ? "background" : "mingSong";
@@ -880,7 +916,7 @@ export default defineComponent({
                 }
                 await handlerModeChange(oldPlayType, oldPlaySource);
                 showToast({
-                  message: state.playType === "play" ? (state.playSource === "music" ? "已切换为原声" : "已切换为伴奏") : state.playSource === "music" ? "已切换为范唱" : state.playSource === "background" ? "已切换为伴唱" : "已切换为唱名",
+                  message: state.playType === "play" ? (state.playSource === "music" ? "已切换为原声" : state.playSource === "background" ? "已切换为伴奏" : "已切换为唱名") : state.playSource === "music" ? "已切换为范唱" : state.playSource === "background" ? "已切换为伴唱" : "已切换为唱名",
                   position: "top",
                   className: "selectionToast",
                 });
@@ -892,6 +928,16 @@ export default defineComponent({
               <span>{state.playSource === "music" ? (state.playType === "play" ? "原声" : "范唱") : state.playSource === "background" ? (state.playType === "play" ? "伴奏" : "伴唱") : "唱名"}</span>
             </div>
             <div
+                style={{ display: rhythmBtn.value.display ? "" : "none" }}
+                class={["driver-777", styles.btn, styles.rhythmMode, headTopData.rhythmMode && styles.isrhythmMode, rhythmBtn.value.disabled && styles.disabled]}
+                onClick={() => {
+                  headTopData.rhythmMode = !headTopData.rhythmMode
+                }}
+              >
+                <img class={styles.iconBtn} src={headImg(`rhythm.png`)} />
+                <span>律动</span>
+            </div>
+            <div
               id={state.platform === IPlatform.PC ? "teacherTop-2" : "studnetT-2"}
               style={{ display: selectBtn.value.display ? "" : "none" }}
               class={["driver-4", styles.btn, selectBtn.value.disabled && styles.disabled, styles.section, state.sectionStatus && styles.isSection]}
@@ -982,7 +1028,10 @@ export default defineComponent({
         {/* 播放按钮 */}
         <div
           id="studnetT-7"
-          style={{ display: playBtn.value.display ? "" : "none" }}
+          style={{ 
+            display: playBtn.value.display ? "" : "none" ,
+            opacity: rhythmBtn.value.playIng? "0.4" : "1"
+          }}
           class={[
             // 引导使用的类
             "driver-1",
@@ -1009,7 +1058,7 @@ export default defineComponent({
           <div class={styles.btnWrap}>
             <img style={{ display: state.playState === "play" ? "none" : "" }} class={styles.iconBtn} src={headImg("icon_play.png")} />
             <img style={{ display: state.playState === "play" ? "" : "none" }} class={styles.iconBtn} src={headImg("icon_pause.png")} />
-            <Circle style={{ opacity: state.playState === "play" ? 1 : 0 }} class={styles.progress} stroke-width={60} stroke-linecap={"square"} currentRate={state.playProgress} rate={100} color="#FFED78" layer-color="rgba(0,0,0,0)" />
+            <Circle style={{ opacity: state.playState === "play" ? 1 : 0 }} class={styles.progress} stroke-width={60} stroke-linecap={"square"} currentRate={state.playProgress} rate={100} color="#FFE36A" layer-color="rgba(255,255,255,0.5)" />
           </div>
         </div>
 

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

@@ -198,7 +198,7 @@
                 .radioBox{
                     display: flex;
                     > div{
-                        width: 66px;
+                        width: 60px;
                         height: 28px;
                         font-weight: 600;
                         font-size: 14px;
@@ -207,7 +207,7 @@
                         line-height: 26px;
                         background: url("../image/radio.png") no-repeat;
                         background-size: 100% 100%;
-                        margin-right: 10px;
+                        margin-right: 8px;
                         cursor: pointer;
                         &:last-child{
                             margin-right: 0;
@@ -219,9 +219,20 @@
                         }
                     }
                 }
-                .speBox {
-                    >div {
-                        width: 48px;
+                &.speCon{
+                    .tit{
+                        flex-shrink: 0;
+                    }
+                    .radioBox {
+                        flex-wrap: wrap;
+                        justify-content: flex-end;
+                        >div {
+                            margin: 0 0 8px 8px;
+                            width: 48px;
+                            &:nth-child(n+4){
+                                margin-bottom: 0;
+                            }
+                        }
                     }
                 }
                 .frequency{

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

@@ -26,7 +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 zoomList = [{name:'0.5x',value: 0.5},{name:'0.75x',value: 0.65},{name:'1x',value: 0.8},{name:'1.25x',value: 1.25},{name:'1.5x',value: 1.5},{name:'1.75x',value: 1.75},{name:'2x',value: 2},{name:'2.25x',value: 2.25}] 
 		const parentClassName = "recommenBoxClass_drag";
 		const userId = storeData.user?.id ? String(storeData.user?.id) : "";
 		const positionInfo =
@@ -258,9 +258,9 @@ export default defineComponent({
                         }
                         {
                             !state.isCbsView ? 
-                            <div class={styles.cellBox}>
+                            <div class={[styles.cellBox, styles.speCon]}>
                                 <div class={styles.tit}>谱面大小</div>
-                                <div class={[styles.radioBox, styles.speBox]}>
+                                <div class={styles.radioBox}>
                                     {
                                         zoomList.map(item=>{
                                             return <div class={ state.zoom===item.value && styles.active } onClick={ async ()=>{ 

+ 27 - 0
src/page-instrument/header-top/workHomePop/index.module.less

@@ -51,3 +51,30 @@
         }
     }
 }
+
+.microBox {
+    position: relative;
+    width: 100vw;
+    height: 100vh;
+    .microBg {
+        position: absolute;
+        left: 50%;
+        top: 20%;
+        height: 60%;
+        transform: translateX(-50%);
+    }
+    .microBtn {
+        position: absolute;
+        bottom: 23.5%;
+        left: 50%;
+        transform: translate(-50%);
+    }
+    .microCancel {
+        width: 11.2vw;
+        margin-right: 2px;
+    }
+    .microConfirm {
+        width: 11.2vw;
+        margin-left: 2px;
+    }
+}

+ 16 - 9
src/page-instrument/header-top/workHomePop/index.tsx

@@ -14,15 +14,22 @@ export default defineComponent({
 	emits: ["close"],
 	setup(props, { emit }) {
 		return () => (
-			<div class={styles.popBox}>
-				<img class={styles.boxBg} src={headImg("workHome_bg.png")} />
-				<img class={styles.boxTitle} src={headImg("workHome_icon1.png")} />
-				<div class={styles.boxContent}>
-					<p>本条练习还没达到老师的练习要求,是否继续练习?</p>
-					<div class={styles.boxBtn}>
-						<img class={styles.boxClose} src={headImg("workHome_icon3.png")} onClick={() => emit("close")} />
-						<img class={styles.boxConfirm} src={headImg("workHome_icon2.png")} onClick={() => emit("close", true)} />
-					</div>
+			// <div class={styles.popBox}>
+			// 	<img class={styles.boxBg} src={headImg("workHome_bg.png")} />
+			// 	<img class={styles.boxTitle} src={headImg("workHome_icon1.png")} />
+			// 	<div class={styles.boxContent}>
+			// 		<p>本条练习还没达到老师的练习要求,是否继续练习?</p>
+			// 		<div class={styles.boxBtn}>
+			// 			<img class={styles.boxClose} src={headImg("workHome_icon3.png")} onClick={() => emit("close")} />
+			// 			<img class={styles.boxConfirm} src={headImg("workHome_icon2.png")} onClick={() => emit("close", true)} />
+			// 		</div>
+			// 	</div>
+			// </div>
+			<div class={styles.microBox}>
+				<img class={styles.microBg} src={headImg("workNoDoneBg.png")} />
+				<div class={styles.microBtn}>
+					<img class={styles.microCancel} src={headImg("workNoBack.png")} onClick={() => emit("close")} />
+					<img class={styles.microConfirm} src={headImg("workNoContinue.png")} onClick={() => emit("close", true)} />
 				</div>
 			</div>
 		);

+ 1 - 1
src/page-instrument/simple-detail/index.tsx

@@ -201,7 +201,7 @@ export default defineComponent({
 					{!detailData.isLoading && 
 					<MusicScore 
 						onRendered={handleRendered} 
-						musicColor={'#FFFFFF'}
+						musicColor={'#000000'}
 					/>}
 				</div>
 			</div>

二進制
src/page-instrument/view-detail/images/bg2_left_zs.png


二進制
src/page-instrument/view-detail/images/bg2_right_zs.png


File diff suppressed because it is too large
+ 0 - 0
src/page-instrument/view-detail/images/index.json


+ 1 - 24
src/page-instrument/view-detail/index.module.less

@@ -51,15 +51,7 @@
         width: 100%;
         height: 100%;
         object-fit: cover; /* 保持宽高比 */
-        &.practise{
-            background-color: #213793;
-        }        
-        &.follow{
-            background-color: #114067;
-        }        
-        &.evaluating{
-            background-color: #142979;
-        }
+        background-color: #fff;
     }
 
     .headHeight {
@@ -90,7 +82,6 @@
         position: sticky;
         top: 0;
         height: 100vh;
-        border-radius: 10px;
         transition: height .2s;
         transition: padding-bottom .2s;
         overflow: hidden;
@@ -395,18 +386,4 @@
         font-size: 14px;
         color: #fff;
     }
-}
-
-.bg2Left {
-    width: 52px;
-    position: absolute;
-    left: 0px;
-    top: 0;
-}
-
-.bg2Right {
-    width: 52px;
-    position: absolute;
-    right: 0;
-    top: 0;
 }

+ 72 - 20
src/page-instrument/view-detail/index.tsx

@@ -9,7 +9,7 @@ import MusicScore from "../../view/music-score";
 import TestCheck from "/src/view/music-score/testCheck";
 import { sysMusicScoreAccompanimentQueryPage } from "../api";
 import EvaluatModel from "../evaluat-model";
-import HeaderTop, { handlerModeChange } from "../header-top";
+import HeaderTop, { handlerModeChange, headTopData } from "../header-top";
 import styles from "./index.module.less";
 import { api_cloudAccompanyMessage, api_cloudLoading, api_keepScreenLongLight, api_openCamera, api_openWebView, api_setEventTracking, api_setRequestedOrientation, api_setStatusBarVisibility, isSpecialShapedScreen } from "/src/helpers/communication";
 import { getQuery } from "/src/utils/queryString";
@@ -17,6 +17,7 @@ import Evaluating, { evaluatingData } from "/src/view/evaluating";
 import MeasureSpeed from "/src/view/plugins/measure-speed";
 import { mappingVoicePart, subjectFingering } from "/src/view/fingering/fingering-config";
 import Fingering from "/src/view/fingering";
+import Rhythm from "/src/view/rhythm";
 import store from "store";
 import Tick, { handleInitTick } from "/src/view/tick";
 import FollowPractice, { followData } from "/src/view/follow-practice";
@@ -40,8 +41,6 @@ import { position } from "html2canvas/dist/types/css/property-descriptors/positi
 import Loading from "./loading"
 import LoadingCss from "./loadingCss"
 // import bgJson from "./images/index.json";
-import bg2Left from "./images/bg2_left_zs.png";
-import bg2Right from "./images/bg2_right_zs.png";
 
 // const DelayCheck = defineAsyncComponent(() =>
 //   import('/src/page-instrument/evaluat-model/delay-check')
@@ -128,14 +127,15 @@ export default defineComponent({
         Object.assign(state.setting, settting);
         //state.setting.beatVolume = state.setting.beatVolume || 50
         state.setting.beatVolume = 50;
-        if (state.setting.camera) {
-          const res = await api_openCamera();
-          // 没有授权
-          if (res?.content?.reson) {
-            state.setting.camera = false;
-            store.set("musicscoresetting", state.setting);
-          }
-        }
+        // 默认进来不需要开启摄像头,进入评测页面才需要判断是否开启摄像头
+        // if (state.setting.camera) {
+        //   const res = await api_openCamera();
+        //   // 没有授权
+        //   if (res?.content?.reson) {
+        //     state.setting.camera = false;
+        //     store.set("musicscoresetting", state.setting);
+        //   }
+        // }
       }
     });
 
@@ -400,6 +400,57 @@ export default defineComponent({
       };
     });
 
+    /** 节奏律动配置  */
+    const rhythmConfig = computed<any>(()=>{
+      if(headTopData.rhythmMode){
+        if(headTopData.rhythmModeDirection === "vertical"){
+          if(state.platform === IPlatform.PC && state.playBtnDirection === "left") {
+            return {
+              container: {
+                paddingLeft: "4.6rem"
+              },
+              rhythmBox: {
+                width: "4.6rem",
+                position: "absolute",
+                height: "100%",
+                left: 0,
+                top: 0
+              },
+            };
+          }else{
+            return {
+              container: {
+                paddingRight: "4.6rem"
+              },
+              rhythmBox: {
+                width: "4.6rem",
+                position: "absolute",
+                height: "100%",
+                right: 0,
+                top: 0
+              },
+            };
+          }
+        }else{
+          return {
+            container: {
+              paddingBottom: "2.5rem"
+            },
+            rhythmBox: {
+              height: "2.5rem",
+              position: "absolute",
+              width: "100%",
+              left: 0,
+              bottom: 0,
+            },
+          };
+        }
+      }
+      return {
+        container: {},
+        rhythmBox: {},
+      }; 
+    })
     // 监听指法显示
     watch(
       () => state.setting.displayFingering,
@@ -530,15 +581,9 @@ export default defineComponent({
             src={state.modeType === 'practise' ? bgJsonData.value[1] : state.modeType === 'evaluating' ? bgJsonData.value[2] : state.modeType === 'follow' ? bgJsonData.value[3] : ''} 
           /> : <div 
                 style={{opacity: state.setting.camera && state.modeType === 'evaluating' ? state.setting.cameraOpacity / 100 : 1}}  
-                class={[styles.pageBg, styles[state.modeType]]} >
+                class={[styles.pageBg]} >
               </div>    
         }
-        {
-          state.modeType === 'evaluating' ? (<>
-            <img src={bg2Left} class={styles.bg2Left} />
-            <img src={bg2Right} class={styles.bg2Right} />
-          </>
-        ) : null}
         {/* 骨架屏 */}
         {/* <Transition name="van-fade">
           {detailData.skeletonLoading && (
@@ -553,7 +598,7 @@ export default defineComponent({
         {!state.isPreView && <div class={["headHeight", styles.headHeight, headerColumnHide.value && styles.headHide]}>{state.musicRendered && <HeaderTop />}</div>}
         <div
           id="scrollContainer"
-          style={{ ...fingerConfig.value.container }}
+          style={{ ...fingerConfig.value.container, ...rhythmConfig.value.container }}
           class={[styles.container, !state.setting.displayCursor && "hideCursor", browsInfo.xiaomi && styles.xiaomi, state.platform === IPlatform.PC && styles.pcContainer]}
           onClick={(e: Event) => {
             e.stopPropagation();
@@ -570,7 +615,7 @@ export default defineComponent({
           {!detailData.isLoading && 
             <MusicScore 
               ref={musicScoreRef}
-              musicColor={state.isPreView || state.isCbsView ? '#000000' : '#FFFFFF'}
+              musicColor={'#000000'}
               showPartNames={state.isCombineRender}
               onRendered={handleOnRendered} 
             > 
@@ -598,6 +643,13 @@ export default defineComponent({
               />
             </div>
           )}
+          {/* 节奏律动 */}
+          {
+            headTopData.rhythmMode &&  
+            <div style={{ ...rhythmConfig.value.rhythmBox}}>
+              <Rhythm></Rhythm>
+            </div>
+          }
         </div>
         {/* 曲目渲染完成,再去下载mp3资源 */}
         {!detailData.isLoading && !detailData.skeletonLoading && <AudioList />}

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

@@ -194,7 +194,7 @@ function drawProgressectMusic() {
    const filterProgressMusic = progressMusicData.progressMusic.filter(item => {
       return item.width !== 0
    })
-   drawPathRectByArr(canvasCtx!, filterProgressMusic, "#FFC121")
+   drawPathRectByArr(canvasCtx!, filterProgressMusic, "#0EA7FF")
 }
 
 /**

File diff suppressed because it is too large
+ 0 - 0
src/page-instrument/view-detail/smoothAnimation/bird/imgs/fly.json


File diff suppressed because it is too large
+ 0 - 0
src/page-instrument/view-detail/smoothAnimation/bird/imgs/note.json


File diff suppressed because it is too large
+ 0 - 0
src/page-instrument/view-detail/smoothAnimation/bird/imgs/stilln.json


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

@@ -354,7 +354,7 @@ export function moveTranslateXNum(translateXNum: number) {
  */
 function smoothAnimationMove(pos: { x: number; y: number }, progresspointsPos: pointsPosType) {
    smoothAnimationState.smoothBotDom && (smoothAnimationState.smoothBotDom.style.transform = `translate(${pos.x}px, ${pos.y}px)`)
-   smoothAnimationState.canvasCtx && drawSmoothCurveProgress(smoothAnimationState.canvasCtx, progresspointsPos, "#FFC121")
+   smoothAnimationState.canvasCtx && drawSmoothCurveProgress(smoothAnimationState.canvasCtx, progresspointsPos, "#FF8B8F")
 }
 
 /**
@@ -508,7 +508,7 @@ function initCanvasSmooth() {
    smoothDomCtx.lineCap = "round"
    smoothDomCtx.lineJoin = "round"
    // 根据坐标花线
-   const defaultColor = state.isCbsView ? "rgba(0,0,0,0.1)" : "rgba(255,255,255,0.6)";
+   const defaultColor = state.isCbsView ? "rgba(0,0,0,0.1)" : "#BDBDBD";
    drawLines(smoothDomCtx, smoothAnimationState.pointsPos, defaultColor)
    smoothAnimationState.canvasSmoothDom = smoothDom
 }

二進制
src/page-instrument/view-evaluat-report/component/share-top/image/audioBg.png


File diff suppressed because it is too large
+ 0 - 0
src/page-instrument/view-evaluat-report/component/share-top/image/audioBga.json


Some files were not shown because too many files changed in this diff