瀏覽代碼

延迟检测

liushengqiang 2 年之前
父節點
當前提交
9544c967dd
共有 23 個文件被更改,包括 470 次插入83 次删除
  1. 二進制
      src/page-instrument/evaluat-model/delay-check/image/icon_1.png
  2. 二進制
      src/page-instrument/evaluat-model/delay-check/image/icon_1_1.png
  3. 二進制
      src/page-instrument/evaluat-model/delay-check/image/icon_2_1.png
  4. 二進制
      src/page-instrument/evaluat-model/delay-check/image/icon_2_2.png
  5. 二進制
      src/page-instrument/evaluat-model/delay-check/image/icon_2_3.png
  6. 二進制
      src/page-instrument/evaluat-model/delay-check/image/icon_2_4.png
  7. 二進制
      src/page-instrument/evaluat-model/delay-check/image/icon_3_0.png
  8. 二進制
      src/page-instrument/evaluat-model/delay-check/image/icon_3_1.png
  9. 二進制
      src/page-instrument/evaluat-model/delay-check/image/icon_3_2.png
  10. 二進制
      src/page-instrument/evaluat-model/delay-check/image/icon_4_0.png
  11. 二進制
      src/page-instrument/evaluat-model/delay-check/image/icon_4_1.png
  12. 二進制
      src/page-instrument/evaluat-model/delay-check/image/icon_4_2.png
  13. 二進制
      src/page-instrument/evaluat-model/delay-check/image/icon_rect.png
  14. 二進制
      src/page-instrument/evaluat-model/delay-check/image/icon_rect_1.png
  15. 二進制
      src/page-instrument/evaluat-model/delay-check/image/r1.png
  16. 205 8
      src/page-instrument/evaluat-model/delay-check/index.module.less
  17. 229 62
      src/page-instrument/evaluat-model/delay-check/index.tsx
  18. 0 0
      src/page-instrument/evaluat-model/delay-check/json/bg.json
  19. 0 0
      src/page-instrument/evaluat-model/delay-check/json/bg1.json
  20. 0 0
      src/page-instrument/evaluat-model/delay-check/json/f2.json
  21. 0 0
      src/page-instrument/evaluat-model/delay-check/json/l1.json
  22. 0 0
      src/page-instrument/evaluat-model/delay-check/json/r1.json
  23. 36 13
      src/page-instrument/evaluat-model/index.tsx

二進制
src/page-instrument/evaluat-model/delay-check/image/icon_1.png


二進制
src/page-instrument/evaluat-model/delay-check/image/icon_1_1.png


二進制
src/page-instrument/evaluat-model/delay-check/image/icon_2_1.png


二進制
src/page-instrument/evaluat-model/delay-check/image/icon_2_2.png


二進制
src/page-instrument/evaluat-model/delay-check/image/icon_2_3.png


二進制
src/page-instrument/evaluat-model/delay-check/image/icon_2_4.png


二進制
src/page-instrument/evaluat-model/delay-check/image/icon_3_0.png


二進制
src/page-instrument/evaluat-model/delay-check/image/icon_3_1.png


二進制
src/page-instrument/evaluat-model/delay-check/image/icon_3_2.png


二進制
src/page-instrument/evaluat-model/delay-check/image/icon_4_0.png


二進制
src/page-instrument/evaluat-model/delay-check/image/icon_4_1.png


二進制
src/page-instrument/evaluat-model/delay-check/image/icon_4_2.png


二進制
src/page-instrument/evaluat-model/delay-check/image/icon_rect.png


二進制
src/page-instrument/evaluat-model/delay-check/image/icon_rect_1.png


二進制
src/page-instrument/evaluat-model/delay-check/image/r1.png


+ 205 - 8
src/page-instrument/evaluat-model/delay-check/index.module.less

@@ -1,8 +1,9 @@
-.popup{
+.popup {
     width: 100%;
     height: 100%;
 }
-.delayBox{
+
+.delayBox {
     position: fixed;
     left: 0;
     right: 0;
@@ -11,7 +12,8 @@
     background: url('./background.png') center center / 100% 100%;
     background-repeat: no-repeat;
 }
-.item{
+
+.item {
     position: absolute;
     left: 0;
     top: 0;
@@ -21,13 +23,208 @@
     justify-content: center;
     align-items: center;
     opacity: 0;
+    & > div{
+        width: 100%;
+        height: 100%;
+    }
 }
-.show{
-    opacity: 1;
+
+.show {
+    opacity: 1 !important;
 }
-.btn{
+
+.btnBox {
     position: absolute;
-    bottom: 20%;
-    right: 20%;
+    left: 50%;
+    bottom: 7%;
+    width: 360px;
+    height: 60px;
+    transform: translateX(-50%);
+    background: url('./image/icon_rect.png');
+    background-repeat: no-repeat;
+    background-size: 100% 100%;
     z-index: 100;
+    transition: opacity .3s linear;
+}
+
+.baseBtn {
+    position: absolute;
+    left: 0;
+    top: 0;
+    width: 100%;
+    height: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    padding-top: 10px;
+
+    &.btnDisabled {
+        opacity: 0;
+        pointer-events: none;
+    }
+
+}
+
+.btn0 {
+    width: 98px;
+}
+
+.btn1 {
+    &>img:first-child {
+        width: 220px;
+        margin-right: 14px;
+    }
+}
+
+.btn2 {
+    &>img:first-child {
+        width: 150px;
+    }
+}
+
+.btn3 {
+    &>img:first-child {
+        width: 262px;
+    }
+}
+
+.btn4 {
+    &>img:first-child {
+        width: 139px;
+    }
+}
+
+.btn5 {
+    padding: 0 17px;
+    padding-top: 12px;
+    justify-content: space-between;
+
+    &>img:first-child {
+        width: 195px;
+    }
+}
+
+.btn6 {
+    padding: 0 17px;
+    padding-top: 12px;
+    justify-content: space-between;
+
+    &>img:first-child {
+        width: 208px;
+    }
+}
+
+.btn7 {
+    padding: 0 17px;
+    padding-top: 12px;
+    justify-content: space-between;
+
+    &>img:first-child {
+        width: 165px;
+    }
+}
+
+.dotbox {
+    position: absolute;
+    left: 50%;
+    top: -10px;
+    width: 230px;
+    height: 24px;
+    transform: translateX(-50%);
+    background: url('./image/icon_rect_1.png');
+    background-repeat: no-repeat;
+    background-size: 100% 100%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+
+}
+
+.dotLine {
+    background-color: #e6e6e6;
+    width: 186px;
+    height: 5px;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+}
+
+.dot {
+    position: relative;
+    width: 12px;
+    height: 12px;
+    border-radius: 50%;
+    background: url('./image/icon_4_0.png');
+    background-repeat: no-repeat;
+    background-size: 100% 100%;
+    background-position: center center;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+
+    &>img {
+        width: 100%;
+        height: 100%;
+    }
+}
+.dotWraning{
+    animation: aniOpacity 1s linear infinite;
+}
+@keyframes aniOpacity {
+    0% {
+        opacity: 1;
+    }
+
+    50% {
+        opacity: 0;
+    }
+
+    100% {
+        opacity: 1;
+    }
+}
+
+.r1 {
+    position: absolute;
+    right: 40px;
+    top: 20%;
+    width: 50px;
+    height: 50px;
+    animation: iconDuihuaScale 2.8s linear infinite;
+}
+
+@keyframes iconDuihuaScale {
+    0% {
+        transform: scale(.8);
+    }
+
+    50% {
+        transform: scale(1.2);
+    }
+
+    100% {
+        transform: scale(.8);
+    }
+}
+
+.l1 {
+    position: absolute;
+    left: -8%;
+    top: -2%;
+    width: 100%;
+    z-index: 10;
+}
+
+@keyframes framesf1 {
+    0% {
+        opacity: 1;
+    }
+
+    50% {
+        opacity: .2;
+    }
+
+    100% {
+        opacity: 1;
+    }
 }

+ 229 - 62
src/page-instrument/evaluat-model/delay-check/index.tsx

@@ -1,10 +1,11 @@
 import { Button, Popup } from "vant";
 import styles from "./index.module.less";
 import { defineComponent, onMounted, onUnmounted, reactive, ref } from "vue";
-import { api_toggleTune, removeResult, sendResult } from "/src/helpers/communication";
+import { api_toggleTune, getEarphone, removeResult, sendResult } from "/src/helpers/communication";
 import { Vue3Lottie } from "vue3-lottie";
 import bg from "./json/bg.json";
 import bg1 from "./json/bg1.json";
+import l1 from "./json/l1.json";
 import f1 from "./json/f1.json";
 import f2 from "./json/f2.json";
 import f3 from "./json/f3.json";
@@ -12,78 +13,120 @@ import f4 from "./json/f4.json";
 import f5 from "./json/f5.json";
 import f6 from "./json/f6.json";
 import f7 from "./json/f7.json";
+import r1 from "./image/r1.png";
+import icon_1 from "./image/icon_1.png";
+import icon_1_1 from "./image/icon_1_1.png";
+import icon_2_1 from "./image/icon_2_1.png";
+import icon_2_2 from "./image/icon_2_2.png";
+import icon_2_3 from "./image/icon_2_3.png";
+import icon_2_4 from "./image/icon_2_4.png";
+import icon_4_0 from "./image/icon_4_0.png";
+import icon_4_1 from "./image/icon_4_1.png";
+import icon_4_2 from "./image/icon_4_2.png";
+import icon_3_0 from "./image/icon_3_0.png";
+import icon_3_1 from "./image/icon_3_1.png";
+import icon_3_2 from "./image/icon_3_2.png";
+import { evaluatingData } from "/src/view/evaluating";
+import { IPostMessage } from "/src/utils/native-message";
 
 export default defineComponent({
 	name: "delay-check",
-	setup() {
+	emits: ["close"],
+	setup(props, { emit }) {
 		const anim = ref();
 		const data = reactive({
 			show: false,
 			/** 检测状态 */
-			checkStatus: "init" as "init" | "ing" | "error",
+			checkStatus: "init" as "init" | "ing" | "finish" | "end",
 			count: 0,
 			step: 1,
+			startTimer: null as any,
+			stopTimer: null as any,
+			volumeTimer: null as any,
+			earPhoneType: "" as "" | "有线耳机" | "蓝牙耳机",
 		});
-		const listenerResult = () => {
-			if (data.checkStatus !== "ing") return;
-			data.count++;
-			if (data.count >= 2) {
-				toggleTune("finishTune");
-				return;
+		/** 获取耳机状态 */
+		const getEarphoneState = async () => {
+			const res = await getEarphone();
+			data.earPhoneType = res?.content?.type || "";
+			return res?.content?.checkIsWired || false;
+		};
+		/** 持续检测耳机状态 */
+		const keepCheckEarphone = async () => {
+			if (data.checkStatus === "end") return;
+			evaluatingData.earphone = await getEarphoneState();
+			if (evaluatingData.earphone) {
+				if (data.step <= 5) {
+					if (data.checkStatus === "ing") {
+						data.count = 0;
+						clearTimeout(data.startTimer);
+						clearTimeout(data.stopTimer);
+						toggleTune("stop");
+					}
+					data.step = 3;
+				}
+			} else {
+				if (data.step === 2 || data.step === 3) {
+					data.step = 4;
+					setTimeout(() => {
+						data.step = 5;
+						data.checkStatus = "ing";
+						data.count = 0;
+						toggleTune("start");
+					}, 2000);
+				}
 			}
 			setTimeout(() => {
-				toggleTune("start");
-			}, 100);
+				keepCheckEarphone();
+			}, 1000);
+		};
+		const listenerResult = (res?: IPostMessage) => {
+			console.log("🚀 ~ res:", res);
+			if (res?.content) {
+				const { header, body } = res.content;
+				if (header?.commond === "recordEnd") {
+					if (data.checkStatus !== "ing") return;
+					data.count++;
+					if (data.count >= 2) {
+						toggleTune("finishTune");
+						return;
+					}
+					data.startTimer = setTimeout(() => {
+						toggleTune("start");
+					}, 100);
+				}
+			}
 		};
 		onMounted(() => {
 			data.show = true;
 			sendResult(listenerResult);
-			console.log(anim.value);
 		});
 		onUnmounted(() => {
 			removeResult(listenerResult);
 		});
 
+		const handleStartTune = async () => {
+			await keepCheckEarphone();
+			// data.step = evaluatingData.earphone ? 4 : 3;
+		};
+		const hanldeEndTune = () => {
+			data.step = 7;
+			data.checkStatus = "end";
+			anim.value?.play();
+		};
+
 		const toggleTune = async (state: "start" | "stop" | "finishTune") => {
 			if (state === "start") {
 				api_toggleTune("start", data.count);
-				setTimeout(() => {
+				data.stopTimer = setTimeout(() => {
 					api_toggleTune("stop");
-				}, 1500);
+				}, 2000);
 			} else if (state === "finishTune") {
+				data.checkStatus = "finish";
+				data.step = 6;
 				api_toggleTune("finishTune");
 			}
 		};
-		const list = [
-			{
-				id: 1,
-				json: f1,
-			},
-			{
-				id: 2,
-				json: f2,
-			},
-			{
-				id: 3,
-				json: f3,
-			},
-			{
-				id: 4,
-				json: f4,
-			},
-			{
-				id: 5,
-				json: f5,
-			},
-			{
-				id: 6,
-				json: f6,
-			},
-			{
-				id: 7,
-				json: f7,
-			},
-		];
 		return () => (
 			<Popup
 				teleport="body"
@@ -99,32 +142,156 @@ export default defineComponent({
 					<div class={[styles.item, data.step === 7 && styles.show]}>
 						<Vue3Lottie animationData={bg1}></Vue3Lottie>
 					</div>
+					<div class={[styles.l1]}>
+						<Vue3Lottie animationData={l1}></Vue3Lottie>
+					</div>
+					<img class={styles.r1} src={r1} />
+
+					<div
+						style={{ left: "10px", top: "-11px", transform: "rotate(-2deg)" }}
+						class={[styles.item, data.step == 1 && styles.show]}
+					>
+						<Vue3Lottie
+							animationData={f1}
+							loop={false}
+							onOnComplete={() => {
+								data.step = 2;
+							}}
+						></Vue3Lottie>
+					</div>
+
+					<div
+						style={{ left: "10px", top: "-11px", transform: "rotate(-2deg)" }}
+						class={[styles.item, data.step === 2 && styles.show]}
+					>
+						<Vue3Lottie animationData={f2}></Vue3Lottie>
+					</div>
+
+					<div class={[styles.item, data.step === 3 && styles.show]}>
+						<Vue3Lottie animationData={f3}></Vue3Lottie>
+					</div>
+
+					<div class={[styles.item, data.step === 4 && styles.show]}>
+						<Vue3Lottie animationData={f4}></Vue3Lottie>
+					</div>
+					<div class={[styles.item, data.step === 5 && styles.show]}>
+						<Vue3Lottie animationData={f5}></Vue3Lottie>
+					</div>
+					<div class={[styles.item, data.step === 6 && styles.show]}>
+						<Vue3Lottie animationData={f6}></Vue3Lottie>
+					</div>
 					<div class={[styles.item, data.step === 7 && styles.show]}>
 						<Vue3Lottie
 							ref={anim}
-							animationData={bg1}
+							animationData={f7}
+							autoPlay={false}
+							loop={false}
 							onOnComplete={() => {
-								console.log(123, anim.value);
+								emit("close");
 							}}
 						></Vue3Lottie>
 					</div>
-					{list.map((item, index) => {
-						return (
-							<div class={[styles.item, data.step === item.id && styles.show]}>
-								<Vue3Lottie animationData={item.json} loop={false}></Vue3Lottie>
+
+					<div style={{ opacity: data.step > 1 ? "" : "0" }} class={styles.btnBox}>
+						<div class={[styles.baseBtn, styles.btn1, data.step <= 2 ? "" : styles.btnDisabled]}>
+							<img src={icon_2_2} />
+							<img class={styles.btn0} src={icon_1} onClick={() => handleStartTune()} />
+						</div>
+						<div class={[styles.baseBtn, styles.btn2, data.step == 3 ? "" : styles.btnDisabled]}>
+							<img src={icon_2_1} />
+						</div>
+						<div class={[styles.baseBtn, styles.btn3, data.step == 4 ? "" : styles.btnDisabled]}>
+							<img src={icon_2_3} />
+						</div>
+						<div class={[styles.baseBtn, styles.btn4, data.step == 5 ? "" : styles.btnDisabled]}>
+							<img src={icon_2_4} />
+						</div>
+
+						<div
+							class={[
+								styles.baseBtn,
+								styles.btn5,
+								data.step >= 6 && !evaluatingData.earphone ? "" : styles.btnDisabled,
+							]}
+						>
+							<img src={icon_3_0} />
+							<img class={styles.btn0} src={icon_1_1} onClick={() => hanldeEndTune()} />
+						</div>
+						<div
+							class={[
+								styles.baseBtn,
+								styles.btn6,
+								data.step >= 6 && evaluatingData.earphone && data.earPhoneType !== "有线耳机"
+									? ""
+									: styles.btnDisabled,
+							]}
+						>
+							<img src={icon_3_1} />
+							<img class={styles.btn0} src={icon_1_1} onClick={() => hanldeEndTune()} />
+						</div>
+						<div
+							class={[
+								styles.baseBtn,
+								styles.btn7,
+								data.step >= 6 && evaluatingData.earphone && data.earPhoneType === "有线耳机"
+									? ""
+									: styles.btnDisabled,
+							]}
+						>
+							<img src={icon_3_2} />
+							<img class={styles.btn0} src={icon_1_1} onClick={() => hanldeEndTune()} />
+						</div>
+						<div class={styles.dotbox}>
+							<div class={styles.dotLine}>
+								<div class={styles.dot}>
+									<img
+										style={{
+											display:
+												data.step >= 3 && evaluatingData.earphone && data.checkStatus !== "finish"
+													? ""
+													: "none",
+										}}
+										class={styles.dotWraning}
+										src={icon_4_1}
+									/>
+									<img
+										style={{
+											display:
+												data.step >= 3 && (!evaluatingData.earphone || data.checkStatus === "finish")
+													? ""
+													: "none",
+										}}
+										src={icon_4_2}
+									/>
+								</div>
+								<div class={styles.dot}>
+									<img style={{ display: data.step >= 4 ? "" : "none" }} src={icon_4_2} />
+								</div>
+								<div class={styles.dot}>
+									<img
+										style={{ display: data.step >= 5 && data.checkStatus === "ing" ? "" : "none" }}
+										class={styles.dotWraning}
+										src={icon_4_1}
+									/>
+									<img
+										style={{ display: data.step >= 5 && data.checkStatus === "finish" ? "" : "none" }}
+										src={icon_4_2}
+									/>
+								</div>
+								<div class={styles.dot}>
+									<img
+										style={{ display: data.step >= 6 && !evaluatingData.earphone ? "" : "none" }}
+										class={styles.dotWraning}
+										src={icon_4_1}
+									/>
+									<img
+										style={{ display: data.step >= 6 && evaluatingData.earphone ? "" : "none" }}
+										src={icon_4_2}
+									/>
+								</div>
 							</div>
-						);
-					})}
-					<Button
-						class={styles.btn}
-						disabled={data.checkStatus !== "init"}
-						onClick={() => {
-							data.checkStatus = "ing";
-							toggleTune("start");
-						}}
-					>
-						开始检测
-					</Button>
+						</div>
+					</div>
 				</div>
 			</Popup>
 		);

文件差異過大導致無法顯示
+ 0 - 0
src/page-instrument/evaluat-model/delay-check/json/bg.json


文件差異過大導致無法顯示
+ 0 - 0
src/page-instrument/evaluat-model/delay-check/json/bg1.json


文件差異過大導致無法顯示
+ 0 - 0
src/page-instrument/evaluat-model/delay-check/json/f2.json


文件差異過大導致無法顯示
+ 0 - 0
src/page-instrument/evaluat-model/delay-check/json/l1.json


文件差異過大導致無法顯示
+ 0 - 0
src/page-instrument/evaluat-model/delay-check/json/r1.json


+ 36 - 13
src/page-instrument/evaluat-model/index.tsx

@@ -3,8 +3,6 @@ import {
 	connectWebsocket,
 	evaluatingData,
 	handleEndBegin,
-	handleEndSoundCheck,
-	handlePerformDetection,
 	handleStartBegin,
 	handleStartEvaluat,
 	handleViewReport,
@@ -19,7 +17,7 @@ import { getNoteByMeasuresSlursStart } from "/src/helpers/formateMusic";
 import { Icon, Popup, showToast } from "vant";
 import EvaluatResult from "./evaluat-result";
 import EvaluatAudio from "./evaluat-audio";
-import { api_proxyServiceMessage, api_videoUpdate } from "/src/helpers/communication";
+import { api_getDeviceDelay, api_proxyServiceMessage, api_videoUpdate, getEarphone } from "/src/helpers/communication";
 import EvaluatShare from "./evaluat-share";
 import { Vue3Lottie } from "vue3-lottie";
 import startData from "./data/start.json";
@@ -41,6 +39,37 @@ export default defineComponent({
 			isSaveVideo: state.setting.camera && state.setting.saveToAlbum,
 			shareMode: false,
 		});
+		
+		/**
+		 * 执行检测
+		 */
+		const handlePerformDetection = async () => {
+			// 检测完成不检测了
+			if (evaluatingData.checkEnd) return;
+			// 延迟检测
+			if (evaluatingData.checkStep === 0) {
+				evaluatingData.checkStep = 10;
+				// 没有设备延迟数据 或 开启了效音 显示检测组件,并持续检测耳机状态
+				if (state.setting.soundEffect) {
+					evaluatingData.soundEffectMode = true;
+					return;
+				}
+				const delayTime = await api_getDeviceDelay();
+				console.log("🚀 ~ delayTime:", delayTime);
+				if (!delayTime) {
+					evaluatingData.soundEffectMode = true;
+					return;
+				}
+				handlePerformDetection();
+				return;
+			}
+			// 效验完成
+			if (evaluatingData.checkStep === 10) {
+				evaluatingData.checkEnd = true;
+				console.log("检测结束,生成数据");
+				handleConnect();
+			}
+		};
 		const browserInfo = browser();
 		/** 是否是节奏练习 */
 		const isRhythmicExercises = () => {
@@ -213,15 +242,6 @@ export default defineComponent({
 		onMounted(() => {
 			handlePerformDetection();
 		});
-		watch(
-			() => evaluatingData.checkEnd,
-			() => {
-				if (evaluatingData.checkEnd) {
-					console.log("检测结束,生成数据");
-					handleConnect();
-				}
-			}
-		);
 		return () => (
 			<div>
 				<Transition name="pop-center">
@@ -259,7 +279,10 @@ export default defineComponent({
 					<Vue3Lottie class={styles.dialogueIcon} animationData={startingData}></Vue3Lottie>
 				</div>
 
-				{evaluatingData.soundEffectMode && <DelayCheck />}
+				{evaluatingData.soundEffectMode && <DelayCheck onClose={() => {
+					evaluatingData.soundEffectMode = false;
+					handlePerformDetection();
+				}} />}
 
 				<Popup
 					teleport="body"

部分文件因文件數量過多而無法顯示