瀏覽代碼

初步完成PC audio

gemercheung 2 年之前
父節點
當前提交
e839139184

+ 1 - 0
packages/qjkankan-view/package.json

@@ -19,6 +19,7 @@
     "clipboard": "^2.0.11",
     "clipboard": "^2.0.11",
     "consola": "^3.1.0",
     "consola": "^3.1.0",
     "core-js": "^3.8.3",
     "core-js": "^3.8.3",
+    "mitt": "^3.0.0",
     "photoswipe": "^5.2.2",
     "photoswipe": "^5.2.2",
     "swiper": "^9.2.3",
     "swiper": "^9.2.3",
     "tiny-emitter": "^2.1.0",
     "tiny-emitter": "^2.1.0",

+ 1 - 1
packages/qjkankan-view/src/components/Fdkk/index.vue

@@ -88,7 +88,7 @@ const handleMessage = (res) => {
 
 
     //场景本身的背景音乐 (同时可判断场景已经加载完成)
     //场景本身的背景音乐 (同时可判断场景已经加载完成)
     if (event == "fdkkBgmLink") {
     if (event == "fdkkBgmLink") {
-      // debugger
+      debugger
       // store.commit('fdkk/setFdkkBGM', params.music)
       // store.commit('fdkk/setFdkkBGM', params.music)
       if (params.music) {
       if (params.music) {
         store.dispatch('audio/initV4BGM', params.music)
         store.dispatch('audio/initV4BGM', params.music)

+ 1 - 1
packages/qjkankan-view/src/components/Pano/index.vue

@@ -35,7 +35,7 @@ const hadGetInfo = ref(false);
 const loadScene = async (currentScene) => {
 const loadScene = async (currentScene) => {
   let app = await getApp();
   let app = await getApp();
   // await new Promise((r) => setTimeout(r, 10000));
   // await new Promise((r) => setTimeout(r, 10000));
-  console.error("loadScene",unref(currentScene).initVisual);
+  console.error("loadScene",unref(currentScene));
   if (app.krpanoDom) {
   if (app.krpanoDom) {
     let { sceneCode, initVisual, someData } = currentScene;
     let { sceneCode, initVisual, someData } = currentScene;
     app.krpanoDom.call(
     app.krpanoDom.call(

+ 45 - 77
packages/qjkankan-view/src/components/UIGather/control.vue

@@ -31,14 +31,14 @@
     <li
     <li
       @click="onIsBGM"
       @click="onIsBGM"
       v-tooltip="$t('menu.music')"
       v-tooltip="$t('menu.music')"
-      v-if="
-        (metadata.backgroundMusic && metadata.backgroundMusic.id) || fdkkBGM
-      "
+      v-if="isHasNormalBGM || isHasV4BGM"
     >
     >
       <img
       <img
         :src="
         :src="
           require(`@/assets/images/icon/${
           require(`@/assets/images/icon/${
-            showMusicPlaying ? 'music@2x.png' : 'music_disabled@2x.png'
+            isPlayNormalBGM && isCurrentPlaying
+              ? 'music@2x.png'
+              : 'music_disabled@2x.png'
           }`)
           }`)
         "
         "
         alt=""
         alt=""
@@ -49,12 +49,12 @@
     <li
     <li
       @click="onIsCommentary"
       @click="onIsCommentary"
       v-tooltip="$t('menu.commentary')"
       v-tooltip="$t('menu.commentary')"
-      v-if="currentScene.explanation && currentScene.explanation.audioUrl"
+      v-if="isHasExplanationBGM"
     >
     >
       <img
       <img
         :src="
         :src="
           require(`@/assets/images/icon/${
           require(`@/assets/images/icon/${
-            showCommentaryPlaying
+            isPlayExplanationBGM && isCurrentPlaying
               ? 'commentary@2x.png'
               ? 'commentary@2x.png'
               : 'commentary_disabled@2x.png'
               : 'commentary_disabled@2x.png'
           }`)
           }`)
@@ -117,16 +117,27 @@ import { useApp } from "@/app";
 import introduce from "./control/text";
 import introduce from "./control/text";
 import telephone from "./control/telephone";
 import telephone from "./control/telephone";
 import clink from "./control/link";
 import clink from "./control/link";
-// import { useMusicPlayer, useSoundPlayer } from "@/utils/sound";
-
-// //背景音乐
-// const musicPlayer = useMusicPlayer();
-
-// //解说音乐
-// const soundPlayer = useSoundPlayer();
 
 
 const store = useStore();
 const store = useStore();
 
 
+//BMG音乐
+const isHasNormalBGM = computed(() => store.getters["audio/isHasNormalBGM"]);
+const isCurrentPlaying = computed(
+  () => store.getters["audio/isCurrentPlaying"]
+);
+const isHasV3BGM = computed(() => store.getters["audio/isHasV3BGM"]);
+const isHasV4BGM = computed(() => store.getters["audio/isHasV4BGM"]);
+const isHasExplanationBGM = computed(
+  () => store.getters["audio/isHasExplanationBGM"]
+);
+//BMG playing音乐
+const isPlayNormalBGM = computed(() => store.getters["audio/isPlayNormalBGM"]);
+const isPlayV3BGM = computed(() => store.getters["audio/isPlayV3BGM"]);
+const isPlayV4BGM = computed(() => store.getters["audio/isPlayV4BGM"]);
+const isPlayExplanationBGM = computed(
+  () => store.getters["audio/isPlayExplanationBGM"]
+);
+
 const metadata = computed(() => store.getters["scene/metadata"]);
 const metadata = computed(() => store.getters["scene/metadata"]);
 
 
 const isDoneforCover = computed(() => store.getters["scene/isDoneforCover"]);
 const isDoneforCover = computed(() => store.getters["scene/isDoneforCover"]);
@@ -154,65 +165,6 @@ const customLink = computed(() => store.getters["scene/customLink"]);
 // const fdkkmetadata = computed(() => store.getters["fdkk/metadata"]);
 // const fdkkmetadata = computed(() => store.getters["fdkk/metadata"]);
 const fdkkBGM = computed(() => store.getters["fdkk/fdkkBGM"]);
 const fdkkBGM = computed(() => store.getters["fdkk/fdkkBGM"]);
 
 
-// const setExplanation = (from) => {
-//   if (
-//     "explanation" in currentScene.value &&
-//     "audioUrl" in currentScene.value.explanation
-//   ) {
-//     console.log("设置解说", from);
-//     let { audioUrl, openByDefault, repeat } = currentScene.value.explanation;
-//     // showCommentaryPlaying.value = false;
-//     store.commit("functions/setCommentaryUrl", {
-//       src: audioUrl,
-//       loop: repeat,
-//       openByDefault: openByDefault,
-//     });
-//     useSoundPlayer.player.isLock = false;
-//     useSoundPlayer.player.watchPlay();
-//   }
-// };
-// const stopExplanation = (from) => {
-//   console.log("stop解说", from);
-//   useSoundPlayer.player.isLock = true;
-//   soundPlayer.paused();
-// };
-// const resumeExplanation = () => {
-//   console.log("resume解说");
-//   useSoundPlayer.player.isLock = false;
-//   useSoundPlayer.player.watchPlay();
-// };
-// const resetExplanation = (from) => {
-//   console.log("清空解说", from);
-//   store.commit("functions/setCommentaryUrl", "");
-//   useSoundPlayer.player.isLock = true;
-//   soundPlayer.paused();
-// };
-// watch([isShowCover, isDoneforCover], (val) => {
-//   if (unref(val[0]) && unref(val[1])) {
-//     resumeExplanation(2);
-//   }
-//   if (unref(val[0]) && !unref(val[1])) {
-//     stopExplanation(2);
-//   }
-// });
-
-// watchEffect(() => {
-//   if (currentScene.value.explanation) {
-//     let { audioUrl } = currentScene.value.explanation;
-
-//     if (audioUrl) {
-//       //解说有变,初始化按钮状态
-//       setExplanation(1);
-//       if (unref(isShowCover)) {
-//         stopExplanation(1);
-//       }
-//     } else {
-//       resetExplanation(1);
-//     }
-//   } else {
-//     resetExplanation(2);
-//   }
-// });
 const showIntroduce = computed(() => store.getters["functions/showIntroduce"]);
 const showIntroduce = computed(() => store.getters["functions/showIntroduce"]);
 const showTelephone = computed(() => store.getters["functions/showTelephone"]);
 const showTelephone = computed(() => store.getters["functions/showTelephone"]);
 const showLink = computed(() => store.getters["functions/showLink"]);
 const showLink = computed(() => store.getters["functions/showLink"]);
@@ -236,16 +188,32 @@ const onLink = () => {
   }
   }
 };
 };
 
 
-// const onIsBGM = () => {
-//   showMusicPlaying.value ? musicPlayer.pause() : musicPlayer.play();
-// };
+const onIsBGM = () => {
+  if (!unref(isPlayNormalBGM)) {
+    store.dispatch("audio/playBGM", 0);
+  } else {
+    if (unref(isCurrentPlaying)) {
+      store.dispatch("audio/pauseBGM");
+    } else {
+      store.dispatch("audio/playBGM", 0);
+    }
+  }
+};
 
 
 const onIsAutoRotate = (data) => {
 const onIsAutoRotate = (data) => {
   store.commit("functions/setAutoRotate", !isAutoRotate.value);
   store.commit("functions/setAutoRotate", !isAutoRotate.value);
 };
 };
 
 
-const onIsCommentary = (data) => {
-  showCommentaryPlaying.value ? soundPlayer.pause() : soundPlayer.play();
+const onIsCommentary = () => {
+  if (!unref(isPlayExplanationBGM)) {
+    store.dispatch("audio/playBGM", 3);
+  } else {
+    if (unref(isCurrentPlaying)) {
+      store.dispatch("audio/pauseBGM");
+    } else {
+      store.dispatch("audio/playBGM", 3);
+    }
+  }
 };
 };
 
 
 const onFullScreen = () => {
 const onFullScreen = () => {

+ 185 - 2
packages/qjkankan-view/src/hooks/useAudio.js

@@ -1,15 +1,198 @@
 /**
 /**
  * 利用
  * 利用
  */
  */
+import store from '@/store';
+import { computed, onMounted, watch, ref, unref } from 'vue';
+import mitt from 'mitt';
+let CLICKFIRST = false
 
 
+const currentPlayer = ref(null);
+const isInit = ref(false);
+const currentAudio = computed(() => store.getters['audio/currentAudio']);
+const isDoneforCover = computed(() => store.getters["scene/isDoneforCover"]);
+const currentScene = computed(() => store.getters["scene/currentScene"]);
+const isShowCover = computed(
+    () => store.getters["scene/metadata"].coverInfo.isShowCover === 1 || false
+);
 
 
 
 
-async function playDefaultAudio() {
+async function initDefaultAudio() {
+    watch([isShowCover, isDoneforCover, currentScene], ([val1, val2, val3]) => {
+        //开场完成后才开始初始化audioplayer
+        console.log('initDefaultAudio', unref(val1), unref(val2));
+        if (!unref(val1)) {
+            // 开场封面关闭时
+            initAudioPlayer();
+        } else {
+            // 开场封面开启时并跳转完成时
+            if (unref(val2)) {
+                initAudioPlayer();
+            }
+        }
+        watchUpdateCurrentScenEexplanation(unref(val3))
+        watchResetV4BGM(unref(val3))
+    }, {
+        deep: true,
+        immediate: true,
+    })
 
 
+    watch(currentAudio, (val) => {
+        if (unref(val).url.length > 0) {
+            console.log('currentAudio', unref(val).url)
+            if (unref(currentPlayer)) {
+                unref(currentPlayer).changeUrl(unref(val).url);
+            }
+            // currentPlayer.value.changeUrl(unref(val).url);
+        }
+    }, {
+        deep: true,
+        immediate: true,
+    })
+}
+function initAudioPlayer() {
+
+    if (!unref(isInit)) {
+        const player = createAudioPlayer(unref(currentAudio).url);
+        isInit.value = true
+        currentPlayer.value = player
+        player.on('play', () => {
+            console.log('play--22', player.isPlaying);
+            store.dispatch('audio/updatePlayerStatus', player.isPlaying);
+        })
+        player.on('pause', () => {
+            console.log('pause--33', player.isPlaying);
+            store.dispatch('audio/updatePlayerStatus', player.isPlaying);
+        })
+        player.on('end', () => {
+            console.log('end--33', player.isPlaying);
+            store.dispatch('audio/updatePlayerStatus', player.isPlaying);
+        })
+        window.store = store
+    }
+}
+
+function watchUpdateCurrentScenEexplanation(data) {
+
+    if ("explanation" in data) {
+        store.dispatch("audio/initExplanationBGM", {
+            url: data.explanation.audioUrl,
+            repeat: data.explanation.repeat,
+            isAuto: data.explanation.openByDefault,
+        });
+    } else {
+        console.log('not initExplanationBGM');
+        store.dispatch("audio/initExplanationBGM", {
+            url: "",
+            repeat: false,
+            isAuto: false,
+
+        });
+    }
+}
+function watchResetV4BGM(data) {
+    console.log('data.type', data.type)
+    if (data.type !== '4dkk') {
+        store.dispatch('audio/initV4BGM', '')
+    }
+
+}
+
+function createAudioPlayer(url) {
+    const player = new AudioPlayer({
+        src: url,
+        loop: true
+    });
+
+    return player
+}
+
+class AudioPlayer {
+    constructor(options) {
+        this._src = options.src;
+        this._loop = options.loop;
+        this._isPlaying = false;
+        const emitter = mitt()
+        Object.keys(emitter).forEach((method) => {
+            this[method] = emitter[method]
+        })
+        this.audio = null
+        this.init();
+    }
+    get isPlaying() {
+        return this._isPlaying;
+    }
+    changeUrl(url) {
+        console.log('changeUrl');
+        this.audio.unload();
+        this._isPlaying = false;
+        this._src = url;
+        this.audio = null;
+        this.createAudio();
+        this.play();
+        this.emit('change', this.audio);
+    }
+    init() {
+        this.createAudio();
+        this.bindElement();
+        this.play();
+        this.emit('ready', this.audio);
+    }
+    createAudio() {
+        this.audio = new Howl({
+            preload: true,
+            src: [this._src],
+            loop: this._loop || false,
+            html5: false,
+            onplay: () => {
+                this._isPlaying = true
+                this.emit('play')
+            },
+            onpause: () => {
+                this._isPlaying = false
+                this.emit('pause')
+            },
+            onend: () => {
+                this._isPlaying = false
+                this.emit('end')
+            },
+
+        })
+
+    }
+    bindElement() {
+        const $player = document.querySelector('.ui-view-layout')
+        const onclick = () => {
+            $player.removeEventListener('click', onclick)
+            $player.removeEventListener('touchstart', onclick)
+            //判断是否第一次进入或者是否已点击过
+            if (CLICKFIRST) {
+                return
+            }
+            CLICKFIRST = true
+            this.play();
+        }
+        $player.addEventListener('click', onclick)
+        $player.addEventListener('touchstart', onclick)
+    }
+
+    async play() {
+        try {
+            if (!this._isPlaying) {
+                await this.audio.play();
+            }
+
+        } catch (error) {
+            console.warn('playError', error);
+        }
+    }
+    pause() {
+        return this.audio.pause();
+    }
 }
 }
 
 
 export function useAudio() {
 export function useAudio() {
     return {
     return {
-        playDefaultAudio,
+        initDefaultAudio,
+        currentPlayer,
     };
     };
 }
 }

+ 51 - 51
packages/qjkankan-view/src/pages/show.vue

@@ -37,7 +37,7 @@ import { getPanoInfo, checkWork } from "@/apis";
 import { useStore } from "vuex";
 import { useStore } from "vuex";
 import config from "@/utils/config";
 import config from "@/utils/config";
 import browser from "@/utils/browser";
 import browser from "@/utils/browser";
-import { useApp } from "@/app";
+import { useAudio } from "@/hooks/useAudio";
 import { useI18n, getLocale } from "@/i18n";
 import { useI18n, getLocale } from "@/i18n";
 const { t } = useI18n({ useScope: "global" });
 const { t } = useI18n({ useScope: "global" });
 
 
@@ -114,14 +114,6 @@ onMounted(async () => {
     const currentSceneData = firstScene || data.scenes[0];
     const currentSceneData = firstScene || data.scenes[0];
     // debugger;
     // debugger;
     store.dispatch("audio/initNormalBGM", data.backgroundMusic.ossPath);
     store.dispatch("audio/initNormalBGM", data.backgroundMusic.ossPath);
-    if ("explanation" in currentSceneData) {
-      store.dispatch("audio/initExplanationBGM", {
-        url: currentSceneData.explanation.audioUrl,
-        repeat: currentSceneData.explanation.repeat,
-        isAuto: currentSceneData.explanation.openByDefault,
-      });
-    }
-
     store.commit("scene/setCurrentScene", currentSceneData);
     store.commit("scene/setCurrentScene", currentSceneData);
 
 
     // 过滤空分组
     // 过滤空分组
@@ -201,56 +193,64 @@ onMounted(async () => {
       passQueryParameters: true,
       passQueryParameters: true,
     });
     });
 
 
-    coverInfo.value = data.coverInfo || {};
-    app.Scene.lock();
-    //如果不需要开场封面就直接渲染
-    if (!coverInfo.value?.isShowCover) {
-      app.render();
-    }
-
-    if (isHavePano) {
-      app.Scene.on("sceneReady", () => {
-        if (app.krpanoDom) {
-          let defaultMask = `%SWFPATH%/skin/masking_${lang}.png`;
+    if (app) {
+      coverInfo.value = data.coverInfo || {};
+      app.Scene.lock();
+      //如果不需要开场封面就直接渲染
+      if (!coverInfo.value?.isShowCover) {
+        app.render();
+      }
 
 
-          if (earthMask.value) {
-            app.krpanoDom.set(`hotspot[nadirlogo].url`, defaultMask);
-            app.krpanoDom.set(
-              `hotspot[nadirlogo].visible`,
-              earthMask.value.isShow
-            );
+      if (isHavePano) {
+        app.Scene.on("sceneReady", () => {
+          if (app.krpanoDom) {
+            let defaultMask = `%SWFPATH%/skin/masking_${lang}.png`;
+
+            if (earthMask.value) {
+              app.krpanoDom.set(`hotspot[nadirlogo].url`, defaultMask);
+              app.krpanoDom.set(
+                `hotspot[nadirlogo].visible`,
+                earthMask.value.isShow
+              );
+
+              if (earthMask.value.icon) {
+                app.krpanoDom.set(
+                  `hotspot[nadirlogo].url`,
+                  earthMask.value.icon
+                );
+              }
+            }
 
 
-            if (earthMask.value.icon) {
-              app.krpanoDom.set(`hotspot[nadirlogo].url`, earthMask.value.icon);
+            if (skyMask.value) {
+              app.krpanoDom.set(`hotspot[peaklogo].url`, defaultMask);
+              app.krpanoDom.set(
+                `hotspot[peaklogo].visible`,
+                skyMask.value.isShow
+              );
+              if (skyMask.value.icon) {
+                app.krpanoDom.set(`hotspot[peaklogo].url`, skyMask.value.icon);
+              }
             }
             }
-          }
 
 
-          if (skyMask.value) {
-            app.krpanoDom.set(`hotspot[peaklogo].url`, defaultMask);
             app.krpanoDom.set(
             app.krpanoDom.set(
-              `hotspot[peaklogo].visible`,
-              skyMask.value.isShow
+              `layer[webvr_exitbutton].html`,
+              t("common.exit_vr")
             );
             );
-            if (skyMask.value.icon) {
-              app.krpanoDom.set(`hotspot[peaklogo].url`, skyMask.value.icon);
-            }
           }
           }
+          let hotspots = [];
+          if (currentScene.value.someData) {
+            hotspots =
+              typeof currentScene.value.someData == "string"
+                ? JSON.parse(currentScene.value.someData).hotspots
+                : currentScene.value.someData.hotspots;
+          }
+          console.log(hotspots, "hotspots");
+          app.Tags.initHotspot(hotspots, false);
+        });
+      }
 
 
-          app.krpanoDom.set(
-            `layer[webvr_exitbutton].html`,
-            t("common.exit_vr")
-          );
-        }
-        let hotspots = [];
-        if (currentScene.value.someData) {
-          hotspots =
-            typeof currentScene.value.someData == "string"
-              ? JSON.parse(currentScene.value.someData).hotspots
-              : currentScene.value.someData.hotspots;
-        }
-        console.log(hotspots, "hotspots");
-        app.Tags.initHotspot(hotspots, false);
-      });
+      const { initDefaultAudio } = useAudio();
+      initDefaultAudio();
     }
     }
   });
   });
 });
 });

+ 2 - 2
packages/qjkankan-view/src/store/index.js

@@ -4,13 +4,13 @@ import modules from './modules/'
 export default createStore({
 export default createStore({
   state() {
   state() {
     return {
     return {
-    
+
     }
     }
   },
   },
   getters: {
   getters: {
   },
   },
   mutations: {
   mutations: {
-   
+
   },
   },
   actions: {},
   actions: {},
   modules: {
   modules: {

+ 81 - 22
packages/qjkankan-view/src/store/modules/audio.js

@@ -1,3 +1,5 @@
+import { useAudio } from '@/hooks/useAudio';
+import { unref } from 'vue';
 
 
 export default {
 export default {
     namespaced: true,
     namespaced: true,
@@ -33,13 +35,44 @@ export default {
                 url: "",
                 url: "",
                 type: 3,
                 type: 3,
                 isAuto: false,
                 isAuto: false,
-                order: 100,
+                order: 11,
                 repeat: false,
                 repeat: false,
             }, //解说音乐
             }, //解说音乐
+            currentPlaying: false
         }
         }
     },
     },
-    getters() {
-        bgmList: (state) => [state.normalBGM, state.v3BGM, state.v4BGM, state.explanationBGM]
+    getters: {
+        bgmList: (state) => [state.normalBGM, state.v3BGM, state.v4BGM, state.explanationBGM],
+        currentAudio: (_, getters) => {
+            const arr = Array.from(getters.bgmList).filter(i => i.url).sort((a, b) => b.order - a.order)
+            return arr.length > 0 ? arr[0] : [];
+        },
+
+        isCurrentPlaying: (state) => state.currentPlaying,
+        isHasNormalBGM: (state) => {
+            return state.normalBGM.url.length > 0
+        },
+        isHasV3BGM: (state) => {
+            return state.v4BGM.url.length > 0
+        },
+        isHasV4BGM: (state) => {
+            return state.v4BGM.url.length > 0
+        },
+        isHasExplanationBGM: (state) => {
+            return state.explanationBGM.url.length > 0
+        },
+        isPlayNormalBGM: (_, getters) => {
+            return getters.currentAudio.type === 0
+        },
+        isPlayV3BGM: (_, getters) => {
+            return getters.currentAudio.type === 2
+        },
+        isPlayV4BGM: (_, getters) => {
+            return getters.currentAudio.type === 2
+        },
+        isPlayExplanationBGM: (_, getters) => {
+            return getters.currentAudio.type === 3
+        }
     },
     },
     mutations: {
     mutations: {
         setNormalBGM(state, payload) {
         setNormalBGM(state, payload) {
@@ -56,38 +89,64 @@ export default {
             state.v4BGM.isAuto = payload.isAuto
             state.v4BGM.isAuto = payload.isAuto
             state.v4BGM.repeat = payload.repeat
             state.v4BGM.repeat = payload.repeat
         },
         },
+        setPlayStatus(state, payload) {
+            state.currentPlaying = payload
+        }
 
 
     },
     },
     actions: {
     actions: {
         initNormalBGM({ commit }, url) {
         initNormalBGM({ commit }, url) {
             // 一般背景音乐
             // 一般背景音乐
-            if (url.length > 0) {
-                commit('setNormalBGM', {
-                    isAuto: true,
-                    url: url
-                })
-            }
-
-            // debugger
+            commit('setNormalBGM', {
+                isAuto: true,
+                url: url
+            })
         },
         },
         initExplanationBGM({ commit }, { url, repeat, isAuto }) {
         initExplanationBGM({ commit }, { url, repeat, isAuto }) {
-            // 解说音乐
-            if (url.length > 0) {
-                commit('setExplanationBGM', { url, repeat, isAuto });
-            }
+            commit('setExplanationBGM', { url, repeat, isAuto });
         },
         },
 
 
-        initExplanationBGM({ commit }, { url, repeat, isAuto }) {
-            // 解说音乐
-            if (url.length > 0) {
-                commit('setExplanationBGM', { url, repeat, isAuto });
-            }
+        initV3BGM({ commit }, { url, repeat, isAuto }) {
+            // V3音乐
+            commit('setV3BGM', { url, repeat, isAuto });
         },
         },
         initV4BGM({ commit }, url) {
         initV4BGM({ commit }, url) {
             // v4音乐
             // v4音乐
-            if (url.length > 0) {
-                commit('setV4BGM', { url, repeat: true, isAuto: true });
+            commit('setV4BGM', { url, repeat: true, isAuto: true });
+        },
+        playBGM({ commit, getters, state }, type) {
+            const index = getters['currentAudio'].order;
+            const order = index + 1;
+            const target = getters['bgmList'].find(i => i.type === type);
+            if (target.url.length > 0) {
+                switch (type) {
+                    case 0:
+                        state.normalBGM.order = order;
+                        break;
+                    case 1:
+                        state.v3BGM.order = order;
+                        break;
+                    case 2:
+                        state.v4BGM.order = order;
+                        break;
+                    case 3:
+                        state.explanationBGM.order = order;
+                        break;
+                    default:
+                        state.normalBGM.order = order;
+                        break;
+                }
+            } else {
+                console.error('当前BGM没有URL');
             }
             }
+
+        },
+        pauseBGM() {
+            const { currentPlayer } = useAudio();
+            currentPlayer.value.pause();
+        },
+        updatePlayerStatus({ commit }, status) {
+            commit('setPlayStatus', status)
         }
         }
     }
     }