Browse Source

Merge branch 'dev' of http://git.dayaedu.com/huangqiyong/classroom into staging

黄琪勇 9 tháng trước cách đây
mục cha
commit
e8545916b2

+ 0 - 0
src/views/coursewarePlay/components/practiceForm/index.ts → src/businessComponents/practiceForm/index.ts


+ 1 - 1
src/views/coursewarePlay/components/practiceForm/practiceForm.vue → src/businessComponents/practiceForm/practiceForm.vue

@@ -1,5 +1,5 @@
 <!--
-* @FileDescription: 去练习 弹窗
+* @FileDescription: 云教练 弹窗
 * @Author: 黄琪勇
 * @Date:2024-09-05 19:13:16
 -->

BIN
src/img/cloudPractice/icon-left-active.png


+ 80 - 43
src/views/cloudPractice/cloudPractice.tsx

@@ -1,4 +1,4 @@
-import { computed, defineComponent, onMounted, reactive, ref, shallowRef } from "vue"
+import { computed, defineComponent, nextTick, onMounted, reactive, ref, shallowRef } from "vue"
 import styles from "./index.module.scss"
 import NavContainer from "@/businessComponents/navContainer"
 import { ElEmpty, ElScrollbar } from "element-plus"
@@ -32,12 +32,14 @@ import { getInstrumentName } from "@/libs/instruments"
 import { formatXML, getCustomInfo, onlyVisible } from "./instrument"
 import { useFunction } from "./useData"
 import userStore from "@/store/modules/user"
+import PlayLoading from "./component/play-loading"
+import PracticeForm from "@/businessComponents/practiceForm"
 
 export default defineComponent({
    name: "cloudPractice",
    setup() {
       const userStoreHook = userStore()
-      const { goToCloud } = useFunction()
+      const { goToCloud, isPracticeShow, practiceUrl, handlePracticeClose } = useFunction()
       const navs = [
          {
             name: "主页",
@@ -73,6 +75,7 @@ export default defineComponent({
          selectedPartName: "" as any,
          selectedPartIndex: 0,
          partXmlIndex: 0,
+         categoryShow: false, // 是否展开
          playState: "pause" as "play" | "pause", // 播放状态
          showPlayer: false // 是否显示播放器
       })
@@ -92,7 +95,8 @@ export default defineComponent({
                background: list?.background,
                xmlUrl: item?.xmlUrl,
                musicSheetType: item?.musicSheetType,
-               audioFileUrl
+               audioFileUrl,
+               isComberRender: false
             }
          } else if (userStoreHook.roles === "GYT") {
             tempList = {
@@ -101,7 +105,8 @@ export default defineComponent({
                background: list?.background,
                xmlUrl: list?.xmlFileUrl,
                musicSheetType: list?.musicSheetType,
-               audioFileUrl: list?.audioFileUrl
+               audioFileUrl: list?.audioFileUrl,
+               isComberRender: list?.musicSubject === "1"
             }
          } else if (userStoreHook.roles === "KLX") {
             const item: any = list.background?.[0]
@@ -111,7 +116,8 @@ export default defineComponent({
                background: list?.background,
                xmlUrl: list?.xmlFileUrl,
                musicSheetType: list?.musicSheetType,
-               audioFileUrl: item?.audioFileUrl
+               audioFileUrl: item?.audioFileUrl,
+               isComberRender: false
             }
          }
          return tempList
@@ -668,6 +674,11 @@ export default defineComponent({
          state.listActive = 0
          state.showPlayer = false
          state.playState = "pause"
+         state.partNames = []
+         state.partList = []
+         state.selectedPartName = ""
+         state.selectedPartIndex = 0
+         state.partXmlIndex = 0
          document.querySelector(".musicList-container")?.scroll(0, 0)
          state.page = 1
          state.finshed = false
@@ -682,7 +693,6 @@ export default defineComponent({
             loading.value = false
             return
          }
-         console.log(row, "row")
          state.partNames = await getPartNames(row.xmlUrl)
          let partList = row.background || []
          partList = partList.filter((item: any) => !item.track?.toLocaleUpperCase()?.includes("COMMON"))
@@ -690,7 +700,7 @@ export default defineComponent({
             const instrumentName = getInstrumentName(item.track)
             const xmlIndex = state.partNames.findIndex((name: any) => name === item.track)
             return {
-               text: item.track + (instrumentName ? `(${instrumentName})` : ""),
+               label: item.track + (instrumentName ? `(${instrumentName})` : ""),
                instrumentName: instrumentName,
                xmlIndex,
                value: index
@@ -701,15 +711,13 @@ export default defineComponent({
          console.log(defaultShowStaff, partList)
          state.selectedPartName = defaultShowStaff?.instrumentName
          state.partXmlIndex = defaultShowStaff?.xmlIndex
-
-         console.log(partColumns.value, "partColumns partColumns")
       }
 
       const getPartNames = async (xmlUrl: string) => {
          const partNames: string[] = []
          try {
             const res: any = await axios.get(xmlUrl)
-            const xml: any = new DOMParser().parseFromString(res, "text/xml")
+            const xml: any = new DOMParser().parseFromString(res.data, "text/xml")
             for (const item of xml.getElementsByTagName("part-name")) {
                if (item.textContent) {
                   partNames.push(item.textContent)
@@ -723,24 +731,33 @@ export default defineComponent({
 
       const musicIframeLoad = async () => {
          const iframeRef: any = document.getElementById("staffIframeRef")
-         if (iframeRef && iframeRef.contentWindow?.renderXml) {
+         if (iframeRef && iframeRef.contentWindow.renderXml) {
             staffLoading.value = true
-            const res = await axios.get(activeItem.value.xmlUrl)
+            const res: any = await axios.get(activeItem.value.xmlUrl)
             const parseXmlInfo = getCustomInfo(res.data)
             const xml = formatXML(parseXmlInfo.parsedXML)
-            const currentXml = onlyVisible(xml, state.selectedPartIndex)
-            iframeRef.contentWindow.renderXml(currentXml, state.selectedPartIndex)
+            if (activeItem.value.isComberRender) {
+               iframeRef.contentWindow.renderXml(xml, state.partXmlIndex, activeItem.value.isComberRender)
+            } else {
+               const currentXml = onlyVisible(xml, state.partXmlIndex)
+               iframeRef.contentWindow.renderXml(currentXml, state.partXmlIndex, activeItem.value.isComberRender)
+            }
          }
       }
       const resetRender = async () => {
          const iframeRef: any = document.getElementById("staffIframeRef")
-         if (iframeRef && iframeRef.contentWindow?.renderXml) {
+         if (iframeRef && iframeRef.contentWindow.renderXml) {
             staffLoading.value = true
-            const res = await axios.get(activeItem.value.xmlUrl)
+            const res: any = await axios.get(activeItem.value.xmlUrl)
             const parseXmlInfo = getCustomInfo(res.data)
             const xml = formatXML(parseXmlInfo.parsedXML)
-            const currentXml = onlyVisible(xml, state.selectedPartIndex)
-            iframeRef.contentWindow.renderXml(currentXml, state.selectedPartIndex)
+            if (activeItem.value.isComberRender) {
+               iframeRef.contentWindow.renderXml(xml, state.partXmlIndex, activeItem.value.isComberRender)
+            } else {
+               console.log(state.partXmlIndex, " state.partXmlIndex")
+               const currentXml = onlyVisible(xml, state.partXmlIndex)
+               iframeRef.contentWindow.renderXml(currentXml, 0, activeItem.value.isComberRender)
+            }
          }
       }
 
@@ -813,9 +830,11 @@ export default defineComponent({
                                  <div
                                     class={[styles.leftSection_item, item.id === state.firstTreeId && styles.leftSection_item__active]}
                                     onClick={async () => {
+                                       if (loading.value) return
                                        state.firstTreeId = item.id
                                        await setDefaultData("first")
-                                       handleGetList()
+                                       await handleGetList()
+                                       await toDetail()
                                     }}
                                  >
                                     {item.name}
@@ -829,6 +848,8 @@ export default defineComponent({
                               {state.categoryList.length > 1 && (
                                  <div class={[styles.categorySection]}>
                                     <NPopselect
+                                       placement="bottom-start"
+                                       disabled={loading.value}
                                        options={state.categoryList}
                                        v-model:value={state.categoryId}
                                        onUpdate:value={async (val: any) => {
@@ -837,13 +858,17 @@ export default defineComponent({
                                              state.categoryName = item.label
                                              state.categoryId = item.value
                                              await setDefaultData("category")
-                                             handleGetList()
+                                             await handleGetList()
+                                             await toDetail()
                                           }
                                        }}
+                                       onUpdate:show={(value: any) => {
+                                          state.categoryShow = value
+                                       }}
                                        trigger="click"
                                        class={"PopSelect"}
                                     >
-                                       <span class={styles.iconTagName}>{state.categoryName}</span>
+                                       <span class={[styles.iconTagName, state.categoryShow && styles.show]}>{state.categoryName}</span>
                                     </NPopselect>
                                  </div>
                               )}
@@ -854,6 +879,7 @@ export default defineComponent({
                                        popperClass="classTypePopper"
                                        v-model={state.subjectId}
                                        height={42}
+                                       // disabled={loading.value}
                                        options={state.subjectList}
                                        placeholder="全部声部"
                                        onChange={handleGetList}
@@ -863,6 +889,7 @@ export default defineComponent({
                                           popperClass="classTypePopper"
                                           v-model={state.levelId}
                                           height={42}
+                                          // disabled={loading.value}
                                           options={state.levelList}
                                           placeholder="级别"
                                           onChange={() => {
@@ -876,6 +903,7 @@ export default defineComponent({
                                           popperClass="classTypePopper"
                                           v-model={state.typeId}
                                           height={42}
+                                          // disabled={loading.value}
                                           options={state.typeList}
                                           propsOpt={{
                                              labelField: "name",
@@ -912,8 +940,9 @@ export default defineComponent({
                               {state.list.map((item: any, index: number) => (
                                  <div
                                     class={[styles.item, index === state.listActive && styles.active]}
-                                    onClick={() => {
+                                    onClick={async () => {
                                        state.listActive = index
+                                       await toDetail()
                                        resetRender()
                                     }}
                                  >
@@ -928,14 +957,9 @@ export default defineComponent({
                                                 ;(e.target as any).dataset.loaded = "true"
                                              }}
                                           />
-                                          {/* <PlayLoading
-                                       class={[
-                                         data.listActive === index &&
-                                         data.playState === 'play'
-                                           ? ''
-                                           : styles.showPlayLoading
-                                       ]}
-                                       /> */}
+                                          <PlayLoading
+                                             class={[state.listActive === index && state.playState === "play" ? "" : styles.showPlayLoading]}
+                                          />
                                        </div>
                                        <div class={styles.title}>
                                           <div class={styles.titleName}>
@@ -949,8 +973,8 @@ export default defineComponent({
                                           onClick={(e: any) => {
                                              e.stopPropagation()
                                              handlePlay(item)
-                                             if (state.listActive === index && state.playState === "play") {
-                                                musicIframeLoad()
+                                             if (state.listActive !== index) {
+                                                resetRender()
                                              }
                                           }}
                                        >
@@ -983,10 +1007,13 @@ export default defineComponent({
                      </div>
                   </div>
                   <div class={styles.rightContainer}>
-                     <i class={styles.leftArrow}></i>
+                     {/* <i class={styles.leftArrow}></i> */}
 
                      <NSpin show={staffLoading.value} stroke="#FF531C">
-                        <div class={styles.musicName}>{activeItem.value.name}</div>
+                        <div class={styles.musicName}>
+                           {activeItem.value.name}
+                           {activeItem.value.musicSheetType === "CONCERT" && state.selectedPartName ? `(${state.selectedPartName})` : ""}
+                        </div>
                         <div class={[styles.staffImgs, !loading.value && !activeItem.value?.id && styles.staffImgsEmpty]}>
                            {state.iframeSrc && activeItem.value?.id && (
                               <iframe
@@ -1013,7 +1040,10 @@ export default defineComponent({
                         }}
                         class={[styles.goBtn]}
                         src={btnSubmit as any}
-                        onClick={() => goToCloud(activeItem.value.id)}
+                        onClick={() => {
+                           handleChangeAudio("pause")
+                           goToCloud(activeItem.value.id, state.partXmlIndex)
+                        }}
                      />
 
                      <div
@@ -1021,15 +1051,21 @@ export default defineComponent({
                         style={{ display: activeItem.value.id && activeItem.value.musicSheetType === "CONCERT" ? "" : "none" }}
                      >
                         <NPopselect
-                           //  options={data.trackList}
-                           trigger="hover"
-                           //  v-model:value={data.musicInstrumentIndex}
-                           onUpdate:value={async () => {
-                              // await analyzeXml();
-                              // //
-                              // musicIfrcmeLoad();
+                           options={partColumns.value}
+                           trigger="click"
+                           v-model:value={state.selectedPartIndex}
+                           scrollable
+                           onUpdate:value={async (value: any) => {
+                              console.log(value, "value")
+                              const item = partColumns.value.find((item: any) => item.value === value)
+                              state.selectedPartIndex = value
+                              state.selectedPartName = item.instrumentName
+                              state.partXmlIndex = item.xmlIndex
+                              nextTick(() => {
+                                 resetRender()
+                              })
                            }}
-                           class={[styles.popSelect]}
+                           class={"PopSelect"}
                         >
                            <img class={styles.transBtn} src={iconTransfer as any} />
                         </NPopselect>
@@ -1050,6 +1086,7 @@ export default defineComponent({
                   }}
                />
             )}
+            <PracticeForm v-model={isPracticeShow.value} practiceUrl={practiceUrl.value} onClose={handlePracticeClose} />
          </NavContainer>
       )
    }

+ 0 - 1
src/views/cloudPractice/component/play-item/index.tsx

@@ -79,7 +79,6 @@ export default defineComponent({
       watch(
          () => props.playState,
          val => {
-            console.log(props.playState, "props.playState")
             if (val === "play") {
                audioRef.value.play().catch(() => {
                   audioRef.value.play()

+ 1 - 1
src/views/cloudPractice/component/play-loading/index.module.scss

@@ -13,7 +13,7 @@
     div {
         width: 5px;
         height: 20px;
-        background: linear-gradient(135deg, #34FFC5 0%, #1BD2FF 100%);
+        background: linear-gradient(135deg, #FF9946 0%, #FF5B20 100%);
         transform-origin: bottom;
         border-radius: 5px 5px 0 0;
         margin: 0 2px;

+ 28 - 7
src/views/cloudPractice/index.module.scss

@@ -123,6 +123,7 @@
          background: url("@/img/cloudPractice/icon-left-active.png");
          background-size: contain;
          color: #fe7846;
+         text-shadow: none;
       }
    }
 
@@ -130,6 +131,8 @@
       height: 100%;
       overflow-x: hidden;
       overflow-y: auto;
+      display: flex;
+      flex-direction: column;
 
       &::-webkit-scrollbar {
          width: 0;
@@ -178,6 +181,12 @@
             background: url("../../img/cloudPractice/icon-arrow-down.png") no-repeat center;
             background-size: contain;
          }
+
+         &.show {
+            &::after {
+               transform: rotate(180deg);
+            }
+         }
       }
    }
 
@@ -191,6 +200,12 @@
       gap: 0 16px;
       display: flex;
       margin-right: 16px;
+
+      :global {
+         .el-cascader .el-input .el-input__inner {
+            color: #994D1C;
+         }
+      }
    }
 
    :global {
@@ -204,6 +219,7 @@
          font-size: 16px;
          .el-input__icon {
             margin-left: 0;
+            color: #994D1C;
          }
       }
       .el-cascader:not(.is-disabled):hover .el-input__wrapper {
@@ -245,9 +261,10 @@
          display: flex;
          align-items: center;
          justify-content: center;
-
+         min-height: auto;
+         flex: 1;
          .empty {
-            margin-top: -180px;
+            margin-top: -100px;
             --el-empty-image-width: 277px;
             :global {
                .el-empty__description p {
@@ -268,9 +285,9 @@
 
          cursor: pointer;
 
-         &:hover {
-            background: #fff3d7;
-         }
+         // &:hover {
+         //    background: #fff3d7;
+         // }
 
          &.active {
             background: #fff3d7;
@@ -305,6 +322,10 @@
             img[data-loaded="true"] {
                opacity: 1;
             }
+
+            .showPlayLoading {
+               opacity: 0;
+            }
          }
 
          .itemInfo {
@@ -385,7 +406,7 @@
       left: 50%;
       bottom: 46px;
       transform: translateX(-50%);
-      height: 102px;
+      height: 94px;
       cursor: pointer;
       transition: all 0.2s ease-in;
    }
@@ -467,7 +488,7 @@
 
    .popSelect {
       font-size: 16px;
-      width: 300px;
+      max-width: 400px;
       max-height: 500px;
       overflow-y: scroll;
       box-shadow: 0px 2px 16px 0px rgba(0, 0, 0, 0.08);

+ 56 - 54
src/views/cloudPractice/instrument.ts

@@ -1,5 +1,7 @@
 // import { isSpecialMark, isSpeedKeyword, isGradientWords, GRADIENT_SPEED_RESET_TAG } from "./speed-tag"
 
+// import { isSpecialMark, isSpeedKeyword, isGradientWords, GRADIENT_SPEED_RESET_TAG } from "./speed-tag"
+
 export class StringUtil {
    public static StringContainsSeparatedWord(str: string, wordRegExString: string, ignoreCase = false): boolean {
       const regExp = new RegExp("( |^)" + wordRegExString + "([ .]|$)", ignoreCase ? "i" : undefined)
@@ -57,9 +59,9 @@ export const onlyVisible = (xml: string, partIndex: number): string => {
    const part: any = parts[0]
    const firstMeasures = [...part.getElementsByTagName("measure")]
    const metronomes = [...part.getElementsByTagName("metronome")]
-   // const words = [...part.getElementsByTagName("words")]
-   // const codas = [...part.getElementsByTagName("coda")]
-   // const rehearsals = [...part.getElementsByTagName("rehearsal")]
+   //  const words = [...part.getElementsByTagName("words")]
+   //  const codas = [...part.getElementsByTagName("coda")]
+   //  const rehearsals = [...part.getElementsByTagName("rehearsal")]
 
    /** 第一分谱如果是约定的配置分谱则跳过 */
    if (partListNames[0]?.toLocaleUpperCase?.() === "COMMON") {
@@ -105,68 +107,68 @@ export const onlyVisible = (xml: string, partIndex: number): string => {
             })
             /** word比较特殊需要精确到note位置 */
             // words.forEach((word) => {
-            //   let text = word.textContent || "";
-            //   text = ["cresc."].includes(text) ? "" : text;
+            //   let text = word.textContent || ""
+            //   text = ["cresc."].includes(text) ? "" : text
             //   if ((isSpecialMark(text) || isSpeedKeyword(text) || isGradientWords(text) || isRepeatWord(text) || GRADIENT_SPEED_RESET_TAG) && text) {
-            //     const wordContainer = word.parentElement?.parentElement;
-            //     const parentMeasure = wordContainer?.parentElement;
-            //     const measureWords = [...(parentMeasure?.childNodes || [])];
-            //     const wordIndex = wordContainer ? measureWords.indexOf(wordContainer) : -1;
+            //     const wordContainer = word.parentElement?.parentElement
+            //     const parentMeasure = wordContainer?.parentElement
+            //     const measureWords = [...(parentMeasure?.childNodes || [])]
+            //     const wordIndex = wordContainer ? measureWords.indexOf(wordContainer) : -1
             //     if (wordContainer && parentMeasure && wordIndex > -1) {
-            //       const index = firstMeasures.indexOf(parentMeasure);
-            //       const activeMeasure = part.getElementsByTagName("measure")[index];
+            //       const index = firstMeasures.indexOf(parentMeasure)
+            //       const activeMeasure = part.getElementsByTagName("measure")[index]
             //       // 找当前小节是否包含word标签
-            //       const _words: any = Array.from(activeMeasure?.getElementsByTagName("words") || []);
+            //       const _words: any = Array.from(activeMeasure?.getElementsByTagName("words") || [])
             //       // 遍历word标签,检查是否和第一小节重复,如果有重复则不平移word
             //       const total = _words.reduce((total: any, _word) => {
             //         if (_word.textContent?.includes(text)) {
-            //           total++;
+            //           total++
             //         }
-            //         return total;
-            //       }, 0);
+            //         return total
+            //       }, 0)
             //       if (total === 0) {
-            //         setElementNoteBefore(wordContainer, parentMeasure, activeMeasure);
+            //         setElementNoteBefore(wordContainer, parentMeasure, activeMeasure)
 
             //       }
             //     }
             //   }
-            // });
+            // })
             /** word比较特殊需要精确到note位置 */
             // codas.forEach((coda) => {
-            //   const wordContainer = coda.parentElement?.parentElement;
-            //   const parentMeasure = wordContainer?.parentElement;
-            //   const measureWords = [...(parentMeasure?.childNodes || [])];
-            //   const wordIndex = wordContainer ? measureWords.indexOf(wordContainer) : -1;
+            //   const wordContainer = coda.parentElement?.parentElement
+            //   const parentMeasure = wordContainer?.parentElement
+            //   const measureWords = [...(parentMeasure?.childNodes || [])]
+            //   const wordIndex = wordContainer ? measureWords.indexOf(wordContainer) : -1
             //   if (wordContainer && parentMeasure && wordIndex > -1) {
-            //     const index = firstMeasures.indexOf(parentMeasure);
-            //     const activeMeasure = part.getElementsByTagName("measure")[index];
+            //     const index = firstMeasures.indexOf(parentMeasure)
+            //     const activeMeasure = part.getElementsByTagName("measure")[index]
 
-            //     setElementNoteBefore(wordContainer, parentMeasure, activeMeasure);
+            //     setElementNoteBefore(wordContainer, parentMeasure, activeMeasure)
 
             //   }
-            // });
+            // })
             // rehearsals.forEach((rehearsal) => {
-            //   const container = rehearsal.parentElement?.parentElement;
-            //   const parentMeasure = container?.parentElement;
+            //   const container = rehearsal.parentElement?.parentElement
+            //   const parentMeasure = container?.parentElement
             //   // console.log(rehearsal)
             //   if (parentMeasure) {
-            //     const index = firstMeasures.indexOf(parentMeasure);
-            //     part.getElementsByTagName("measure")[index]?.appendChild(container.cloneNode(true));
+            //     const index = firstMeasures.indexOf(parentMeasure)
+            //     part.getElementsByTagName("measure")[index]?.appendChild(container.cloneNode(true))
             //     // console.log(index, parentMeasure, firstMeasures.indexOf(parentMeasure))
             //   }
-            // });
+            // })
          } else {
             // words.forEach((word) => {
-            //   const text = word.textContent || "";
+            //   const text = word.textContent || ""
             //   if (isSpeedKeyword(text) && text) {
-            //     const wordContainer = word.parentElement?.parentElement?.parentElement;
+            //     const wordContainer = word.parentElement?.parentElement?.parentElement
             //     if (wordContainer && wordContainer.firstElementChild && wordContainer.firstElementChild !== word) {
-            //       const wordParent = word.parentElement?.parentElement;
-            //       const fisrt = wordContainer.firstElementChild;
-            //       wordContainer.insertBefore(wordParent, fisrt);
+            //       const wordParent = word.parentElement?.parentElement
+            //       const fisrt = wordContainer.firstElementChild
+            //       wordContainer.insertBefore(wordParent, fisrt)
             //     }
             //   }
-            // });
+            // })
          }
 
          // 最后一个小节的结束线元素不在最后 调整
@@ -193,25 +195,25 @@ export const onlyVisible = (xml: string, partIndex: number): string => {
       // 处理装饰音问题
       // const notes = xmlParse.getElementsByTagName("note")
       // const getNextvNoteDuration = (i: number) => {
-      //    let nextNote = notes[i + 1]
-      //    // 可能存在多个装饰音问题,取下一个非装饰音时值
-      //    for (let index = i; index < notes.length; index++) {
-      //       const note = notes[index]
-      //       if (!note.getElementsByTagName("grace")?.length) {
-      //          nextNote = note
-      //          break
-      //       }
-      //    }
-      //    const nextNoteDuration = nextNote?.getElementsByTagName("duration")[0]
-      //    return nextNoteDuration
+      //   let nextNote = notes[i + 1]
+      //   // 可能存在多个装饰音问题,取下一个非装饰音时值
+      //   for (let index = i index < notes.length index++) {
+      //     const note = notes[index]
+      //     if (!note.getElementsByTagName("grace")?.length) {
+      //       nextNote = note
+      //       break
+      //     }
+      //   }
+      //   const nextNoteDuration = nextNote?.getElementsByTagName("duration")[0]
+      //   return nextNoteDuration
       // }
-      // Array.from(notes).forEach((note) => {
-      //    const graces = note.getElementsByTagName("grace")
-      //    if (graces && graces.length) {
-      //       // if (i !== 0) {
-      //       // note.appendChild(getNextvNoteDuration(i)?.cloneNode(true))
-      //       // }
-      //    }
+      // Array.from(notes).forEach((note, i) => {
+      //   const graces = note.getElementsByTagName("grace")
+      //   if (graces && graces.length) {
+      //     // if (i !== 0) {
+      //     // note.appendChild(getNextvNoteDuration(i)?.cloneNode(true))
+      //     // }
+      //   }
       // })
    }
    // console.log(xmlParse)

+ 15 - 7
src/views/cloudPractice/useData.ts

@@ -19,16 +19,24 @@ export const useFunction = () => {
    const loading = ref(false)
 
    /** 跳转云教练 */
-   const goToCloud = (musicId: string) => {
+   const isPracticeShow = ref(false)
+   const practiceUrl = ref("")
+   function goToCloud(musicId: string, partIndex = 0) {
+      //  GYM,GYT,KLX 区分   云教练
       const urlObj = {
-         GYT: `${URL_TEACH_GYT}?id=${musicId}&modelType=practice&modeType=json&Authorization=${getToken()}`,
-         GYM: `${URL_TEACH_GYM}?Authorization=${getToken()}&platform=web&liveConfig=1#/detail/${musicId}?isHideBack=true`,
-         KLX: `${URL_TEACH_KLX}??Authorization=${getToken()}&id=${musicId}&isHideBack=true&limitModel=practice`
+         GYT: `${URL_TEACH_GYT}?id=${musicId}&modelType=practice&modeType=json&part-index=${partIndex}&Authorization=${getToken()}&isYjt=1&&isHideBack=false`,
+         GYM: `${URL_TEACH_GYM}#/detail/${musicId}?Authorization=${getToken()}&platform=web&part-index=${partIndex}&liveConfig=1&isYjt=1`,
+         KLX: `${URL_TEACH_KLX}??Authorization=${getToken()}&id=${musicId}&limitModel=practice&part-index=${partIndex}&isYjt=1`
       }
-      window.open(urlObj[userStoreHook.roles!], "_blank")
+      isPracticeShow.value = true
+      practiceUrl.value = urlObj[userStoreHook.roles!]
+      //window.open(urlObj[userStoreHook.roles!], "_blank")
    }
-
-   return { loading, goToCloud }
+   function handlePracticeClose() {
+      isPracticeShow.value = false
+      practiceUrl.value = ""
+   }
+   return { loading, goToCloud, isPracticeShow, practiceUrl, handlePracticeClose }
 }
 
 // function chunkArray(array: any[], size: number) {

+ 1 - 1
src/views/coursewarePlay/coursewarePlay.vue

@@ -130,7 +130,7 @@ import { ElMessageBox } from "element-plus"
 import courseCollapse from "./components/courseCollapse"
 import pen from "./components/pen"
 import playRecordTime from "./components/playRecordTime"
-import practiceForm from "./components/practiceForm"
+import practiceForm from "@/businessComponents/practiceForm"
 import useDialogConfirm from "@/hooks/useDialogConfirm"
 import { getRecentCourseSchedule_gym } from "@/api/homePage.api"
 import { getToken } from "@/libs/auth"