| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026 | 
							- <template>
 
-   <div>
 
-     <el-form ref="form" :model="form" label-width="150px">
 
-       <el-form-item
 
-         prop="sysMusicScore.name"
 
-         label="曲名"
 
-         :rules="[{ required: true, message: '请输入曲名' }]"
 
-       >
 
-         <el-input placeholder="请输入曲名" v-model="form.sysMusicScore.name" />
 
-       </el-form-item>
 
-       <el-form-item
 
-         prop="sysMusicScore.musicScoreCategoriesId"
 
-         label="分类"
 
-         :rules="[{ required: true, message: '请选择分类' }]"
 
-       >
 
-         <el-cascader
 
-           v-model="form.sysMusicScore.musicScoreCategoriesId"
 
-           style="width: 100%"
 
-           :options="tree"
 
-           placeholder="请选择分类"
 
-           :props="treeProps"
 
-         ></el-cascader>
 
-         <!-- <el-select style="width: 100%!important;" v-model="form.sysMusicScore.musicScoreCategoriesId" placeholder="请选择声部">
 
-           <el-option
 
-             v-for="item in selects.subjects"
 
-             :value="item.id"
 
-             :label="item.name"
 
-             :key="item.id"
 
-           ></el-option>
 
-         </el-select> -->
 
-       </el-form-item>
 
-       <!-- 是否收费  免费  收费 -->
 
-       <el-form-item
 
-         prop="rankIdType"
 
-         label="是否收费"
 
-         :rules="[{ required: true, message: '请选择是否收费' }]"
 
-       >
 
-         <el-select
 
-           style="width: 100% !important"
 
-           v-model="form.rankIdType"
 
-           placeholder="请选择是否收费"
 
-           @change="rankChange"
 
-         >
 
-           <!-- <el-option
 
-             :value="item.id"
 
-             :label="item.name"
 
-             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-select>
 
-       </el-form-item>
 
-       <el-form-item
 
-         prop="sysMusicScore.isOpenMetronome"
 
-         label="节拍器"
 
-         :rules="[{ required: true, message: '请选择节拍器' }]"
 
-       >
 
-         <template slot="label">
 
-           <span>
 
-             节拍器
 
-             <el-tooltip placement="top" popper-class="mTooltip">
 
-               <div slot="content">是否播放系统自带节拍器</div>
 
-               <i
 
-                 class="el-icon-question"
 
-                 style="font-size: 18px; color: #f56c6c"
 
-               ></i>
 
-             </el-tooltip>
 
-           </span>
 
-         </template>
 
-         <el-select
 
-           style="width: 100% !important"
 
-           v-model="form.sysMusicScore.isOpenMetronome"
 
-           placeholder="请选择节拍器"
 
-         >
 
-           <!-- <el-option
 
-             :value="item.id"
 
-             :label="item.name"
 
-             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-select>
 
-       </el-form-item>
 
-       <el-form-item label="重复节拍时长">
 
-         <template slot="label">
 
-           <span>
 
-             重复节拍时长
 
-             <el-tooltip placement="top" popper-class="mTooltip">
 
-               <div slot="content">2/4拍类似的节拍器是否重复时长</div>
 
-               <i
 
-                 class="el-icon-question"
 
-                 style="font-size: 18px; color: #f56c6c"
 
-               ></i>
 
-             </el-tooltip>
 
-           </span>
 
-         </template>
 
-         <el-select
 
-           style="width: 100% !important"
 
-           v-model="form.repeatedBeats"
 
-           placeholder="请选择是否重复节拍器时长"
 
-         >
 
-           <el-option :value="0" label="不重复"></el-option>
 
-           <el-option :value="1" label="重复"></el-option>
 
-         </el-select>
 
-       </el-form-item>
 
-       <!-- <el-form-item
 
-         prop="sysMusicScore.clientType"
 
-         label="客户端类型"
 
-         :rules="[{ required: true, message: '请选择客户端类型' }]"
 
-       >
 
-         <el-select
 
-           style="width: 100% !important"
 
-           v-model="form.sysMusicScore.clientType"
 
-           placeholder="请选择客户端类型"
 
-         >
 
-           <el-option value="NETWORK_ROOM" label="网络教室"></el-option>
 
-           <el-option value="SMART_PRACTICE" label="云教练"></el-option>
 
-         </el-select>
 
-       </el-form-item> -->
 
-       <!-- <el-form-item
 
-         prop="sysMusicScore.renderFrom"
 
-         label="渲染模式"
 
-         :rules="[{ required: true, message: '请选择渲染模式' }]"
 
-       >
 
-         <el-select
 
-           style="width: 100% !important"
 
-           v-model="form.sysMusicScore.renderFrom"
 
-           placeholder="请选择渲染模式"
 
-         >
 
-           <el-option value="H5" label="H5"></el-option>
 
-           <el-option value="APP" label="原生"></el-option>
 
-         </el-select>
 
-       </el-form-item> -->
 
-       <el-form-item
 
-         prop="sysMusicScore.playMode"
 
-         label="播放模式"
 
-         :rules="[{ required: true, message: '请选择播放模式' }]"
 
-       >
 
-         <el-select
 
-           style="width: 100% !important"
 
-           v-model="form.sysMusicScore.playMode"
 
-           placeholder="请选择播放模式"
 
-         >
 
-           <el-option value="MP3" label="MP3播放"></el-option>
 
-           <el-option value="XML" label="XML播放"></el-option>
 
-         </el-select>
 
-       </el-form-item>
 
-       <el-form-item
 
-         prop="sysMusicScore.enableEvaluation"
 
-         label="支持评测"
 
-         :rules="[{ required: true, message: '请选择支持评测' }]"
 
-       >
 
-         <el-radio-group v-model="form.sysMusicScore.enableEvaluation">
 
-           <el-radio :label="1">是</el-radio>
 
-           <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',
 
-           },
 
-         ]"
 
-       >
 
-         <el-input placeholder="请输入排序" v-model="form.sysMusicScore.order" />
 
-       </el-form-item>
 
-       <el-form-item
 
-         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"
 
-       >
 
-         <singe-file-upload
 
-           tips="仅支持上传 mp3/aac 格式音频文件"
 
-           accept=".mp3, .aac"
 
-           v-model="form.sysMusicScore.url"
 
-           bucket_name="cloud-coach"
 
-         />
 
-       </el-form-item>
 
-       <el-form-item
 
-         v-else
 
-         label="伴奏(含节拍器)"
 
-         prop="sysMusicScore.metronomeUrl"
 
-       >
 
-         <singe-file-upload
 
-           tips="仅支持上传 mp3/aac 格式音频文件"
 
-           accept=".mp3, .aac"
 
-           v-model="form.sysMusicScore.metronomeUrl"
 
-           bucket_name="cloud-coach"
 
-         />
 
-       </el-form-item>
 
-       <el-form-item label="MIDI" prop="sysMusicScore.midiUrl">
 
-         <singe-file-upload
 
-           tips="仅支持上传 mid 格式音频文件"
 
-           accept=".mid"
 
-           v-model="form.sysMusicScore.midiUrl"
 
-           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 class="gradual-item" v-for="(item,index) in gradual" :key="index">
 
-           {{item[0].type}}
 
-           <el-form-item
 
-             :label="item[0].measureIndex + 2 + ' 小节'"
 
-             :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-form-item>
 
-           <el-form-item
 
-             :label="item[1].measureIndex + 2 + ' 小节'"
 
-             :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-form-item>
 
-         </div>
 
-       </div>
 
-       <div
 
-         class="files"
 
-         v-for="(song, index) in form.sysMusicScoreAccompaniments"
 
-         :key="index"
 
-       >
 
-         <el-row>
 
-           <!-- <el-col :span="12">
 
-           </el-col> -->
 
-           <!-- <el-col :span="12">
 
-           </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" v-if="form.sysMusicScore.isOpenMetronome === 1">
 
-             <el-form-item
 
-               label="原音(不含节拍器)"
 
-               :prop="`sysMusicScoreAccompaniments.${index}.mp3Url`"
 
-               :rules="[
 
-                 {
 
-                   required: form.sysMusicScore.isOpenMetronome
 
-                     ? form.sysMusicScore.playMode === 'MP3'
 
-                     : false,
 
-                   message: '请上传原音(不含节拍器)',
 
-                 },
 
-               ]"
 
-             >
 
-               <singe-file-upload
 
-                 tips="仅支持上传 mp3/aac 格式音频文件"
 
-                 accept=".mp3, .aac"
 
-                 v-model="song.mp3Url"
 
-                 bucket_name="cloud-coach"
 
-               />
 
-             </el-form-item>
 
-           </el-col>
 
-           <el-col :span="12" v-else>
 
-             <el-form-item
 
-               label="原音(含节拍器)"
 
-               :prop="`sysMusicScoreAccompaniments.${index}.metronomeMp3Url`"
 
-               :rules="[
 
-                 {
 
-                   required: form.sysMusicScore.isOpenMetronome
 
-                     ? false
 
-                     : form.sysMusicScore.playMode === 'MP3',
 
-                   message: '原音(含节拍器)',
 
-                 },
 
-               ]"
 
-             >
 
-               <singe-file-upload
 
-                 tips="仅支持上传 mp3/aac 格式音频文件"
 
-                 accept=".mp3, .aac"
 
-                 v-model="song.metronomeMp3Url"
 
-                 bucket_name="cloud-coach"
 
-               />
 
-             </el-form-item>
 
-           </el-col>
 
-         </el-row>
 
-         <el-row>
 
-           <el-col :span="24">
 
-             <el-form-item
 
-               :prop="`sysMusicScoreAccompaniments.${index}.memo`"
 
-               label="描述"
 
-             >
 
-               <el-input
 
-                 type="textarea"
 
-                 :rows="2"
 
-                 placeholder="请输入描述"
 
-                 v-model="song.memo"
 
-               />
 
-             </el-form-item>
 
-           </el-col>
 
-           <!-- <el-col :span="12">
 
-           </el-col> -->
 
-         </el-row>
 
-         <el-button
 
-           class="file-remove"
 
-           type="text"
 
-           @click="removeSys(index)"
 
-           :disabled="form.sysMusicScoreAccompaniments.length == 1"
 
-           >删除</el-button
 
-         >
 
-       </div>
 
-       <el-button
 
-         @click="createSys"
 
-         type="info"
 
-         style="width: 100%; margin-bottom: 20px"
 
-         plain
 
-         >添加原音</el-button
 
-       >
 
-       <div class="btns">
 
-         <el-button type="primary" @click="submit">提交</el-button>
 
-         <el-button @click="$listeners.close">取消</el-button>
 
-       </div>
 
-     </el-form>
 
-   </div>
 
- </template>
 
- <script>
 
- import axios from "axios";
 
- import { Add, Update, queryPageSysExam, queryTree } from "../api";
 
- import { getAllmemberRank } from "@/views/resetTeaming/api";
 
- const initailExtConfigJson = {
 
-   repeatedBeats: 0,
 
- };
 
- export default {
 
-   props: ["detail", "type"],
 
-   data() {
 
-     return {
 
-       gradual: null,
 
-       xmlFirstSpeed: "",
 
-       partListNames: [],
 
-       tree: [],
 
-       extConfigJson: {},
 
-       memberRankList: [], // 会员列表
 
-       form: {
 
-         graduals: {},
 
-         rankIdType: 0, // 收费会员类型 默认免费
 
-         repeatedBeats: 0, // 重复节拍
 
-         sysMusicScore: {
 
-           isOpenMetronome: 0, // 是否开启节拍器 默认关闭
 
-           name: "",
 
-           rankIds: "", // 收费会员编号
 
-           url: "",
 
-           metronomeUrl: "",
 
-           midiUrl: "",
 
-           order: 0,
 
-           musicScoreCategoriesId: [],
 
-           // 兼容之前数据,默认选择云教练
 
-           clientType: "SMART_PRACTICE",
 
-           renderFrom: "",
 
-           playMode: "MP3",
 
-           enableEvaluation: 1,
 
-           extConfigJson: "{}",
 
-           subjectId:null,
 
-           speed:'',
 
-           xmlUrl:null,
 
-           isShowFingering:true,
 
-         },
 
-         sysMusicScoreAccompaniments: [
 
-           {
 
-             subjectId: "",
 
-             speed: "",
 
-             mp3Url: "",
 
-             xmlUrl: "",
 
-             isShowFingering: true,
 
-             memo: "",
 
-             track: "",
 
-           },
 
-         ],
 
-         delExamSongAccompanimentIds: [],
 
-       },
 
-       treeProps: {
 
-         value: "id",
 
-         label: "name",
 
-         children: "sysMusicScoreCategoriesList",
 
-       },
 
-     };
 
-   },
 
-   async mounted() {
 
-     this.$store.dispatch("setSubjects");
 
-     await this.FetchTree();
 
-     await this.memberRank();
 
-     if (this.detail) {
 
-       try {
 
-         this.extConfigJson = JSON.parse(this.detail.extConfigJson);
 
-       } catch (error) {
 
-         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),
 
-         name: this.detail.name,
 
-         url: this.detail.url,
 
-         midiUrl: this.detail.midiUrl,
 
-         rankIds: this.detail.rankIds,
 
-         order: this.detail.order,
 
-         clientType: this.detail.clientType,
 
-         enableEvaluation: +this.detail.enableEvaluation,
 
-         metronomeUrl: this.detail.metronomeUrl,
 
-         renderFrom: this.detail.renderFrom,
 
-         playMode: this.detail.playMode,
 
-         musicScoreCategoriesId: this.detail.categoriesId
 
-           ? this.formatParentId(this.detail.categoriesId, this.tree)
 
-           : [],
 
-       });
 
-       if (this.detail.rankIds) {
 
-         this.form.rankIdType = 1;
 
-       } else {
 
-         this.form.rankIdType = 0;
 
-       }
 
-       const xmlres = await axios(this.detail.xmlUrl);
 
-       this.gradual = getGradualLengthByXml(xmlres.data).filter(
 
-         (item) => item.length === 2
 
-       );
 
-       console.log(this.gradual)
 
-       this.partListNames = this.getPartListNames(xmlres.data);
 
-       this.FeatchDetailList();
 
-     } else {
 
-       // 新增条件下默认设置为收费
 
-       this.rankChange(1);
 
-       this.form.rankIdType = 1;
 
-     }
 
-   },
 
-   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 || "";
 
-       // 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
 
-         );
 
-         for (let j = 0; j < this.form.sysMusicScoreAccompaniments.length; j++) {
 
-           this.form.sysMusicScoreAccompaniments[j].track =
 
-             this.partListNames[j];
 
-           if (!this.form.sysMusicScoreAccompaniments[j].speed) {
 
-             this.form.sysMusicScoreAccompaniments[j].speed = this.xmlFirstSpeed;
 
-           }
 
-           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];
 
-           const sysData = {
 
-             ...this.form.sysMusicScoreAccompaniments[0],
 
-             metronomeMp3Url: "",
 
-             mp3Url: "",
 
-             memo:'',
 
-             track: part,
 
-           };
 
-           if (!sysData.speed) {
 
-             sysData.speed = this.xmlFirstSpeed;
 
-           }
 
-           this.createSys(sysData);
 
-         }
 
-       };
 
-       xmlRead.readAsText(file.raw);
 
-     },
 
-     rankChange(value) {
 
-       if (value) {
 
-         let tempIds = [];
 
-         this.memberRankList.forEach((item) => {
 
-           tempIds.push(item.id);
 
-         });
 
-         this.form.sysMusicScore.rankIds = tempIds.join(",");
 
-       } else {
 
-         // 会员购买重置
 
-         this.form.sysMusicScore.rankIds = "";
 
-       }
 
-     },
 
-     async memberRank() {
 
-       try {
 
-         const res = await getAllmemberRank({ isDefault: 0 });
 
-         this.memberRankList = res.data || [];
 
-       } catch (e) {
 
-         console.log(e);
 
-       }
 
-     },
 
-     formatParentId(id, list, ids = []) {
 
-       for (const item of list) {
 
-         if (item.sysMusicScoreCategoriesList) {
 
-           const cIds = this.formatParentId(
 
-             id,
 
-             item.sysMusicScoreCategoriesList,
 
-             [...ids, item.id]
 
-           );
 
-           if (cIds.includes(id)) {
 
-             return cIds;
 
-           }
 
-         }
 
-         if (item.id === id) {
 
-           return [...ids, id];
 
-         }
 
-       }
 
-       return ids;
 
-     },
 
-     async FetchTree() {
 
-       try {
 
-         const res = await queryTree();
 
-         this.tree = res.data;
 
-         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);
 
-         } else {
 
-           i.sysMusicScoreCategoriesList = null;
 
-         }
 
-       }
 
-     },
 
-     async FeatchDetailList() {
 
-       try {
 
-         const res = await queryPageSysExam({
 
-           sysMusicScoreId: this.detail.id,
 
-         });
 
-         const result = res.data || [];
 
-         result.forEach((item) => {
 
-           if (!item.subjectId) {
 
-             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 || {}
 
-         )
 
-       );
 
-     },
 
-     async removeSys(index) {
 
-       try {
 
-         await this.$confirm("是否确认删除此原音?", "提示", {
 
-           type: "warning",
 
-         });
 
-         if (this.form.sysMusicScoreAccompaniments[index]) {
 
-           this.form.delExamSongAccompanimentIds.push(
 
-             this.form.sysMusicScoreAccompaniments[index].id
 
-           );
 
-         }
 
-         this.form.sysMusicScoreAccompaniments.splice(index, 1);
 
-       } catch (error) {}
 
-     },
 
-     hasPartName(name) {
 
-       const names = [];
 
-       for (const item of this.form.sysMusicScoreAccompaniments) {
 
-         names.push(item.track);
 
-       }
 
-       return names.includes(name);
 
-     },
 
-     hasSubjectId(id) {
 
-       const ids = [];
 
-       for (const item of this.form.sysMusicScoreAccompaniments) {
 
-         ids.push(item.subjectId);
 
-       }
 
-       return ids.includes(id);
 
-     },
 
-     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.xmlUrl =  this.form.sysMusicScore.xmlUrl
 
-             item.isShowFingering =  this.form.sysMusicScore.isShowFingering
 
-           })
 
-           console.log(this.form)
 
-           if (!this.detail) {
 
-             await Add({
 
-               ...this.form,
 
-               sysMusicScore: {
 
-                 ...this.form.sysMusicScore,
 
-                 extConfigJson: JSON.stringify({
 
-                   repeatedBeats: this.form.repeatedBeats,
 
-                   gradualTimes: this.form.graduals,
 
-                 }),
 
-                 type: "COMMON",
 
-                 showFlag: 0,
 
-                 musicScoreCategoriesId: (
 
-                   this.form.sysMusicScore.musicScoreCategoriesId || []
 
-                 ).pop(),
 
-               },
 
-             });
 
-             this.$message.success("提交成功");
 
-           } else {
 
-             await Update({
 
-               ...this.form,
 
-               sysMusicScore: {
 
-                 ...this.form.sysMusicScore,
 
-                 extConfigJson: JSON.stringify({
 
-                   repeatedBeats: this.form.repeatedBeats,
 
-                   gradualTimes: this.form.graduals,
 
-                 }),
 
-                 type: "COMMON",
 
-                 id: this.detail.id,
 
-                 showFlag: this.detail.showFlag,
 
-                 musicScoreCategoriesId: (
 
-                   this.form.sysMusicScore.musicScoreCategoriesId || []
 
-                 ).pop(),
 
-               },
 
-             });
 
-             this.$message.success("修改成功");
 
-           }
 
-           this.$listeners.close();
 
-           this.$listeners.submited();
 
-         }
 
-       });
 
-     },
 
-   },
 
- };
 
- /**
 
-  * 获取指定元素下一个Note元素
 
-  * @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;
 
-   // 查找到相邻的第一个note元素
 
-   while (!siblingNote && index < (measure?.childNodes.length || 50)) {
 
-     index++;
 
-     if (pointer?.nextElementSibling?.tagName === "note") {
 
-       siblingNote = pointer?.nextElementSibling;
 
-     }
 
-     pointer = pointer?.nextElementSibling;
 
-   }
 
-   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") || [];
 
-   // const partListNames = Array.from(partList).map(item => item.getElementsByTagName('part-name')?.[0].textContent || '')
 
-   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];
 
-   // 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);
 
-         // 不等于第一行才添加避免重复添加
 
-       } else {
 
-         // words.forEach(word => {
 
-         //   const text = word.textContent || ''
 
-         //   if(isSpeedKeyword(text) && text) {
 
-         //     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)
 
-         //     }
 
-         //   }
 
-         // })
 
-       }
 
-       // 最后一个小节的结束线元素不在最后 调整
 
-       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") {
 
-               // 将结束线元素放到最后
 
-               lastParent?.appendChild(el);
 
-               break;
 
-             }
 
-           }
 
-         }
 
-       }
 
-     });
 
-     Array.from(partList).forEach((part) => {
 
-       if (part && part.getAttribute("id") !== id) {
 
-         part.parentNode?.removeChild(part);
 
-       }
 
-     });
 
-     // 处理装饰音问题
 
-     const notes = xmlParse.getElementsByTagName("note");
 
-     const getNextvNoteDuration = (i) => {
 
-       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, i) => {
 
-       const graces = note.getElementsByTagName("grace");
 
-       if (graces && graces.length) {
 
-         // if (i !== 0) {
 
-         note.appendChild(getNextvNoteDuration(i)?.cloneNode(true));
 
-         // }
 
-       }
 
-     });
 
-   }
 
-   // console.log(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,
 
-   "molto": 1.333333333,
 
-   lentando: 1.333333333,
 
-   allargando: 1.333333333,
 
-   morendo: 1.333333333,
 
-   "accel.": 0.8,
 
-   calando: 2,
 
-   "poco accel.": 0.8,
 
-   'gradually slowing': 1.333333333,
 
-   'slowing': 1.333333333,
 
-   'slow': 1.333333333,
 
-   'slowly': 1.333333333,
 
-   faster: 1.333333333,
 
- };
 
- /**
 
-  * 按照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"));
 
-   const eles = [];
 
-   for (const ele of [...words, ...metronomes]) {
 
-     const note = getNextNote(ele, "direction");
 
-     // console.log(ele, note)
 
-     if (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);
 
-       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;
 
-         if (i < noteInMeasureIndex) {
 
-           leftDuration = allDuration;
 
-         }
 
-       }
 
-       eles.push({
 
-         ele,
 
-         index: notes.indexOf(note),
 
-         noteInMeasureIndex,
 
-         textContent: ele.textContent,
 
-         measureIndex: measures.indexOf(measure),
 
-         type: ele.tagName,
 
-         allDuration,
 
-         leftDuration,
 
-       });
 
-     }
 
-   }
 
-   // 结尾处手动插入一个音符节点
 
-   eles.push({
 
-     ele: notes[notes.length - 1],
 
-     index: notes.length,
 
-     noteInMeasureIndex: 0,
 
-     textContent: '',
 
-     type: 'metronome',
 
-     allDuration: 1,
 
-     leftDuration: 1,
 
-     measureIndex: measures.length,
 
-   })
 
-   const gradualNotes = [];
 
-   eles.sort((a, b) => a.index - b.index);
 
-   const keys = Object.keys(speedInfo).map((w) => w.toLocaleLowerCase());
 
-   let isLastNoteAndNotClosed = false;
 
-   for (const ele of eles) {
 
-     const textContent = ele.textContent?.toLocaleLowerCase().trim();
 
-     if (ele === eles[eles.length - 1]) {
 
-       if (gradualNotes[gradualNotes.length - 1]?.length === 1) {
 
-         isLastNoteAndNotClosed = true;
 
-       }
 
-     }
 
-     const isKeyWork = keys.find(k => k.startsWith(textContent) || textContent?.startsWith(k))
 
-     if (
 
-       ele.type === "metronome" ||
 
-       (ele.type === "words" && (textContent.startsWith("a tempo") || isKeyWork) || isLastNoteAndNotClosed)
 
-     ) {
 
-       const indexOf = gradualNotes.findIndex((item) => item.length === 1);
 
-       if (indexOf > -1 && ele.index > gradualNotes[indexOf]?.[0].start) {
 
-         gradualNotes[indexOf][1] = {
 
-           start: ele.index,
 
-           measureIndex: ele.measureIndex,
 
-           noteInMeasureIndex: ele.noteInMeasureIndex,
 
-           allDuration: ele.allDuration,
 
-           leftDuration: ele.leftDuration,
 
-           type: textContent,
 
-         };
 
-       }
 
-     }
 
-     if (ele.type === "words" && isKeyWork) {
 
-       gradualNotes.push([
 
-         {
 
-           start: ele.index,
 
-           measureIndex: ele.measureIndex,
 
-           noteInMeasureIndex: ele.noteInMeasureIndex,
 
-           allDuration: ele.allDuration,
 
-           leftDuration: ele.leftDuration,
 
-           type: textContent,
 
-         },
 
-       ]);
 
-     }
 
-   }
 
-   return gradualNotes;
 
- }
 
- </script>
 
- <style lang="less" scoped>
 
- .btns {
 
-   text-align: right;
 
- }
 
- .files {
 
-   background-color: #f8f8f8;
 
-   padding: 20px 0;
 
-   padding-right: 20px;
 
-   margin-bottom: 20px;
 
-   border-radius: 5px;
 
-   position: relative;
 
-   .file-remove {
 
-     position: absolute;
 
-     right: 20px;
 
-     bottom: 10px;
 
-   }
 
- }
 
- .gradual-item{
 
-   background-color: #f8f8f8;
 
-   margin-bottom: 10px;
 
-   padding: 10px;
 
-   border-radius: 6px;
 
- }
 
- </style>
 
 
  |