Browse Source

feat: 评测作业新版开发

TIANYONG 1 month ago
parent
commit
8083ad26e3

+ 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);

+ 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>						
+				}
+			</>
+		);
 	},
 });

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

@@ -98,7 +98,7 @@ export default defineComponent({
 					state.isWorkDone = true
 					training.showWorkDonePop = true
 				}
-				console.log('练习时长',training.trainingTimeSecond)
+				// console.log('练习时长',training.trainingTimeSecond)
 			}, 1000);
 		};
         const handleStop = () => {

+ 5 - 0
src/page-instrument/custom-plugins/work-index/index.tsx

@@ -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) {

BIN
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}

+ 56 - 4
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, // 提交作业显示未达标确认弹窗
     });
     /**
      * 检测返回
@@ -325,7 +328,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;
@@ -367,11 +370,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) {
@@ -485,11 +533,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(
@@ -636,6 +684,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>
+		);
+	},
+});

BIN
src/page-instrument/header-top/image/submitWorkAgain.png


BIN
src/page-instrument/header-top/image/submitWorkConfirm.png


BIN
src/page-instrument/header-top/image/submitWorkNoDoneBg.png


BIN
src/page-instrument/header-top/image/workCameraBg.png


BIN
src/page-instrument/header-top/image/workCameraCancel.png


BIN
src/page-instrument/header-top/image/workCameraConfirm.png


+ 1 - 3
src/page-instrument/header-top/workHomePop/index.module.less

@@ -67,16 +67,14 @@
         position: absolute;
         bottom: 23.5%;
         left: 50%;
-        transform: translate(-45%);
+        transform: translate(-50%);
     }
     .microCancel {
         width: 11.2vw;
-        height: 100%;
         margin-right: 2px;
     }
     .microConfirm {
         width: 11.2vw;
-        height: 100%;
         margin-left: 2px;
     }
 }

+ 1 - 0
src/view/evaluating/index.tsx

@@ -117,6 +117,7 @@ export const evaluatingData = reactive({
   tipErjiShow: false, // 评测提示弹窗
   onceErjiPopShow: false, // 是否已经提示过耳机弹窗,重新进入评测页面,重置该状态为false,手动关掉耳机弹窗,改变该状态为true,本次评测都不在提示耳机状态弹窗
   needCheckErjiStatus: true, // 点击评测模式进入评测模块的需要检测耳机状态,通过返回按钮进入评测模块的,不检测耳机状态
+  showOpenCameraPop: false, // 开启摄像头提示弹窗
 });
 
 const sendOffsetTime = async (offsetTime: number) => {