Browse Source

修改曲谱上传

1
mo 2 years ago
parent
commit
c63557cce4
1 changed files with 330 additions and 269 deletions
  1. 330 269
      src/views/accompaniment/modals/form.vue

+ 330 - 269
src/views/accompaniment/modals/form.vue

@@ -54,15 +54,13 @@
       <el-form-item
         prop="sysMusicScore.isOpenMetronome"
         label="节拍器"
-        :rules="[{required: true, message: '请选择节拍器'}]"
+        :rules="[{ required: true, message: '请选择节拍器' }]"
       >
         <template slot="label">
           <span>
             节拍器
             <el-tooltip placement="top" popper-class="mTooltip">
-              <div slot="content">
-                是否播放系统自带节拍器
-              </div>
+              <div slot="content">是否播放系统自带节拍器</div>
               <i
                 class="el-icon-question"
                 style="font-size: 18px; color: #f56c6c"
@@ -81,26 +79,16 @@
             v-for="item in memberRankList"
             :key="item.id"
           ></el-option> -->
-          <el-option
-            :value="0"
-            label="不播放"
-          ></el-option>
-          <el-option
-            :value="1"
-            label="播放"
-          ></el-option>
+          <el-option :value="0" label="不播放"></el-option>
+          <el-option :value="1" label="播放"></el-option>
         </el-select>
       </el-form-item>
-      <el-form-item
-        label="重复节拍时长"
-      >
+      <el-form-item label="重复节拍时长">
         <template slot="label">
           <span>
             重复节拍时长
             <el-tooltip placement="top" popper-class="mTooltip">
-              <div slot="content">
-                2/4拍类似的节拍器是否重复时长
-              </div>
+              <div slot="content">2/4拍类似的节拍器是否重复时长</div>
               <i
                 class="el-icon-question"
                 style="font-size: 18px; color: #f56c6c"
@@ -113,14 +101,8 @@
           v-model="form.repeatedBeats"
           placeholder="请选择是否重复节拍器时长"
         >
-          <el-option
-            :value="0"
-            label="不重复"
-          ></el-option>
-          <el-option
-            :value="1"
-            label="重复"
-          ></el-option>
+          <el-option :value="0" label="不重复"></el-option>
+          <el-option :value="1" label="重复"></el-option>
         </el-select>
       </el-form-item>
       <!-- <el-form-item
@@ -175,19 +157,77 @@
           <el-radio :label="0">否</el-radio>
         </el-radio-group>
       </el-form-item>
+      <el-form-item :prop="`sysMusicScore.subjectId`" label="声部">
+        <!-- :rules="[{required: true, message: '请选择声部'}]" -->
+        <el-select
+          style="width: 100% !important"
+          v-model="form.sysMusicScore.subjectId"
+          clearable
+          placeholder="请选择声部"
+        >
+          <el-option
+            v-for="item in selects.subjects"
+            :value="item.id"
+            :label="item.name"
+            :key="item.id"
+            :disabled="hasSubjectId(item.id)"
+          ></el-option>
+        </el-select>
+      </el-form-item>
+
+      <el-form-item
+        :prop="`sysMusicScore.isShowFingering`"
+        label="指法展示"
+        :rules="[{ required: true, message: '请选择是否展示指法' }]"
+      >
+        <el-select
+          style="width: 100% !important"
+          v-model="form.sysMusicScore.isShowFingering"
+          placeholder="请选择是否展示指法"
+        >
+          <el-option :value="true" label="是"></el-option>
+          <el-option :value="false" label="否"></el-option>
+        </el-select>
+      </el-form-item>
       <el-form-item
         prop="sysMusicScore.order"
         label="排序"
-        :rules="[{ required: true, message: '请输入排序' }, {
-              pattern: /^([1-9]\d*|[0]{1,1})$/,
-              message: '请输入正确的排序',
-              trigger: 'blur',
-            },]"
+        :rules="[
+          { required: true, message: '请输入排序' },
+          {
+            pattern: /^([1-9]\d*|[0]{1,1})$/,
+            message: '请输入正确的排序',
+            trigger: 'blur',
+          },
+        ]"
       >
         <el-input placeholder="请输入排序" v-model="form.sysMusicScore.order" />
       </el-form-item>
       <el-form-item
-      v-if="form.sysMusicScore.isOpenMetronome ===1"
+        label="MusicXML"
+        :prop="`sysMusicScore.xmlUrl`"
+        :rules="[{ required: true, message: '请选择MusicXML文件' }]"
+      >
+        <singe-file-upload
+          tips="仅支持上传 xml 格式文件"
+          accept=".xml"
+          v-model="form.sysMusicScore.xmlUrl"
+          @inputFile="inputFile"
+          bucket_name="cloud-coach"
+        />
+      </el-form-item>
+      <el-form-item
+        prop="sysMusicScore.speed"
+        label="速度"
+        :rules="[{ required: true, message: '请输入速度' }]"
+      >
+        <el-input
+          placeholder="请输入速度"
+          v-model="form.sysMusicScore.speed"
+        />
+      </el-form-item>
+      <el-form-item
+        v-if="form.sysMusicScore.isOpenMetronome === 1"
         label="伴奏(不含节拍器)"
         prop="sysMusicScore.url"
       >
@@ -199,7 +239,7 @@
         />
       </el-form-item>
       <el-form-item
-      v-else
+        v-else
         label="伴奏(含节拍器)"
         prop="sysMusicScore.metronomeUrl"
       >
@@ -207,45 +247,58 @@
           tips="仅支持上传 mp3/aac 格式音频文件"
           accept=".mp3, .aac"
           v-model="form.sysMusicScore.metronomeUrl"
-            bucket_name="cloud-coach"
+          bucket_name="cloud-coach"
         />
       </el-form-item>
-      <el-form-item
-        label="MIDI"
-        prop="sysMusicScore.midiUrl"
-      >
+      <el-form-item label="MIDI" prop="sysMusicScore.midiUrl">
         <singe-file-upload
           tips="仅支持上传 mid 格式音频文件"
           accept=".mid"
           v-model="form.sysMusicScore.midiUrl"
-            bucket_name="cloud-coach"
+          bucket_name="cloud-coach"
         />
       </el-form-item>
 
       <div v-if="gradual && gradual.length">
-        <el-alert :closable="false" style="margin-bottom: 20px;">识别到共{{gradual.length}}处渐变速度,请输入Dorico对应小节时间信息</el-alert>
-        <div v-for="item in gradual">
+        <el-alert :closable="false" style="margin-bottom: 20px"
+          >识别到共{{
+            gradual.length
+          }}处渐变速度,请输入Dorico对应小节时间信息</el-alert
+        >
+        <div v-for="(item,index) in gradual" :key="index">
           <el-form-item
             :label="item[0].measureIndex + 2 + ' 小节'"
-            :rules="[{required: true, message: '请输入合奏曲目时间'}, {
-              pattern: /^((\d{2}):?){2,3}$/,
-              message: '请输入正确的曲目时间',
-              trigger: 'blur',
-            }]"
+            :rules="[
+              { required: true, message: '请输入合奏曲目时间' },
+              {
+                pattern: /^((\d{2}):?){2,3}$/,
+                message: '请输入正确的曲目时间',
+                trigger: 'blur',
+              },
+            ]"
             :prop="`graduals.${item[0].measureIndex}`"
           >
-            <el-input placeholder="00:00:00" v-model="form.graduals[item[0].measureIndex]"></el-input>
+            <el-input
+              placeholder="00:00:00"
+              v-model="form.graduals[item[0].measureIndex]"
+            ></el-input>
           </el-form-item>
           <el-form-item
             :label="item[1].measureIndex + 2 + ' 小节'"
-            :rules="[{required: true, message: '请输入合奏曲目时间'}, {
-              pattern: /^((\d{2}):?){2,3}$/,
-              message: '请输入正确的曲目时间',
-              trigger: 'blur',
-            }]"
+            :rules="[
+              { required: true, message: '请输入合奏曲目时间' },
+              {
+                pattern: /^((\d{2}):?){2,3}$/,
+                message: '请输入正确的曲目时间',
+                trigger: 'blur',
+              },
+            ]"
             :prop="`graduals.${item[1].measureIndex}`"
           >
-            <el-input placeholder="00:00:00" v-model="form.graduals[item[1].measureIndex]"></el-input>
+            <el-input
+              placeholder="00:00:00"
+              v-model="form.graduals[item[1].measureIndex]"
+            ></el-input>
           </el-form-item>
         </div>
       </div>
@@ -256,73 +309,44 @@
         :key="index"
       >
         <el-row>
-          <el-col :span="12">
+          <!-- <el-col :span="12">
+
+          </el-col> -->
+          <!-- <el-col :span="12">
+
+          </el-col> -->
+          <el-col :span="12" v-if="partListNames.length > 1">
             <el-form-item
-              :prop="`sysMusicScoreAccompaniments.${index}.subjectId`"
-              label="声部"
+              label="所属轨道"
+              :prop="`sysMusicScoreAccompaniments.${index}.track`"
+              :rules="[{ required: true, message: '请选择所属轨道' }]"
             >
-              <!-- :rules="[{required: true, message: '请选择声部'}]" -->
               <el-select
                 style="width: 100% !important"
-                v-model="song.subjectId"
+                v-model="song.track"
                 clearable
-                placeholder="请选择声部"
+                placeholder="请选择轨道"
               >
                 <el-option
-                  v-for="item in selects.subjects"
-                  :value="item.id"
-                  :label="item.name"
-                  :key="item.id"
-                  :disabled="hasSubjectId(item.id)"
+                  v-for="item in partListNames"
+                  :value="item"
+                  :label="item"
+                  :key="item"
+                  :disabled="hasPartName(item)"
                 ></el-option>
               </el-select>
             </el-form-item>
           </el-col>
-          <el-col :span="12">
-            <el-form-item
-              :prop="`sysMusicScoreAccompaniments.${index}.speed`"
-              label="速度"
-              :rules="[{ required: true, message: '请输入速度' }]"
-            >
-              <el-input
-                type="number"
-                placeholder="请输入速度"
-                v-model="song.speed"
-              />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item
-              :prop="`sysMusicScoreAccompaniments.${index}.isShowFingering`"
-              label="指法展示"
-              :rules="[{ required: true, message: '请选择是否展示指法' }]"
-            >
-              <el-select
-                style="width: 100% !important"
-                v-model="song.isShowFingering"
-                placeholder="请选择是否展示指法"
-              >
-                <el-option :value="true" label="是"></el-option>
-                <el-option :value="false" label="否"></el-option>
-              </el-select>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item
-              :prop="`sysMusicScoreAccompaniments.${index}.memo`"
-              label="描述"
-            >
-              <el-input placeholder="请输入描述" v-model="song.memo" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12"  v-if="form.sysMusicScore.isOpenMetronome ===1">
-            <el-form-item
 
+          <el-col :span="12" v-if="form.sysMusicScore.isOpenMetronome === 1">
+            <el-form-item
               label="原音(不含节拍器)"
               :prop="`sysMusicScoreAccompaniments.${index}.mp3Url`"
               :rules="[
                 {
-                  required: form.sysMusicScore.isOpenMetronome ? form.sysMusicScore.playMode === 'MP3' : false,
+                  required: form.sysMusicScore.isOpenMetronome
+                    ? form.sysMusicScore.playMode === 'MP3'
+                    : false,
                   message: '请上传原音(不含节拍器)',
                 },
               ]"
@@ -331,7 +355,7 @@
                 tips="仅支持上传 mp3/aac 格式音频文件"
                 accept=".mp3, .aac"
                 v-model="song.mp3Url"
-                  bucket_name="cloud-coach"
+                bucket_name="cloud-coach"
               />
             </el-form-item>
           </el-col>
@@ -341,7 +365,9 @@
               :prop="`sysMusicScoreAccompaniments.${index}.metronomeMp3Url`"
               :rules="[
                 {
-                  required: form.sysMusicScore.isOpenMetronome ? false : form.sysMusicScore.playMode === 'MP3',
+                  required: form.sysMusicScore.isOpenMetronome
+                    ? false
+                    : form.sysMusicScore.playMode === 'MP3',
                   message: '原音(含节拍器)',
                 },
               ]"
@@ -350,49 +376,28 @@
                 tips="仅支持上传 mp3/aac 格式音频文件"
                 accept=".mp3, .aac"
                 v-model="song.metronomeMp3Url"
-                  bucket_name="cloud-coach"
+                bucket_name="cloud-coach"
               />
             </el-form-item>
           </el-col>
         </el-row>
         <el-row>
-          <el-col :span="12">
+          <el-col :span="24">
             <el-form-item
-              label="MusicXML"
-              :prop="`sysMusicScoreAccompaniments.${index}.xmlUrl`"
-              :rules="[{ required: true, message: '请选择MusicXML文件' }]"
+              :prop="`sysMusicScoreAccompaniments.${index}.memo`"
+              label="描述"
             >
-              <singe-file-upload
-                tips="仅支持上传 xml 格式文件"
-                accept=".xml"
-                v-model="song.xmlUrl"
-                @inputFile="inputFile"
-                  bucket_name="cloud-coach"
+              <el-input
+                type="textarea"
+                :rows="2"
+                placeholder="请输入描述"
+                v-model="song.memo"
               />
             </el-form-item>
           </el-col>
-          <el-col :span="12" v-if="partListNames.length > 1">
-            <el-form-item
-              label="所属轨道"
-              :prop="`sysMusicScoreAccompaniments.${index}.track`"
-              :rules="[{ required: true, message: '请选择所属轨道' }]"
-            >
-              <el-select
-                style="width: 100% !important"
-                v-model="song.track"
-                clearable
-                placeholder="请选择轨道"
-              >
-                <el-option
-                  v-for="item in partListNames"
-                  :value="item"
-                  :label="item"
-                  :key="item"
-                  :disabled="hasPartName(item)"
-                ></el-option>
-              </el-select>
-            </el-form-item>
-          </el-col>
+          <!-- <el-col :span="12">
+
+          </el-col> -->
         </el-row>
         <el-button
           class="file-remove"
@@ -417,18 +422,18 @@
   </div>
 </template>
 <script>
-import axios from 'axios'
+import axios from "axios";
 import { Add, Update, queryPageSysExam, queryTree } from "../api";
 import { getAllmemberRank } from "@/views/resetTeaming/api";
 const initailExtConfigJson = {
-  repeatedBeats: 0
-}
+  repeatedBeats: 0,
+};
 export default {
   props: ["detail", "type"],
   data() {
     return {
       gradual: null,
-      xmlFirstSpeed: '',
+      xmlFirstSpeed: "",
       partListNames: [],
       tree: [],
       extConfigJson: {},
@@ -451,7 +456,11 @@ export default {
           renderFrom: "",
           playMode: "MP3",
           enableEvaluation: 1,
-          extConfigJson: "{}"
+          extConfigJson: "{}",
+          subjectId:null,
+          speed:'',
+          xmlUrl:null,
+          isShowFingering:null,
         },
         sysMusicScoreAccompaniments: [
           {
@@ -461,7 +470,7 @@ export default {
             xmlUrl: "",
             isShowFingering: true,
             mome: "",
-            track: ""
+            track: "",
           },
         ],
         delExamSongAccompanimentIds: [],
@@ -481,12 +490,12 @@ export default {
       try {
         this.extConfigJson = JSON.parse(this.detail.extConfigJson);
       } catch (error) {
-        this.extConfigJson = {...initailExtConfigJson}
+        this.extConfigJson = { ...initailExtConfigJson };
       }
       this.form.repeatedBeats = this.extConfigJson.repeatedBeats;
       this.form.graduals = this.extConfigJson.gradualTimes || {};
       this.$set(this.form, "sysMusicScore", {
-        isOpenMetronome:Number(this.detail.isOpenMetronome),
+        isOpenMetronome: Number(this.detail.isOpenMetronome),
         name: this.detail.name,
         url: this.detail.url,
         midiUrl: this.detail.midiUrl,
@@ -506,9 +515,11 @@ export default {
       } else {
         this.form.rankIdType = 0;
       }
-      const xmlres = await axios(this.detail.xmlUrl)
-      this.gradual = getGradualLengthByXml(xmlres.data).filter(item => item.length === 2)
-      this.partListNames = this.getPartListNames(xmlres.data)
+      const xmlres = await axios(this.detail.xmlUrl);
+      this.gradual = getGradualLengthByXml(xmlres.data).filter(
+        (item) => item.length === 2
+      );
+      this.partListNames = this.getPartListNames(xmlres.data);
       this.FeatchDetailList();
     } else {
       // 新增条件下默认设置为收费
@@ -518,40 +529,65 @@ export default {
   },
   methods: {
     getPartListNames(xml) {
-      if (!xml) return []
-      const xmlParse = new DOMParser().parseFromString(xml, 'text/xml')
-      const partList = xmlParse.getElementsByTagName('part-list')?.[0]?.getElementsByTagName('score-part') || []
-      const partListNames = Array.from(partList).map(item => item.getElementsByTagName('part-name')?.[0].textContent || '')
-      this.xmlFirstSpeed = xmlParse.getElementsByTagName('per-minute')?.[0]?.textContent || ''
-      return partListNames.filter(text => text.toLocaleUpperCase() !== 'COMMON')
+      if (!xml) return [];
+      const xmlParse = new DOMParser().parseFromString(xml, "text/xml");
+      const partList =
+        xmlParse
+          .getElementsByTagName("part-list")?.[0]
+          ?.getElementsByTagName("score-part") || [];
+      const partListNames = Array.from(partList).map(
+        (item) => item.getElementsByTagName("part-name")?.[0].textContent || ""
+      );
+
+      this.xmlFirstSpeed =
+        xmlParse.getElementsByTagName("per-minute")?.[0]?.textContent || "";
+
+      // this.form.sysMusicScore.speed = this.xmlFirstSpeed;
+      this.$set(this.form.sysMusicScore,'speed',this.xmlFirstSpeed)
+      return partListNames.filter(
+        (text) => text.toLocaleUpperCase() !== "COMMON"
+      );
     },
     inputFile(file) {
-      const xmlRead = new FileReader()
-      xmlRead.onload = res => {
-        this.partListNames = this.getPartListNames(res.target.result)
-        this.gradual = getGradualLengthByXml(res.target.result).filter(item => item.length === 2)
+      const xmlRead = new FileReader();
+      xmlRead.onload = (res) => {
+        this.partListNames = this.getPartListNames(res.target.result);
+        this.gradual = getGradualLengthByXml(res.target.result).filter(
+          (item) => item.length === 2
+        );
+
+
         for (let j = 0; j < this.form.sysMusicScoreAccompaniments.length; j++) {
-          this.form.sysMusicScoreAccompaniments[j].track =  this.partListNames[j]
+          this.form.sysMusicScoreAccompaniments[j].track =
+            this.partListNames[j];
           if (!this.form.sysMusicScoreAccompaniments[j].speed) {
-            this.form.sysMusicScoreAccompaniments[j].speed = this.xmlFirstSpeed
+            this.form.sysMusicScoreAccompaniments[j].speed = this.xmlFirstSpeed;
           }
-          this.$set(this.form, 'sysMusicScoreAccompaniments', this.form.sysMusicScoreAccompaniments)
+          this.$set(
+            this.form,
+            "sysMusicScoreAccompaniments",
+            this.form.sysMusicScoreAccompaniments
+          );
         }
-        for (let index = this.form.sysMusicScoreAccompaniments.length; index < this.partListNames.length; index++) {
-          const part = this.partListNames[index]
+        for (
+          let index = this.form.sysMusicScoreAccompaniments.length;
+          index < this.partListNames.length;
+          index++
+        ) {
+          const part = this.partListNames[index];
           const sysData = {
             ...this.form.sysMusicScoreAccompaniments[0],
             metronomeMp3Url: "",
             mp3Url: "",
             track: part,
-          }
+          };
           if (!sysData.speed) {
-            sysData.speed = this.xmlFirstSpeed
+            sysData.speed = this.xmlFirstSpeed;
           }
-          this.createSys(sysData)
+          this.createSys(sysData);
         }
-      }
-      xmlRead.readAsText(file.raw)
+      };
+      xmlRead.readAsText(file.raw);
     },
     rankChange(value) {
       if (value) {
@@ -595,15 +631,18 @@ export default {
       try {
         const res = await queryTree();
         this.tree = res.data;
-        this.formatTree(this.tree)
+        this.formatTree(this.tree);
       } catch (error) {}
     },
-    formatTree(data){
-      for(let i of data) {
-        if(i.sysMusicScoreCategoriesList && i.sysMusicScoreCategoriesList.length > 0) {
-          this.formatTree(i.sysMusicScoreCategoriesList, i)
+    formatTree(data) {
+      for (let i of data) {
+        if (
+          i.sysMusicScoreCategoriesList &&
+          i.sysMusicScoreCategoriesList.length > 0
+        ) {
+          this.formatTree(i.sysMusicScoreCategoriesList, i);
         } else {
-          i.sysMusicScoreCategoriesList = null
+          i.sysMusicScoreCategoriesList = null;
         }
       }
     },
@@ -618,17 +657,29 @@ export default {
             item.subjectId = null;
           }
         });
+      if(result.length >0){
+        console.log(result[0].speed)
+        this.$set(this.form.sysMusicScore, "subjectId", result[0].subjectId);
+        this.$set(this.form.sysMusicScore, "speed", result[0].speed);
+        this.$set(this.form.sysMusicScore, "xmlUrl", result[0].xmlUrl);
+        this.$set(this.form.sysMusicScore, "isShowFingering", result[0].isShowFingering);
+      }
         this.$set(this.form, "sysMusicScoreAccompaniments", result);
       } catch (error) {}
     },
     createSys(initData) {
-      this.form.sysMusicScoreAccompaniments.push(Object.assign({
-        subjectId: "",
-        speed: "",
-        mp3Url: "",
-        xmlUrl: "",
-        track: "",
-      }, (initData || {})));
+      this.form.sysMusicScoreAccompaniments.push(
+        Object.assign(
+          {
+            subjectId: "",
+            speed: "",
+            mp3Url: "",
+            xmlUrl: "",
+            track: "",
+          },
+          initData || {}
+        )
+      );
     },
     async removeSys(index) {
       try {
@@ -661,6 +712,13 @@ export default {
     async submit() {
       this.$refs.form.validate(async (valid) => {
         if (valid) {
+          // 提交前平铺 速度,声部,XML,isShowFingering
+          this.form.sysMusicScoreAccompaniments.forEach(item=>{
+            item.speed = this.form.sysMusicScore.speed
+            item.subjectId = this.form.sysMusicScore.subjectId
+            item.spexmlUrled =  this.form.sysMusicScore.spexmlUrled
+            item.isShowFingering =  this.form.sysMusicScore.isShowFingering
+          })
           if (!this.detail) {
             await Add({
               ...this.form,
@@ -710,43 +768,46 @@ export default {
  * @param ele 指定元素
  * @param selectors 选择器
  */
- const getNextNote = (ele, selectors) => {
-  let index = 0
-  const parentEle = ele.closest(selectors)
-  let pointer = parentEle
-  const measure = parentEle?.closest('measure')
-  let siblingNote = null
+const getNextNote = (ele, selectors) => {
+  let index = 0;
+  const parentEle = ele.closest(selectors);
+  let pointer = parentEle;
+  const measure = parentEle?.closest("measure");
+  let siblingNote = null;
   // 查找到相邻的第一个note元素
   while (!siblingNote && index < (measure?.childNodes.length || 50)) {
-    index++
-    if (pointer?.nextElementSibling?.tagName === 'note') {
-      siblingNote = pointer?.nextElementSibling
+    index++;
+    if (pointer?.nextElementSibling?.tagName === "note") {
+      siblingNote = pointer?.nextElementSibling;
     }
-    pointer = pointer?.nextElementSibling
+    pointer = pointer?.nextElementSibling;
   }
-  return siblingNote
-}
+  return siblingNote;
+};
 
 export const onlyVisible = (xml, partIndex) => {
-  if (!xml) return ''
-  const xmlParse = new DOMParser().parseFromString(xml, 'text/xml')
-  const partList = xmlParse.getElementsByTagName('part-list')?.[0]?.getElementsByTagName('score-part') || []
+  if (!xml) return "";
+  const xmlParse = new DOMParser().parseFromString(xml, "text/xml");
+  const partList =
+    xmlParse
+      .getElementsByTagName("part-list")?.[0]
+      ?.getElementsByTagName("score-part") || [];
   // const partListNames = Array.from(partList).map(item => item.getElementsByTagName('part-name')?.[0].textContent || '')
-  const parts = xmlParse.getElementsByTagName('part')
+  const parts = xmlParse.getElementsByTagName("part");
   // const firstTimeInfo = parts[0]?.getElementsByTagName('metronome')[0]?.parentElement?.parentElement?.cloneNode(true)
   // const firstMeasures = [...Array.from(parts[0]?.getElementsByTagName('measure') || [])]
   // const metronomes = [...Array.from(parts[0]?.getElementsByTagName('metronome') || [])]
   // const words = [...Array.from(parts[0]?.getElementsByTagName('words') || [])]
   // const codas = [...Array.from(parts[0]?.getElementsByTagName('coda') || [])]
   // const rehearsals = [...Array.from(parts[0]?.getElementsByTagName('rehearsal') || [])]
-  const visiblePartInfo = partList[partIndex]
+  const visiblePartInfo = partList[partIndex];
   // console.log(visiblePartInfo, partIndex)
   // state.partListNames = partListNames
   if (visiblePartInfo) {
-    const id = visiblePartInfo.getAttribute('id')
-    Array.from(parts).forEach(part => {
-      if (part && part.getAttribute('id') !== id) {
-        part.parentNode?.removeChild(part)
+    const id = visiblePartInfo.getAttribute("id");
+    Array.from(parts).forEach((part) => {
+      if (part && part.getAttribute("id") !== id) {
+        part.parentNode?.removeChild(part);
         // 不等于第一行才添加避免重复添加
       } else {
         // words.forEach(word => {
@@ -763,101 +824,101 @@ export const onlyVisible = (xml, partIndex) => {
       }
 
       // 最后一个小节的结束线元素不在最后 调整
-      if (part && part.getAttribute('id') === id) {
-        const barlines = part.getElementsByTagName('barline')
-        const lastParent = barlines[barlines.length - 1]?.parentElement
-        if (lastParent?.lastElementChild?.tagName !== 'barline') {
-          const children = lastParent?.children || []
+      if (part && part.getAttribute("id") === id) {
+        const barlines = part.getElementsByTagName("barline");
+        const lastParent = barlines[barlines.length - 1]?.parentElement;
+        if (lastParent?.lastElementChild?.tagName !== "barline") {
+          const children = lastParent?.children || [];
           for (let el of children) {
-            if (el.tagName === 'barline') {
+            if (el.tagName === "barline") {
               // 将结束线元素放到最后
-              lastParent?.appendChild(el)
-              break
+              lastParent?.appendChild(el);
+              break;
             }
           }
         }
       }
-    })
-    Array.from(partList).forEach(part => {
-      if (part && part.getAttribute('id') !== id) {
-        part.parentNode?.removeChild(part)
+    });
+    Array.from(partList).forEach((part) => {
+      if (part && part.getAttribute("id") !== id) {
+        part.parentNode?.removeChild(part);
       }
-    })
+    });
     // 处理装饰音问题
-    const notes = xmlParse.getElementsByTagName('note')
+    const notes = xmlParse.getElementsByTagName("note");
     const getNextvNoteDuration = (i) => {
-      let nextNote = notes[i + 1]
+      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
+        if (!note.getElementsByTagName("grace")?.length) {
+          nextNote = note;
+          break;
         }
       }
-      const nextNoteDuration = nextNote?.getElementsByTagName('duration')[0]
-      return nextNoteDuration
-    }
+      const nextNoteDuration = nextNote?.getElementsByTagName("duration")[0];
+      return nextNoteDuration;
+    };
     Array.from(notes).forEach((note, i) => {
-      const graces = note.getElementsByTagName('grace')
+      const graces = note.getElementsByTagName("grace");
       if (graces && graces.length) {
         // if (i !== 0) {
-          note.appendChild(getNextvNoteDuration(i)?.cloneNode(true))
+        note.appendChild(getNextvNoteDuration(i)?.cloneNode(true));
         // }
       }
-    })
+    });
   }
   // console.log(new XMLSerializer().serializeToString(xmlParse))
-  return new XMLSerializer().serializeToString(xmlParse)
-}
+  return new XMLSerializer().serializeToString(xmlParse);
+};
 
 const speedInfo = {
-  'rall.': 1.333333333,
-  'poco rit.': 1.333333333,
-  'rit.': 1.333333333,
-  'molto rit.': 1.333333333,
-  'molto rall': 1.333333333,
+  "rall.": 1.333333333,
+  "poco rit.": 1.333333333,
+  "rit.": 1.333333333,
+  "molto rit.": 1.333333333,
+  "molto rall": 1.333333333,
   lentando: 1.333333333,
   allargando: 1.333333333,
   morendo: 1.333333333,
-  'accel.': 0.8,
+  "accel.": 0.8,
   calando: 2,
-  'poco accel.': 0.8,
-}
+  "poco accel.": 0.8,
+};
 
 /**
  * 按照xml进行减慢速度的计算
  * @param xml 始终按照第一分谱进行减慢速度的计算
  */
- export function getGradualLengthByXml (xml) {
-  const firstPartXml = onlyVisible(xml, 0)
-  const xmlParse = new DOMParser().parseFromString(firstPartXml, 'text/xml')
-  const measures = Array.from(xmlParse.querySelectorAll('measure'))
-  const notes = Array.from(xmlParse.querySelectorAll('note'))
-  const words = Array.from(xmlParse.querySelectorAll('words'))
-  const metronomes = Array.from(xmlParse.querySelectorAll('metronome'))
+export function getGradualLengthByXml(xml) {
+  const firstPartXml = onlyVisible(xml, 0);
+  const xmlParse = new DOMParser().parseFromString(firstPartXml, "text/xml");
+  const measures = Array.from(xmlParse.querySelectorAll("measure"));
+  const notes = Array.from(xmlParse.querySelectorAll("note"));
+  const words = Array.from(xmlParse.querySelectorAll("words"));
+  const metronomes = Array.from(xmlParse.querySelectorAll("metronome"));
 
-  const eles = []
+  const eles = [];
 
   for (const ele of [...words, ...metronomes]) {
-    const note = getNextNote(ele, 'direction')
+    const note = getNextNote(ele, "direction");
     // console.log(ele, note)
     if (note) {
-      const measure = note?.closest('measure')
-      const measureNotes = Array.from(measure.querySelectorAll('note'))
+      const measure = note?.closest("measure");
+      const measureNotes = Array.from(measure.querySelectorAll("note"));
 
       const noteInMeasureIndex = Array.from(measure.childNodes)
-        .filter((item) => item.nodeName === 'note')
-        .findIndex((item) => item === note)
+        .filter((item) => item.nodeName === "note")
+        .findIndex((item) => item === note);
 
-      let allDuration = 0
-      let leftDuration = 0
+      let allDuration = 0;
+      let leftDuration = 0;
       for (let i = 0; i < measureNotes.length; i++) {
-        const n = measureNotes[i]
-        const duration = +(n.querySelector('duration')?.textContent || '0')
-        allDuration += duration
+        const n = measureNotes[i];
+        const duration = +(n.querySelector("duration")?.textContent || "0");
+        allDuration += duration;
         if (i < noteInMeasureIndex) {
-          leftDuration = allDuration
+          leftDuration = allDuration;
         }
       }
       eles.push({
@@ -869,16 +930,16 @@ const speedInfo = {
         type: ele.tagName,
         allDuration,
         leftDuration,
-      })
+      });
     }
   }
 
-  const gradualNotes = []
-  eles.sort((a, b) => a.index - b.index)
-  const keys = Object.keys(speedInfo).map(w => w.toLocaleLowerCase())
+  const gradualNotes = [];
+  eles.sort((a, b) => a.index - b.index);
+  const keys = Object.keys(speedInfo).map((w) => w.toLocaleLowerCase());
   for (const ele of eles) {
-    const textContent = ele.textContent?.toLocaleLowerCase().trim()
-    if (ele.type === 'words' && keys.includes(textContent)) {
+    const textContent = ele.textContent?.toLocaleLowerCase().trim();
+    if (ele.type === "words" && keys.includes(textContent)) {
       gradualNotes.push([
         {
           start: ele.index,
@@ -888,13 +949,13 @@ const speedInfo = {
           leftDuration: ele.leftDuration,
           type: textContent,
         },
-      ])
+      ]);
     }
     if (
-      ele.type === 'metronome' ||
-      (ele.type === 'words' && textContent === 'a tempo')
+      ele.type === "metronome" ||
+      (ele.type === "words" && textContent === "a tempo")
     ) {
-      const indexOf = gradualNotes.findIndex((item) => item.length === 1)
+      const indexOf = gradualNotes.findIndex((item) => item.length === 1);
       if (indexOf > -1 && ele.index > gradualNotes[indexOf]?.[0].start) {
         gradualNotes[indexOf][1] = {
           start: ele.index,
@@ -903,11 +964,11 @@ const speedInfo = {
           allDuration: ele.allDuration,
           leftDuration: ele.leftDuration,
           type: textContent,
-        }
+        };
       }
     }
   }
-  return gradualNotes
+  return gradualNotes;
 }
 </script>
 <style lang="less" scoped>