123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291 |
- import { Snackbar } from "@varlet/ui";
- import { closeToast, showLoadingToast } from "vant";
- import { defineComponent, onBeforeUnmount, onMounted, onUnmounted, reactive, ref, watch } from "vue";
- import { getLeveByScore, getLeveByScoreMeasure, IEvaluatings } from "./evaluatResult";
- import {
- cancelEvaluating,
- endEvaluating,
- endSoundCheck,
- getEarphone,
- api_proxyServiceMessage,
- removeResult,
- sendResult,
- startEvaluating,
- startSoundCheck,
- api_openWebView,
- api_startRecording,
- api_stopRecording,
- } from "/src/helpers/communication";
- import state, { clearSelection, handleStopPlay, resetPlaybackToStart, togglePlay } from "/src/state";
- import { IPostMessage } from "/src/utils/native-message";
- import { usePageVisibility } from "@vant/use";
- export const evaluatingData = reactive({
- contentData: {} as any,
- /** 评测模块是否加载完成 */
- rendered: false,
- earphone: false, // 是否插入耳机
- soundEffect: false, // 是否效音
- soundEffectFrequency: 0, // 效音频率
- checkStep: 0, // 执行步骤
- checkEnd: false, // 检测结束
- earphoneMode: false, // 耳机弹窗
- soundEffectMode: false, // 效音弹窗
- websocketState: false, // websocket连接状态
- startBegin: false, // 开始
- backtime: 0, // 延迟时间
- /** 已经评测的数据 */
- evaluatings: {} as IEvaluatings,
- /** 评测结果 */
- resultData: {} as any,
- /** 评测结果弹窗 */
- resulstMode: false,
- });
- /** 点击开始评测按钮 */
- export const handleStartEvaluat = () => {
- if (state.modeType === "evaluating") {
- handleCancelEvaluat();
- } else {
- handleStopPlay();
- }
- state.modeType = state.modeType === "evaluating" ? "practise" : "evaluating";
- if (state.modeType !== "evaluating") {
- // 切换到练习模式,卸载评测模块
- evaluatingData.rendered = false;
- }
- };
- /** 开始播放发送延迟时间 */
- export const sendEvaluatingOffsetTime = (currentTime: number) => {
- const nowTime = Date.now();
- // console.log("第一次播放时间", evaluatingData.backtime);
- // console.log("已播放时长: ", currentTime, currentTime * 1000);
- // console.log("不减掉已播放时间: ", nowTime - evaluatingData.backtime , currentTime);
- const delayTime = (nowTime - evaluatingData.backtime - currentTime * 1000) / 1000;
- console.log("真正播放延迟", delayTime / 1000);
- // 蓝牙耳机延迟一点发送消息确保在录音后面
- setTimeout(async () => {
- await api_proxyServiceMessage({
- header: {
- commond: "audioPlayStart",
- type: "SOUND_COMPARE",
- },
- body: {
- offsetTime: delayTime < 0 ? 0 : delayTime,
- },
- });
- evaluatingData.backtime = 0;
- }, 220);
- };
- /** 检测耳机 */
- const checkUseEarphone = async () => {
- const res = await getEarphone();
- return res?.content?.checkIsWired || false;
- };
- /**
- * 开始录音
- */
- const handleStartSoundCheck = () => {
- startSoundCheck();
- };
- /** 结束录音 */
- export const handleEndSoundCheck = () => {
- endSoundCheck();
- };
- /** 连接websocket */
- export const connectWebsocket = async (content: any) => {
- evaluatingData.contentData = content;
- evaluatingData.websocketState = true;
- };
- /**
- * 执行检测
- */
- export const handlePerformDetection = async () => {
- evaluatingData.checkEnd = false;
- if (evaluatingData.checkStep === 0) {
- // 检测耳机
- const erji = await checkUseEarphone();
- evaluatingData.checkStep = 1;
- if (erji) {
- handlePerformDetection();
- } else {
- evaluatingData.earphoneMode = true;
- }
- return;
- }
- if (evaluatingData.checkStep === 1) {
- // 效音
- // 是否需要开启效音
- evaluatingData.checkStep = 10;
- if (state.setting.soundEffect) {
- evaluatingData.soundEffectMode = true;
- handleStartSoundCheck();
- } else {
- handlePerformDetection();
- }
- return;
- }
- if (evaluatingData.checkStep === 10) {
- // 连接websocket
- evaluatingData.checkEnd = true;
- evaluatingData.checkStep = 0;
- }
- };
- /** 记录小节分数 */
- const addMeasureScore = (measureScore: any) => {
- evaluatingData.evaluatings[measureScore.measureRenderIndex] = {
- ...measureScore,
- leve: getLeveByScoreMeasure(measureScore.score),
- show: true,
- };
- // console.log("🚀 ~ measureScore:", evaluatingData.evaluatings[measureScore.measureRenderIndex])
- };
- const handleScoreResult = (res?: IPostMessage) => {
- if (res?.content) {
- console.log("🚀 ~ 评测返回:", res);
- const { header, body } = res.content;
- // 效音返回
- if (header.commond === "checking") {
- evaluatingData.soundEffectFrequency = body.frequency;
- }
- // 小节评分返回
- if (header?.commond === "measureScore") {
- addMeasureScore(body);
- }
- // 评测结束返回
- if (header?.commond === "overall") {
- // console.log("评测结束", body);
- evaluatingData.resulstMode = true;
- evaluatingData.resultData = {
- ...body,
- ...getLeveByScore(body.score),
- };
- // console.log("🚀 ~ evaluatingData.resultData:", evaluatingData.resultData)
- closeToast();
- }
- }
- };
- /** 开始评测 */
- export const handleStartBegin = async () => {
- evaluatingData.startBegin = true;
- evaluatingData.evaluatings = {};
- evaluatingData.resultData = {};
- evaluatingData.backtime = Date.now();
- resetPlaybackToStart();
- try {
- console.log("🚀 ~ content:", evaluatingData.contentData, JSON.stringify(evaluatingData.contentData));
- } catch (error) {}
- const res = await startEvaluating(evaluatingData.contentData);
- if (res?.api !== "startEvaluating") {
- Snackbar.error("请在APP端进行评测");
- evaluatingData.startBegin = false;
- return;
- }
- // 开始录音
- api_startRecording();
- const playState = await togglePlay("play");
- // 取消播放
- if (!playState) {
- evaluatingData.startBegin = false;
- handleCancelEvaluat();
- return;
- }
- };
- /**
- * 结束评测
- */
- export const handleEndEvaluat = () => {
- console.log("触发结束");
- // 没有开始评测 , 不是评测模式 , 不评分
- if (!evaluatingData.startBegin || state.modeType !== "evaluating") return;
- evaluatingData.startBegin = false;
- // 结束录音
- api_stopRecording();
- // 结束评测
- endEvaluating({
- musicScoreId: state.examSongId,
- });
- showLoadingToast({
- message: "评分中",
- duration: 0,
- forbidClick: true,
- });
- };
- /**
- * 结束评测
- * @param isEnd 是否是自动播放停止, 默认: false
- */
- export const handleEndBegin = () => {
- handleEndEvaluat();
- handleStopPlay();
- };
- /**
- * 取消评测
- */
- export const handleCancelEvaluat = () => {
- evaluatingData.evaluatings = {};
- // 关闭提示
- closeToast();
- // 取消记录
- api_proxyServiceMessage({
- header: {
- commond: "recordCancel",
- type: "SOUND_COMPARE",
- status: 200,
- },
- });
- // 取消评测
- cancelEvaluating();
- // 停止播放
- handleStopPlay();
- };
- /** 查看报告 */
- export const handleViewReport = () => {
- api_openWebView({
- url: location.origin + "/accompany/#/report/" + evaluatingData.resultData?.recordId || "",
- orientation: 0,
- isHideTitle: true, // 此处兼容安卓,意思为隐藏全部头部
- statusBarTextColor: false,
- isOpenLight: true,
- });
- };
- export default defineComponent({
- name: "evaluating",
- setup() {
- const pageVisibility = usePageVisibility();
- watch(pageVisibility, (value) => {
- if (value == "hidden" && evaluatingData.startBegin) {
- handleEndBegin();
- }
- });
- onMounted(() => {
- evaluatingData.resultData = {};
- // evaluatingData.resultData = {...getLeveByScore(90), score: 30, intonation: 10, cadence: 30, integrity: 40}
- // console.log("🚀 ~ evaluatingData.resultData:", evaluatingData.resultData)
- evaluatingData.evaluatings = {};
- evaluatingData.soundEffectFrequency = 0;
- evaluatingData.checkStep = 0;
- evaluatingData.rendered = true;
- sendResult(handleScoreResult);
- if (!state.isSelectMeasureMode) {
- clearSelection();
- }
- });
- onUnmounted(() => {
- removeResult(handleScoreResult);
- });
- return () => <div></div>;
- },
- });
|