Bläddra i källkod

Merge branch 'feature/0429-music' into test-online

# Conflicts:
#	src/views/music-library/music-sheet/modal/music-operation.tsx
#	src/views/music-library/project-music-sheet/module/gyt/music-sheet-gyt.tsx
#	src/views/music-library/project-music-sheet/module/kt/addMusic.tsx
yuanliang 9 månader sedan
förälder
incheckning
b95d4e957d

+ 2 - 2
src/utils/constant.ts

@@ -233,8 +233,8 @@ export const heardLevelType = {
 
 // 曲目类型
 export const musicSheetType = {
-  SINGLE: '',
-  CONCERT: ''
+  SINGLE: '多声轨',
+  CONCERT: '单声轨'
 } as any
 
 // 作者属性

+ 17 - 5
src/views/music-library/music-sheet/component/music-list.tsx

@@ -29,7 +29,7 @@ import {
   musicTagPage,
   musicSheetCategoriesQueryTree
 } from '../../api'
-import MusicOperation from '../modal/music-operation'
+import MusicOperation from '../modal/music-operationV2'
 import { subjectPage } from '@/views/system-manage/api'
 import MusicPreView from '../modal/musicPreView'
 import UseProject from '@views/music-library/music-sheet/modal/use-project'
@@ -137,7 +137,7 @@ export default defineComponent({
             return (
               <NDescriptions labelPlacement="left" column={1}>
                 <NDescriptionsItem label="音乐人">{row.composer}</NDescriptionsItem>
-                <NDescriptionsItem label="多声轨渲染">
+                <NDescriptionsItem label="谱面渲染">
                   {getMapValueByKey(row.musicSheetType, new Map(Object.entries(musicSheetType)))}
                 </NDescriptionsItem>
                 <NDescriptionsItem label="分类">
@@ -464,9 +464,20 @@ export default defineComponent({
         const { data } = await musicSheetCategoriesQueryTree({})
         // state.musicSheetCategories = filterPointCategory(data, 'musicSheetCategoriesList')
         state.musicSheetCategories = data || []
+        clearEmptyMusicCategory(state.musicSheetCategories)
       } catch (e) {}
     }
 
+    const clearEmptyMusicCategory = (data: any) => {
+      for (let i = 0; i < data.length; i++) {
+        if (data[i].musicSheetCategoriesList.length < 1) {
+          data[i].musicSheetCategoriesList = null
+        } else {
+          clearEmptyMusicCategory(data[i].musicSheetCategoriesList)
+        }
+      }
+    }
+
     // 获取声部
     const initSubjectList = async () => {
       try {
@@ -524,6 +535,7 @@ export default defineComponent({
       }
     )
     const onSearch = () => {
+      checkedRowKeysRef.value = []
       saveForm.value?.submit()
     }
     const onBtnReset = () => {
@@ -563,9 +575,9 @@ export default defineComponent({
               clearable
             />
           </NFormItem>
-          <NFormItem label="多声轨渲染" path="musicSheetType">
+          <NFormItem label="谱面渲染" path="musicSheetType">
             <NSelect
-              placeholder="请选择多声轨渲染"
+              placeholder="请选择谱面渲染"
               v-model:value={state.searchForm.musicSheetType}
               options={getSelectDataFromObj(musicSheetType)}
               clearable
@@ -796,7 +808,7 @@ export default defineComponent({
             columns={columns()}
             data={state.dataList}
             rowKey={(row: any) => row.id}
-            onUpdateCheckedRowKeys={handleCheck}
+            v-model:checkedRowKeys={checkedRowKeysRef.value}
             scrollX={'1200'}
           ></NDataTable>
           <Pagination

+ 2090 - 0
src/views/music-library/music-sheet/modal/music-operationV2.tsx

@@ -0,0 +1,2090 @@
+import type {SelectOption} from 'naive-ui'
+import {
+  NAlert,
+  NButton,
+  NCascader,
+  NCheckbox,
+  NCheckboxGroup,
+  NForm,
+  NFormItem,
+  NFormItemGi,
+  NGi,
+  NGrid,
+  NInput,
+  NInputGroup,
+  NInputGroupLabel,
+  NInputNumber,
+  NModal,
+  NRadio,
+  NRadioGroup,
+  NSelect,
+  NSpace,
+  NSpin,
+  useDialog,
+  useMessage
+} from 'naive-ui'
+import {defineComponent, onMounted, PropType, reactive, ref} from 'vue'
+import {musicSheetCategoriesQueryTree, musicSheetDetail, musicSheetSave} from '../../api'
+import UploadFile from '@/components/upload-file'
+import styles from './index.module.less'
+import deepClone from '@/utils/deep.clone'
+import axios from 'axios'
+import {appKey, clientType, musicSheetSourceType} from '@/utils/constant'
+import {getMapValueByKey, getSelectDataFromObj} from '@/utils/objectUtil'
+import {musicalInstrumentPage} from '@views/system-manage/subject-manage/api'
+import {subjectPage} from '@views/system-manage/api'
+import MusicSheetOwnerDialog from '@views/music-library/music-sheet/modal/musicSheetOwnerDialog'
+import {sysApplicationPage} from '@views/menu-manage/api'
+import {filterPointCategory} from '@views/teaching-manage/unit-test'
+import MusicCreateImg from './music-create-img'
+import {TABS_ROUTES} from "@/store/mutation-types";
+
+/**
+ * 获取指定元素下一个Note元素
+ * @param ele 指定元素
+ * @param selectors 选择器
+ */
+const getNextNote = (ele: any, selectors: any) => {
+  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: any, partIndex: any) => {
+  if (!xml) return ''
+  const xmlParse = new DOMParser().parseFromString(xml, 'text/xml')
+  const partList =
+      xmlParse.getElementsByTagName('part-list')?.[0]?.getElementsByTagName('score-part') || []
+  const parts = xmlParse.getElementsByTagName('part')
+  const visiblePartInfo = partList[partIndex]
+  if (visiblePartInfo) {
+    const id = visiblePartInfo.getAttribute('id')
+    Array.from(parts).forEach((part) => {
+      if (part && part.getAttribute('id') !== id) {
+        part.parentNode?.removeChild(part)
+        // 不等于第一行才添加避免重复添加
+      }
+
+      // 最后一个小节的结束线元素不在最后 调整
+      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: any[] = (lastParent?.children as any) || []
+          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: any) => {
+      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
+        }
+      }
+      return nextNote?.getElementsByTagName('duration')[0]
+    }
+    Array.from(notes).forEach((note, i) => {
+      const graces = note.getElementsByTagName('grace')
+      if (graces && graces.length) {
+        note.appendChild(getNextvNoteDuration(i)?.cloneNode(true))
+      }
+    })
+  }
+  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: string) {
+  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: any) => item.nodeName === 'note')
+          .findIndex((item) => item === note)
+
+      let allDuration = 0
+      let leftDuration = 0
+      for (let i = 0; i < measureNotes.length; i++) {
+        const n: any = 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), //,measure?.getAttribute('number')
+        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: any[] = []
+  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: any = ele.textContent?.toLocaleLowerCase().trim()
+    if (ele === eles[eles.length - 1]) {
+      if (gradualNotes[gradualNotes.length - 1]?.length === 1) {
+        isLastNoteAndNotClosed = true
+      }
+    }
+
+    const isKeyWork = keys.find((k) => {
+      const ks = k.split(' ')
+      return textContent && ks.includes(textContent)
+    })
+    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
+}
+
+export default defineComponent({
+  name: 'music-operation',
+  props: {
+    type: {
+      type: String,
+      default: 'add'
+    },
+    data: {
+      type: Object as PropType<any>,
+      default: () => {
+      }
+    },
+    tagList: {
+      type: Array as PropType<Array<SelectOption>>,
+      default: () => []
+    },
+    subjectList: {
+      type: Array as PropType<Array<SelectOption>>,
+      default: () => []
+    }
+    // musicSheetCategories: {
+    //   type: Array as PropType<Array<SelectOption>>,
+    //   default: () => []
+    // }
+  },
+  emits: ['close', 'getList'],
+
+  setup(props, {slots, attrs, emit}) {
+    const forms = reactive({
+      details: {} as any, // 曲目详情
+      graduals: {} as any, // 渐变速度
+      playMode: 'MP3', // 播放类型
+      xmlFileUrl: null, // XML
+      midiUrl: null, // mid
+      name: null, // 曲目名称
+      // musicTag: [] as any, // 曲目标签
+      composer: null, // 音乐人
+      playSpeed: null as any, // 曲谱速度
+      // showFingering: null as any, // 是否显示指法
+      // canEvaluate: null as any, // 是否评测
+      // notation: null as any, // 能否转和简谱
+      // auditVersion: null as any, // 审核版本
+      // sortNumber: null, // 排序
+      musicCover: null, // 曲谱封面
+      remark: null, // 曲谱描述
+      // musicSheetSoundList: [] as any, // 原音
+      musicSheetSoundList_YY: [] as any, // 演唱原音
+      musicSheetSoundList_YZ: [] as any, // 演奏演奏
+      musicSheetSoundList_all_subject: null, // 全部声部原音
+      // musicSheetCategoriesId: null,
+      status: false,
+      musicSheetType: 'SINGLE', // 曲目类型
+      sourceType: null as any, //来源类型/作者属性(PLATFORM: 平台; ORG: 机构; PERSON: 个人)
+      // userId: null, // 所属人
+      appAuditFlag: 0, // 是否审核版本
+      midiFileUrl: null, // 伴奏文件 MIDI文件(保留字段)
+      subjectIds: [] as any, // 可用声部
+      musicalInstrumentIdList: [] as any, //可用乐器
+      musicCategoryId: null, //曲目分类
+      musicSheetAccompanimentList: [] as any, //曲目伴奏
+      audioType: 'HOMEMODE', // 伴奏类型
+      isPlayBeat: true, // 是否播放节拍器
+      isUseSystemBeat: true, // 是否使用系统节拍器(0:否;1:是)
+      isUseSingSystemBeat: true, //演唱是否使用系统节拍器(0:否;1:是)
+      repeatedBeats: false, // 是否重复节拍时长
+      repeatedBeatsToSing: false, //演唱是否重复节拍时长
+      isPlaySingBeat: true, //是否播入演唱节拍器(0: 否 1:是)
+      evaluationStandard: 'FREQUENCY', // 评分标准 节奏 AMPLITUDE 音准 FREQUENCY 分贝 DECIBELS
+      multiTracksSelection: [] as any, // 声轨
+      musicSheetExtend: {} as any, //所属人信息
+      musicImg: '', // 五线谱图片
+      musicFirstImg: '', //首调图片
+      musicJianImg: '', // 简谱固定调
+      isEvxml: false, // 是否是evxml
+      isShowFingering: true, // 是否显示指法
+      solmizationFileUrl: null, // 唱名文件
+      isAllSubject: false, // 适用声部
+    })
+    const state = reactive({
+      loading: false,
+      previewMode: false, //是否是预览模式
+      tagList: [...props.tagList] as any, // 标签列表
+      xmlFirstSpeed: null as any, // 第一个音轨速度
+      partListNames: [] as any, // 所有音轨声部列表
+      musicSheetCategories: [] as any,
+      musicSheetAccompanimentUrls: '' as any,
+      musicSheetAccompanimentUrlList: [] as any,
+      instrumentData: [],
+      instrumentList: [] as any,
+      instrumentIdNameMap: new Map() as any,
+      subjectList: [] as any,
+      showMusicSheetOwnerDialog: false, //所属人弹框
+      // musicSheetOwnerData: {}, //所属人信息
+      multiTracks: null,
+      multiInstruments: null,
+      appData: [], // 应用列表
+      ownerName: null as any, // 所属人名称描述
+
+      productOpen: false, // 是否打开自动生成图片
+      productItem: {} as any,
+      productIfameSrc: '',
+      isAutoSave: false, // 是否自动保存
+      fSongFile: null as any, // 范唱
+      bSongFile: null as any, // 伴唱
+      musicSheetSoundList: [] as any,
+    })
+    const gradualData = reactive({
+      list: [] as any[],
+      gradualRefs: [] as any[]
+    })
+
+    const btnLoading = ref(false)
+    const formsRef = ref()
+    const message = useMessage()
+    const dialog = useDialog()
+
+    // 提交记录
+    const onSubmit = async () => {
+      formsRef.value.validate(async (error: any) => {
+        if (error) {
+          return
+        }
+        // 校验合奏时声轨与乐器是否存在不匹配情况
+        if (forms.musicSheetType == 'CONCERT') {
+          let set = [] as any;
+          const {data} = await musicalInstrumentPage({page: 1, rows: 9999})
+          data.rows.map((row: any) => {
+            if (row.code) {
+              row.code.split(',').forEach((code: string) => {
+                let temp = code.replaceAll(' ', '')
+                set.push(temp.toLocaleLowerCase())
+              })
+            }
+          })
+          let unDefinedTrack = [] as any
+          forms.multiTracksSelection.forEach((item: any) => {
+            if (item) {
+              let contain = false;
+              let code = item.replaceAll(' ', '').toLocaleLowerCase()
+              for (let i = 0; i < set.length; i++) {
+                if (set[i].startsWith(code) || set[i].endsWith(code)) {
+                  contain = true
+                  break
+                }
+              }
+              if (!contain) {
+                unDefinedTrack.push(item)
+              }
+            }
+          })
+          if (unDefinedTrack.length > 0) {
+            dialog.warning({
+              title: '提示',
+              content: `声轨未配置:${unDefinedTrack.join(',')}`,
+              positiveText: '确定',
+              onPositiveClick: () => {
+              },
+            })
+            return
+          }
+        }
+
+        if (!state.isAutoSave) {
+          state.isAutoSave = true
+          state.productOpen = true
+          return
+        }
+        try {
+          //extConfigJson: {"repeatedBeats":0,"gradualTimes":{"75":"02:38:60","77":"02:43:39"}}
+          let audioPlayTypes = [] as any;
+          let musicSheetSoundList = [];
+          let musicSheetType = forms.musicSheetType;
+          if (state.fSongFile) {
+            musicSheetSoundList.push({
+              musicSheetId: props.data.id,
+              audioFileUrl: state.fSongFile,
+              audioPlayType: 'SING',
+              solmizationFileUrl: forms.solmizationFileUrl
+            })
+            audioPlayTypes.push("SING")
+          }
+
+          if (forms.isAllSubject) {
+            if (musicSheetType == 'SINGLE' && forms.musicSheetSoundList_all_subject) {
+              audioPlayTypes.push("PLAY")
+              musicSheetSoundList.push({
+                audioFileUrl: forms.musicSheetSoundList_all_subject,
+                musicSheetId: props.data.id,
+                audioPlayType: 'PLAY'
+              })
+            }
+          } else {
+            if (musicSheetType == 'SINGLE' && forms.musicSheetSoundList_YZ.length > 0) {
+              audioPlayTypes.push("PLAY")
+              forms.musicSheetSoundList_YZ.forEach((musicSheetSound: any) => {
+                if (forms.musicalInstrumentIdList.includes(musicSheetSound.musicalInstrumentId)) {
+                  musicSheetSoundList.push({
+                    ...musicSheetSound,
+                    musicSheetId: props.data.id,
+                  })
+                }
+              })
+            }
+          }
+
+            if (musicSheetType == 'CONCERT' && forms.musicSheetSoundList_YY.length > 0) {
+              audioPlayTypes.push("PLAY")
+              forms.musicSheetSoundList_YY.forEach((musicSheetSound: any) => {
+                if (musicSheetSound.audioFileUrl) {
+                  musicSheetSoundList.push({
+                    ...musicSheetSound,
+                    musicSheetId: props.data.id,
+                  })
+                }
+              })
+            }
+
+          if (state.bSongFile) {
+            forms.musicSheetAccompanimentList.push({
+              musicSheetId: props.data.id,
+              audioFileUrl: state.bSongFile,
+              audioPlayType: 'SING'
+            })
+          }
+
+          //
+
+
+          const obj = {
+            musicCategoryId: forms.musicCategoryId,
+            musicCover: forms.musicCover,
+            name: forms.name,
+            appAuditFlag: forms.appAuditFlag,
+            subjectIds: forms.isAllSubject ? "" : forms.subjectIds.join(','),
+            remark: forms.remark,
+            audioPlayTypes: audioPlayTypes.join(','),
+            musicalInstrumentIds: forms.isAllSubject ? "" : forms.musicalInstrumentIdList.join(','),
+            composer: forms.composer,
+            musicSheetType: forms.musicSheetType,
+            isUseSystemBeat: forms.isUseSystemBeat,
+            isShowFingering: forms.isShowFingering,
+            isPlayBeat: forms.isPlayBeat,
+            multiTracksSelection: forms.isAllSubject ? "" : forms.multiTracksSelection.join(','),
+            playSpeed: forms.playSpeed,
+            playMode: forms.playMode,
+            xmlFileUrl: forms.xmlFileUrl,
+            musicImg: forms.musicImg,
+            musicFirstImg: forms.musicFirstImg,
+            musicJianImg: forms.musicJianImg,
+            extConfigJson: JSON.stringify({
+              repeatedBeats: forms.repeatedBeats ? 1 : 0,
+              gradualTimes: forms.graduals,
+              isEvxml: forms.isEvxml ? 1 : 0,
+              repeatedBeatsToSing: forms.repeatedBeatsToSing ? 1 : 0
+            }),
+            // availableType: forms.availableType,
+            sourceType: forms.sourceType,
+            audioType: forms.audioType,
+            status: forms.status,
+            evaluationStandard: forms.evaluationStandard,
+            musicSheetAccompanimentList: forms.musicSheetAccompanimentList,
+            musicSheetSoundList: musicSheetSoundList,
+            musicTag: '-1',
+            isUseSingSystemBeat: forms.isUseSingSystemBeat,
+            isPlaySingBeat: forms.isPlaySingBeat,
+            isAllSubject: forms.isAllSubject,
+          }
+          if (forms.audioType == 'MIDI') {
+            obj.musicSheetSoundList = []
+          }
+          btnLoading.value = true
+          if (props.type === 'add') {
+            await musicSheetSave(obj)
+            message.success('添加成功')
+          } else if (props.type === 'edit') {
+            await musicSheetSave({...obj, id: props.data.id})
+            message.success('修改成功')
+          }
+          emit('getList')
+          emit('close')
+        } catch (e) {
+          console.log(e)
+        }
+        setTimeout(() => {
+          btnLoading.value = false
+        }, 100)
+      })
+    }
+
+    // 上传XML,初始化音轨 音轨速度 乐器、声部
+    const readFileInputEventAsArrayBuffer = (file: any) => {
+      // 是否是evxml
+      forms.isEvxml = file?.name?.includes('.evxml') ? true : false;
+      const xmlRead = new FileReader()
+      xmlRead.onload = (res) => {
+        try {
+          gradualData.list = getGradualLengthByXml(res?.target?.result as any).filter(
+              (item: any) => item.length === 2
+          )
+        } catch (error) {
+        }
+        state.partListNames = getPartListNames(res?.target?.result as any) as any
+        // parseInstrumentAndSubject(res?.target?.result as any)
+        // 这里是如果没有当前音轨就重新写
+        for (let j = 0; j < state.partListNames.length; j++) {
+          if (!forms.musicSheetSoundList_YY[j]) {
+            forms.musicSheetSoundList_YY.push({audioFileUrl: null, track: null})
+          }
+          forms.musicSheetSoundList_YY[j].track = state.partListNames[j].value
+        }
+
+        // 循环添加所在音轨的原音
+        for (
+            let index = forms.musicSheetSoundList_YY.length;
+            index < state.partListNames.length;
+            index++
+        ) {
+          const part = state.partListNames[index].value
+          const sysData = {
+            ...forms.musicSheetSoundList_YY[0],
+            track: part
+          }
+          if (!sysData.speed) {
+            sysData.speed = state.xmlFirstSpeed
+          }
+          createSys(sysData)
+        }
+
+        if (forms.musicSheetSoundList_YY.length == 0) {
+          forms.musicSheetSoundList_YY.push({audioFileUrl: '', track: ''})
+        }
+      }
+      xmlRead.readAsText(file)
+    }
+
+    const containOther = (track: any) => {
+      for (let i = 0; i < state.partListNames.length; i++) {
+        if (state.partListNames[i].value == track) {
+          return true
+        }
+      }
+      return false
+    }
+
+    const parseInstrumentAndSubject = (xml: any) => {
+      if (!xml) return
+      const xmlParse = new DOMParser().parseFromString(xml, 'text/xml')
+      // 乐器
+      const instrumentCodeList: any = []
+      const instrumentEle = xmlParse.getElementsByTagName('virtual-instrument')
+      for (let index = 0; index < instrumentEle.length; index++) {
+        const note = instrumentEle[index]
+        const instrumentCode = note.getElementsByTagName('virtual-name')?.[0]?.textContent || ''
+        if (instrumentCode && !instrumentCodeList.includes(instrumentCode)) {
+          instrumentCodeList.push(instrumentCode)
+        }
+      }
+      // 乐器支持多编码,暂不开放
+      // const codeIdMap = new Map<string, []>() as any
+      // state.instrumentData.forEach((data: any) => {
+      //   const codes = data.code.split(/,|,/)
+      //   codes.forEach((code: string) => {
+      //     if (codeIdMap.has(code)) {
+      //       codeIdMap.get(code).push(data.id + '')
+      //     } else {
+      //       const arr = [] as any;
+      //       arr.push(data.id + '')
+      //       codeIdMap.set(code, arr)
+      //     }
+      //     // codeIdMap.set(code, data.id + '')
+      //   })
+      // })
+      // forms.musicalInstrumentIdList = []
+      // instrumentCodeList.forEach((code: string) => {
+      //   if (codeIdMap.has(code)) {
+      //     codeIdMap.get(code).forEach((c: any) => {
+      //       forms.musicalInstrumentIdList.push(c)
+      //     })
+      //   }
+      // })
+      const codeIdMap = new Map<string, string>()
+      state.instrumentData.forEach((data: any) => {
+        codeIdMap.set(data.code, data.id + '')
+      })
+      forms.musicalInstrumentIdList = []
+      instrumentCodeList.forEach((code: string) => {
+        if (codeIdMap.has(code)) {
+          forms.musicalInstrumentIdList.push(codeIdMap.get(code))
+        }
+      })
+
+      // 声部
+      if (forms.musicalInstrumentIdList.length > 0) {
+        showBackSubject(forms.musicalInstrumentIdList)
+      }
+    }
+
+    // 获取xml中所有轨道 乐器
+    const getPartListNames = (xml: any) => {
+      if (!xml) return []
+      const xmlParse = new DOMParser().parseFromString(xml, 'text/xml')
+      const partList: any =
+          xmlParse.getElementsByTagName('part-list')?.[0]?.getElementsByTagName('score-part') || []
+      let partListNames = Array.from(partList).map((item: any) => {
+        let part = item.getElementsByTagName('part-name')?.[0]?.textContent || ''
+        // evxml没有分轨,需要手动设置一个默认的名称,用于上传原音
+        if (forms.isEvxml) {
+          part = part || 'noPartName'
+        }
+        return {
+          value: part.trim(),
+          label: part.trim()
+        }
+      })
+
+      // 处理空数据
+      // if (partListNames.length === 1 && forms.details.id && !partListNames[0].value) {
+      //   partListNames[0] = {
+      //     value: forms.details.multiTracksSelection,
+      //     label: forms.details.multiTracksSelection
+      //   }
+      // }
+
+      partListNames = partListNames.filter((n: any) => n.value?.toLocaleUpperCase?.() != 'COMMON')
+
+      if (partListNames.length > 0) {
+        forms.musicSheetSoundList_YY = forms.musicSheetSoundList_YY.slice(0, partListNames.length)
+      }
+
+      state.xmlFirstSpeed = xmlParse.getElementsByTagName('per-minute')?.[0]?.textContent || ''
+      if (!forms.playSpeed) {
+        if (state.xmlFirstSpeed) {
+          forms.playSpeed = Number.parseFloat(state.xmlFirstSpeed)
+        } else {
+          // 速度默认给100
+          forms.playSpeed = 100
+        }
+      }
+      // console.log('xml声轨',partListNames,state.xmlFirstSpeed)
+      return partListNames
+    }
+
+    // 判断选择的音轨是否在选中
+    const initPartsListStatus = (track: string): any => {
+      // const _names = state.partListNames.filter(
+      //   (n: any) => n.value?.toLocaleUpperCase?.() != 'COMMON'
+      // )
+      const partListNames = deepClone(state.partListNames) || []
+      const multiTracksSelection = forms.multiTracksSelection
+      partListNames.forEach((item: any) => {
+        if (multiTracksSelection.includes(item.value)) {
+          item.disabled = true
+        } else {
+          item.disabled = false
+        }
+
+        // const index = forms.musicSheetSoundList.findIndex(
+        //   (ground: any) => item.value == ground.track
+        // )
+
+        // if (index > -1 && track == item.value) {
+        //   item.disabled = false
+        // } else {
+        //   item.disabled = true
+        // }
+      })
+      return partListNames || []
+    }
+
+    // 反显声部
+    const showBackSubject = async (musicalInstrumentIdList: []) => {
+      try {
+        const {data} = await subjectPage({
+          page: 1,
+          rows: 999,
+          musicalInstrumentIdList: musicalInstrumentIdList
+        })
+        const tempList = data.rows || []
+        tempList.forEach((item: any) => {
+          forms.subjectIds.push(item.id + '')
+        })
+      } catch {
+      }
+    }
+
+    // 添加原音
+    const createSys = (initData?: any) => {
+      forms.musicSheetSoundList_YY.push({
+        audioFileUrl: null, // 原音
+        track: null, // 轨道
+        ...initData
+      })
+    }
+    // 删除原音
+    const removeSys = (index: number) => {
+      dialog.warning({
+        title: '提示',
+        content: `是否确认删除此原音?`,
+        positiveText: '确定',
+        negativeText: '取消',
+        onPositiveClick: async () => {
+          const sound = forms.musicSheetSoundList_YY[index]
+          const track = sound.track
+          if (track != null) {
+            const selectIndex = forms.multiTracksSelection.indexOf(track)
+            if (selectIndex > -1) {
+              forms.multiTracksSelection.splice(selectIndex, 1)
+            }
+          } else {
+            forms.musicSheetSoundList_YY.splice(index, 1)
+          }
+        }
+      })
+    }
+
+    const checkMultiTracks = (value: string) => {
+      if (!value) {
+        return
+      }
+      if (value === 'all') {
+        forms.multiTracksSelection = []
+        state.partListNames.forEach((next: any) => {
+          forms.multiTracksSelection.push(next.value)
+        })
+      } else if (value === 'invert') {
+        state.partListNames.forEach((next: any) => {
+          const indexOf = forms.multiTracksSelection.indexOf(next.value)
+          if (indexOf > -1) {
+            forms.multiTracksSelection.splice(indexOf, 1)
+          } else {
+            forms.multiTracksSelection.push(next.value)
+          }
+        })
+      } else if (value === 'allUncheck') {
+        forms.multiTracksSelection = []
+      }
+    }
+    const setOwnerName = () => {
+      if (forms.sourceType == 'PLATFORM') {
+        state.ownerName = ''
+        return
+      }
+      if (!forms.musicSheetExtend || !forms.sourceType || !forms.musicSheetExtend?.userId) {
+        return
+      }
+      const appId = forms.musicSheetExtend.applicationId
+      const app = state.appData.filter((next: any) => {
+        return next.id == appId
+      }) as any
+      if (app.length > 0) {
+        state.ownerName = app[0].appName
+      }
+      if (forms.sourceType == 'ORG') {
+        state.ownerName += '-' + forms.musicSheetExtend.organizationRole
+      } else if (forms.sourceType == 'PERSON') {
+        state.ownerName +=
+            '-' +
+            getMapValueByKey(forms.musicSheetExtend.clientType, new Map(Object.entries(clientType)))
+        if (forms.musicSheetExtend.userName) {
+          state.ownerName += '-' + forms.musicSheetExtend.userName
+        }
+        if (forms.musicSheetExtend.phone) {
+          state.ownerName += '(' + forms.musicSheetExtend.phone + ')'
+        }
+      }
+    }
+
+    const changeSubject = async (subjectIdList: []) => {
+      state.instrumentList = []
+      if (!subjectIdList || subjectIdList.length == 0) {
+        forms.musicalInstrumentIdList = []
+        return
+      }
+      let enableFlag = null;
+      if (props.type === 'add') {
+        enableFlag = true;
+      }
+      let tempMusicalInstrumentIdList = [] as any
+      const {data} = await musicalInstrumentPage({page: 1, rows: 999, subjectIds: subjectIdList, enableFlag: enableFlag});
+      data.rows.map((item: any) => {
+        tempMusicalInstrumentIdList.push(item.id + '')
+        state.instrumentList.push(
+            {
+              label: item.name,
+              value: item.id + '',
+              disabled: !item.enableFlag
+            }
+        )
+      })
+      forms.musicalInstrumentIdList = forms.musicalInstrumentIdList.filter((item: any) => {
+        return tempMusicalInstrumentIdList.includes(item)
+      })
+    }
+
+    onMounted(async () => {
+      state.loading = true
+      if (props.type === 'preview') {
+        state.previewMode = true
+      }
+      // 获取乐器信息
+      {
+        if (state.instrumentList && state.instrumentList.length > 0) {
+          return
+        }
+        try {
+          const {data} = await musicalInstrumentPage({page: 1, rows: 999})
+          const tempList = data.rows || []
+          tempList.forEach((item: any) => {
+            item.label = item.name
+            item.value = item.id + ''
+            item.disabled = !item.enableFlag
+
+            state.instrumentIdNameMap.set(item.id + '', item.name)
+
+            forms.musicSheetSoundList_YZ.push({
+              'musicSheetId': props.data.id,
+              'musicalInstrumentId': item.id + '',
+              'musicalInstrumentName': item.name,
+              'audioFileUrl': null,
+              'audioPlayType': 'PLAY'
+            });
+          })
+          state.instrumentData = tempList
+          // state.instrumentList = tempList
+        } catch {
+        }
+      }
+      state.subjectList = deepClone(props.subjectList)
+      state.subjectList.forEach((subject: any) => {
+        subject.disabled = !subject.enableFlag
+      })
+
+      // 初始化应用
+      {
+        const appKeys = Object.keys(appKey)
+
+        const {data} = await sysApplicationPage({page: 1, rows: 999, parentId: 0})
+        const tempList = data.rows || []
+        const filter = tempList.filter((next: any) => {
+          return appKeys.includes(next.appKey)
+        })
+        filter.forEach((item: any) => {
+          item.label = item.appName
+          item.value = item.id
+        })
+        state.appData = filter
+      }
+
+      // 获取分类信息
+      {
+        try {
+          const {data} = await musicSheetCategoriesQueryTree({enable: true})
+          state.musicSheetCategories = filterPointCategory(data, 'musicSheetCategoriesList')
+        } catch (e) {
+        }
+      }
+
+      if (props.type === 'edit' || props.type === 'preview') {
+        const detail = props.data
+        try {
+          const {data} = await musicSheetDetail({id: detail.id})
+          forms.details = data
+          forms.playMode = data.playMode
+          forms.xmlFileUrl = data.xmlFileUrl
+          forms.midiUrl = data.midiUrl
+          forms.name = data.name
+          // forms.musicTag = data.musicTag?.split(',')
+          forms.composer = data.composer
+          forms.playSpeed = data.playSpeed ? Number.parseFloat(data.playSpeed) : 100
+          // forms.showFingering = Number(data.showFingering)
+          // forms.canEvaluate = Number(data.canEvaluate)
+          // forms.notation = Number(data.notation)
+          // forms.auditVersion = Number(data.auditVersion)
+          // forms.sortNumber = data.sortNumber
+          forms.musicCover = data.musicCover
+          forms.remark = data.remark
+          forms.status = data.status
+          forms.musicSheetType = data.musicSheetType || 'SINGLE'
+          forms.sourceType = data.sourceType
+          forms.appAuditFlag = data.appAuditFlag ? 1 : 0
+          forms.midiFileUrl = data.midiFileUrl
+          forms.isShowFingering = data.isShowFingering
+          forms.isAllSubject = data.isAllSubject
+          forms.isUseSingSystemBeat = data.isUseSingSystemBeat
+          forms.isPlaySingBeat = data.isPlaySingBeat
+          forms.subjectIds = []
+          if (data.subjectIds) {
+            const subjectIds = data.subjectIds.split(',') || []
+            subjectIds.forEach((subjectId: any) => {
+              if (!forms.subjectIds.includes(subjectId)) {
+                forms.subjectIds.push(subjectId)
+              }
+            })
+          }
+          forms.musicalInstrumentIdList = data.musicalInstrumentIds ? data.musicalInstrumentIds.split(',') : []
+          await changeSubject(forms.subjectIds)
+          forms.musicCategoryId = data.musicCategoryId
+          forms.audioType = data.audioType
+          forms.isPlayBeat = data.isPlayBeat
+          forms.isUseSystemBeat = data.isUseSystemBeat
+          // 获取渐变 和 是否多声部
+          try {
+            const extConfigJson = data.extConfigJson ? JSON.parse(data.extConfigJson) : {}
+            forms.graduals = extConfigJson.gradualTimes || {}
+            forms.repeatedBeats = !!extConfigJson.repeatedBeats
+            forms.isEvxml = !!extConfigJson.isEvxml
+            forms.repeatedBeatsToSing = !!extConfigJson.repeatedBeatsToSing
+          } catch (error) {
+          }
+          forms.evaluationStandard = data.evaluationStandard
+          forms.musicSheetExtend = data.musicSheetExtend
+
+          state.musicSheetSoundList = data.musicSheetSoundList ? data.musicSheetSoundList : []
+
+          let musicSheetAccompanimentList = data.musicSheetAccompanimentList ? data.musicSheetAccompanimentList : []
+          musicSheetAccompanimentList.forEach((next: any) => {
+            let audioPlayType = next.audioPlayType;
+            if (audioPlayType && audioPlayType == 'SING') {
+              state.bSongFile = next.audioFileUrl;
+            } else {
+              state.musicSheetAccompanimentUrlList.push(next.audioFileUrl)
+              forms.musicSheetAccompanimentList.push(next)
+            }
+          })
+
+          // 初始化演奏
+          for (let i = 0; i < state.musicSheetSoundList.length; i++) {
+            if (state.musicSheetSoundList[i].audioPlayType == 'SING') {
+              // 范唱 唱名
+              state.fSongFile = state.musicSheetSoundList[i].audioFileUrl
+              forms.solmizationFileUrl = state.musicSheetSoundList[i].solmizationFileUrl
+            } else {
+              if (forms.isAllSubject) {
+                forms.musicSheetSoundList_all_subject = state.musicSheetSoundList[i].audioFileUrl
+              } else {
+                // 乐器演奏原音
+                for (let j = 0; j < forms.musicSheetSoundList_YZ.length; j++) {
+                  let musicalInstrumentId = state.musicSheetSoundList[i].musicalInstrumentId;
+                  if (musicalInstrumentId && musicalInstrumentId == forms.musicSheetSoundList_YZ[j].musicalInstrumentId) {
+                    forms.musicSheetSoundList_YZ[j].audioFileUrl = state.musicSheetSoundList[i].audioFileUrl
+                  }
+                }
+              }
+            }
+          }
+
+
+          setOwnerName()
+          axios.get(data.xmlFileUrl).then((res: any) => {
+            if (res?.data) {
+              gradualData.list = getGradualLengthByXml(res?.data as any).filter(
+                  (item: any) => item.length === 2
+              )
+              state.partListNames = getPartListNames(res?.data as any) as any
+
+              // 初始化音轨和原音
+              if (data.multiTracksSelection) {
+                data.multiTracksSelection = data.multiTracksSelection.toLocaleUpperCase()
+              }
+              if (!data.multiTracksSelection || data.multiTracksSelection.trim() == '' || data.multiTracksSelection.trim() == 'NULL') {
+                forms.multiTracksSelection = ['']
+              } else {
+                forms.multiTracksSelection = data.multiTracksSelection.split(',')
+              }
+              let names = state.partListNames.map((next: any) => next.label)
+              forms.multiTracksSelection = names.filter((next: any) => forms.multiTracksSelection.includes(next.toLocaleUpperCase()))
+
+              if (state.musicSheetSoundList.length === 1 && state.musicSheetSoundList[0].track === 'P1') {
+                forms.musicSheetSoundList_YY.push({
+                  audioFileUrl: state.musicSheetSoundList[0].audioFileUrl, // 原音
+                  track: state.partListNames[0].value || '', // 轨道
+                  audioPlayType: 'PLAY'
+                })
+              } else {
+                const tracks = [] as any
+                state.partListNames.forEach((item: any) => {
+                  let audioFileUrl = null
+                  state.musicSheetSoundList.forEach((next: any) => {
+                    let track = next.track ? next.track : ''
+                    if (track.trim() == item.value) {
+                      audioFileUrl = next.audioFileUrl
+                    }
+                  })
+                  forms.musicSheetSoundList_YY.push({
+                    audioFileUrl: audioFileUrl, // 原音
+                    track: item.value, // 轨道
+                    audioPlayType: 'PLAY'
+                  })
+                  tracks.push(item.value)
+                })
+
+                // 处理没有声轨,但有原音
+                if (data.musicSheetType == 'CONCERT') {
+                  state.musicSheetSoundList.forEach((next: any) => {
+                    if (next.track && !tracks.includes(next.track.trim()) && next.audioPlayType == 'PLAY') {
+                      forms.musicSheetSoundList_YY.push({
+                        audioFileUrl: next.audioFileUrl, // 原音
+                        track: next.track ? next.track.trim() : '', // 轨道
+                        audioPlayType: 'PLAY'
+                      })
+                    }
+                  })
+                }
+              }
+            }
+          })
+        } catch (error) {
+        }
+      } else {
+        // 新增只能使用启用状态的数据
+        state.subjectList = state.subjectList.filter((next: any) => {
+          return next.enableFlag == true
+        })
+        // state.instrumentList = state.instrumentList.filter((next: any) => {
+        //   return next.enableFlag == true
+        // })
+      }
+      state.loading = false
+    })
+
+    return () => (
+        <div style="background: #fff; padding-top: 12px">
+          <NSpin show={state.loading}>
+            <NForm
+                class={styles.formContainer}
+                model={forms}
+                ref={formsRef}
+                label-placement="left"
+                label-width="150"
+                disabled={state.previewMode}
+            >
+              <NAlert showIcon={false} style={{marginBottom: '12px'}}>
+                基本信息
+              </NAlert>
+              <NGrid cols={2}>
+                <NFormItemGi
+                    label="曲目名称"
+                    path="name"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入曲目名称',
+                        trigger: ['input', 'blur']
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.name}
+                      placeholder="请输入曲目名称"
+                      maxlength={50}
+                      showCount
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="音乐人"
+                    path="composer"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请输入音乐人',
+                        trigger: ['input', 'blur']
+                      }
+                    ]}
+                >
+                  <NInput
+                      v-model:value={forms.composer}
+                      placeholder="请输入音乐人名称"
+                      showCount
+                      maxlength={14}
+                  />
+                </NFormItemGi>
+              </NGrid>
+              <NGrid cols={2}>
+                <NFormItemGi
+                    label="曲目封面"
+                    path="musicCover"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请上传曲目封面',
+                        trigger: ['input', 'blur']
+                      }
+                    ]}
+                >
+                  <UploadFile
+                      desc={'封面图'}
+                      disabled={state.previewMode}
+                      accept=".jpg,.jpeg,.png"
+                      tips="请上传大小1M以内的JPG、PNG图片"
+                      size={1}
+                      v-model:fileList={forms.musicCover}
+                      cropper
+                      bucketName="cbs"
+                      options={{
+                        autoCrop: true, //是否默认生成截图框
+                        enlarge: 2, //  图片放大倍数
+                        autoCropWidth: 200, //默框高度
+                        fixedBox: true, //是否固定截图框大认生成截图框宽度
+                        autoCropHeight: 200, //默认生成截图小 不允许改变
+                        previewsCircle: false, //预览图是否是原圆形
+                        title: '曲目封面'
+                      }}
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="曲目分类"
+                    path="musicCategoryId"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请选择曲目分类',
+                        trigger: ['change']
+                      }
+                    ]}
+                >
+                  <NCascader
+                      valueField="id"
+                      labelField="name"
+                      children-field="musicSheetCategoriesList"
+                      placeholder="请选择分类"
+                      v-model:value={forms.musicCategoryId}
+                      options={state.musicSheetCategories}
+                      clearable
+                  />
+                </NFormItemGi>
+              </NGrid>
+              <NGrid cols={2}>
+                <NFormItemGi
+                    label="作者属性"
+                    path="sourceType"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请选择作者属性',
+                        trigger: 'change'
+                      }
+                    ]}
+                >
+                  <NSelect
+                      v-model:value={forms.sourceType}
+                      options={getSelectDataFromObj(musicSheetSourceType)}
+                      placeholder="请选择作者属性"
+                      onUpdateValue={() => {
+                        // 发送变化,清理选择的所属人信息
+                        forms.musicSheetExtend = {}
+                        state.ownerName = null
+                        // forms.musicSheetExtend.userId = null
+                        // forms.musicSheetExtend.userName = null
+                        // forms.musicSheetExtend.applicationId = null
+                        // forms.musicSheetExtend.organizationRoleId = null
+                      }}
+                  />
+                </NFormItemGi>
+                {forms.sourceType === 'PERSON' && (
+                    <NFormItemGi
+                        label="所属人"
+                        path="musicSheetExtend.userId"
+                        rule={[
+                          {
+                            required: true,
+                            message: '请选择曲目所属人',
+                            trigger: ['input', 'change']
+                          }
+                        ]}
+                    >
+                      <NButton
+                          disabled={state.previewMode || !forms.sourceType}
+                          type="primary"
+                          size="small"
+                          text
+                          //v-auth="orchestraSubsidyStandard/update1597887579789053953"
+                          onClick={() => {
+                            state.showMusicSheetOwnerDialog = true
+                          }}
+                      >
+                        {state.ownerName ? state.ownerName : '请选择所属人'}
+                      </NButton>
+                    </NFormItemGi>
+                )}
+                {forms.sourceType === 'ORG' && (
+                    <NFormItemGi
+                        label="所属人"
+                        path="musicSheetExtend.organizationRoleId"
+                        rule={[
+                          {
+                            required: true,
+                            message: '请选择曲目所属机构',
+                            trigger: ['input', 'change']
+                          }
+                        ]}
+                    >
+                      <NButton
+                          disabled={state.previewMode || !forms.sourceType}
+                          type="primary"
+                          size="small"
+                          text
+                          //v-auth="orchestraSubsidyStandard/update1597887579789053953"
+                          onClick={() => {
+                            state.showMusicSheetOwnerDialog = true
+                          }}
+                      >
+                        {state.ownerName ? state.ownerName : '请选择所属机构'}
+                      </NButton>
+                    </NFormItemGi>
+                )}
+              </NGrid>
+              <NGrid cols={2}>
+                <NFormItemGi
+                    label="审核版本"
+                    path="appAuditFlag"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请选择审核版本',
+                        trigger: 'change',
+                        type: 'number'
+                      }
+                    ]}
+                >
+                  <NSelect
+                      options={
+                        [
+                          {
+                            label: '是',
+                            value: 1
+                          },
+                          {
+                            label: '否',
+                            value: 0
+                          }
+                        ] as any
+                      }
+                      v-model:value={forms.appAuditFlag}
+                  />
+                </NFormItemGi>
+              </NGrid>
+              <NAlert showIcon={false} style={{marginBottom: '12px'}}>
+                曲目设置
+              </NAlert>
+              <NGrid cols={2}>
+                <NFormItemGi
+                    label="播放模式"
+                    path="playMode"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请选择播放模式'
+                      }
+                    ]}
+                >
+                  <NRadioGroup
+                      v-model:value={forms.playMode}
+                      onUpdateValue={(value: string | number | boolean) => {
+                        if (value === 'MP3') {
+                          forms.playMode = 'MP3'
+                        } else {
+                          forms.playMode = 'MIDI'
+                        }
+                      }}
+                  >
+                    <NRadio value="MP3">MP3</NRadio>
+                    <NRadio value="MIDI">MID</NRadio>
+                  </NRadioGroup>
+                </NFormItemGi>
+                {forms.playMode === 'MP3' && (
+                    <NFormItemGi
+                        label="伴奏类型"
+                        path="audioType"
+                        rule={[
+                          {
+                            required: true,
+                            message: '请选择伴奏类型'
+                          }
+                        ]}
+                    >
+                      <NRadioGroup v-model:value={forms.audioType}>
+                        <NRadio value={'HOMEMODE'}>自制伴奏</NRadio>
+                        <NRadio value={'COMMON'}>普通伴奏</NRadio>
+                      </NRadioGroup>
+                    </NFormItemGi>
+                )}
+              </NGrid>
+              <NGrid cols={2}>
+                <NFormItemGi
+                    label="上传XML"
+                    path="xmlFileUrl"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请选择上传XML',
+                        trigger: ['change', 'input']
+                      }
+                    ]}
+                >
+                  <UploadFile
+                      desc={'XML文件'}
+                      disabled={state.previewMode}
+                      size={30}
+                      key={'xmlFileUrl'}
+                      v-model:fileList={forms.xmlFileUrl}
+                      tips="仅支持上传.xml/.mxml格式文件"
+                      listType="image"
+                      accept=".xml,.mxml,.evxml"
+                      bucketName="cloud-coach"
+                      text="点击上传XML文件"
+                      onReadFileInputEventAsArrayBuffer={readFileInputEventAsArrayBuffer}
+                      onRemove={() => {
+                        forms.multiTracksSelection = []
+                        state.partListNames = []
+                        forms.musicSheetSoundList_YY = []
+                        // forms.musicalInstrumentIdList = []
+                        // forms.subjectIds = []
+                      }}
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="评分标准"
+                    path="evaluationStandard"
+                    rule={[
+                      {
+                        required: true
+                      }
+                    ]}
+                >
+                  <NRadioGroup v-model:value={forms.evaluationStandard}>
+                    <NRadio value={'FREQUENCY'}>标准评测</NRadio>
+                    <NRadio value={'AMPLITUDE'}>打击乐(振幅)</NRadio>
+                    <NRadio value={'DECIBELS'}>节奏(分贝)</NRadio>
+                  </NRadioGroup>
+                </NFormItemGi>
+              </NGrid>
+
+              <NGrid cols={2}>
+                <NFormItemGi
+                    label="谱面渲染"
+                    path="musicSheetType"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请选择谱面渲染',
+                        trigger: 'change'
+                      }
+                    ]}
+                >
+                  <NRadioGroup v-model:value={forms.musicSheetType}>
+                    <NRadio value={'SINGLE'}>多声轨</NRadio>
+                    <NRadio value={'CONCERT'}>单声轨</NRadio>
+                  </NRadioGroup>
+                </NFormItemGi>
+                <NFormItemGi
+                    label="适用声部"
+                    path="isAllSubject"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请选择适用声部',
+                      }
+                    ]}
+                >
+                  <NRadioGroup v-model:value={forms.isAllSubject}>
+                    <NRadio value={false}>部分声部</NRadio>
+                    <NRadio value={true}>全部声部</NRadio>
+                  </NRadioGroup>
+                </NFormItemGi>
+              </NGrid>
+              {!forms.isAllSubject && (
+                  <NGrid cols={2}>
+                    <NFormItemGi
+                        label="可用声部"
+                        path="subjectIds"
+                        rule={[
+                          {
+                            required: true,
+                            message: '请选择可用声部',
+                            trigger: 'change',
+                            type: 'array'
+                          }
+                        ]}
+                    >
+                      <NSelect
+                          v-model:value={forms.subjectIds}
+                          options={state.subjectList}
+                          multiple
+                          filterable
+                          clearable
+                          placeholder="请选择可用声部"
+                          maxTagCount={2}
+                          onUpdateValue={async (val: any) => {
+                            await changeSubject(val)
+                          }}
+                      />
+                    </NFormItemGi>
+                    <NFormItemGi
+                        label="可用乐器"
+                        path="musicalInstrumentIdList"
+                        rule={[
+                          {
+                            required: true,
+                            message: '请选择可用乐器',
+                            trigger: 'change',
+                            type: 'array'
+                          }
+                        ]}
+                    >
+                      <NSelect
+                          placeholder="请选择可用乐器"
+                          options={state.instrumentList}
+                          v-model:value={forms.musicalInstrumentIdList}
+                          clearable
+                          multiple
+                          maxTagCount={2}
+                          onUpdateValue={async (value: any) => {
+                          }}
+                      />
+                    </NFormItemGi>
+                  </NGrid>
+              )}
+              <NGrid cols={2}>
+                <NFormItemGi
+                    label="速度"
+                    path="playSpeed"
+                    rule={[
+                      {
+                        required: false,
+                        message: '请输入速度'
+                      }
+                    ]}
+                >
+                  <NInputNumber
+                      placeholder="请输入速度"
+                      v-model:value={forms.playSpeed}
+                      min={0}
+                      style="width:100%"
+                  />
+                </NFormItemGi>
+              </NGrid>
+              <NGrid cols={1}>
+                <NFormItemGi
+                    label={`${forms.musicSheetType === 'SINGLE' ? '页面渲染声轨' : '用户可切换声轨'}`}
+                    path="multiTracksSelection"
+                    rule={[
+                      {
+                        required: true,
+                        message: `请选择${
+                            forms.musicSheetType === 'SINGLE' ? '页面渲染声轨' : '用户可切换声轨'
+                        }`,
+                        trigger: 'change',
+                        type: 'array'
+                      }
+                    ]}
+                >
+                  <NGrid style="padding-top: 4px;">
+                    <NGi span={24}>
+                      <NRadioGroup
+                          v-model:value={state.multiTracks}
+                          onUpdateValue={(value) => {
+                            checkMultiTracks(value)
+                          }}
+                      >
+                        <NRadio value={'all'}>全选</NRadio>
+                        <NRadio value={'allUncheck'}>重置</NRadio>
+                        <NRadio value={'invert'}>反选</NRadio>
+                      </NRadioGroup>
+                    </NGi>
+                    {state.partListNames && state.partListNames.length > 0 && (
+                        <NGi span={24} style={'margin-top:5px'}>
+                          <NFormItemGi
+                              label=""
+                              path="multiTracksSelection"
+                              rule={[
+                                {
+                                  required: false
+                                }
+                              ]}
+                          >
+                            <NCheckboxGroup v-model:value={forms.multiTracksSelection}>
+                              <NGrid yGap={2} cols={4}>
+                                {state.partListNames.map((item: any) => (
+                                    <NGi>
+                                      <NCheckbox value={item.value} label={item.label}/>
+                                    </NGi>
+                                ))}
+                              </NGrid>
+                            </NCheckboxGroup>
+                          </NFormItemGi>
+                        </NGi>
+                    )}
+                  </NGrid>
+                </NFormItemGi>
+              </NGrid>
+
+
+              <NAlert showIcon={false} style={{marginBottom: '12px'}}>
+                演唱文件
+              </NAlert>
+              <NGrid cols={2}>
+                <NFormItemGi
+                    label="是否播放节拍器"
+                    path="isPlaySingBeat"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请选择是否播放节拍器'
+                      }
+                    ]}
+                >
+                  <NRadioGroup v-model:value={forms.isPlaySingBeat}>
+                    <NRadio value={true}>是</NRadio>
+                    <NRadio value={false}>否</NRadio>
+                  </NRadioGroup>
+                </NFormItemGi>
+                {forms.isPlaySingBeat && (
+                    <NFormItemGi
+                        label="播放方式"
+                        path="isUseSingSystemBeat"
+                        rule={[
+                          {
+                            required: true,
+                            message: '请选择播放方式'
+                          }
+                        ]}
+                    >
+                      <NRadioGroup v-model:value={forms.isUseSingSystemBeat}>
+                        <NRadio value={true}>系统节拍器</NRadio>
+                        <NRadio value={false}>MP3节拍器</NRadio>
+                      </NRadioGroup>
+                    </NFormItemGi>
+                )}
+              </NGrid>
+              <NGrid cols={2}>
+                <NFormItemGi
+                    label="重复节拍时长"
+                    path="repeatedBeatsToSing"
+                    rule={[
+                      {
+                        required: false,
+                        message: '请选择是否重复节拍时长'
+                      }
+                    ]}
+                >
+                  <NRadioGroup v-model:value={forms.repeatedBeatsToSing}>
+                    <NRadio value={true}>是</NRadio>
+                    <NRadio value={false}>否</NRadio>
+                  </NRadioGroup>
+                </NFormItemGi>
+              </NGrid>
+              <NGrid cols={2}>
+                <NFormItemGi
+                    label="上传范唱"
+                    path="fSongFile"
+                    rule={[
+                      {
+                        required: false,
+                        message: '请选择上传范唱',
+                        trigger: ['change', 'input']
+                      }
+                    ]}
+                >
+                  <UploadFile
+                      desc={'上传范唱'}
+                      disabled={state.previewMode}
+                      size={30}
+                      key={'xmlFileUrl'}
+                      v-model:fileList={state.fSongFile}
+                      tips="仅支持上传.mp3格式文件"
+                      listType="image"
+                      accept=".mp3"
+                      bucketName="cloud-coach"
+                      text="点击上传范唱文件"
+                      onRemove={() => {
+                      }}
+                  />
+                </NFormItemGi>
+                <NFormItemGi
+                    label="上传伴唱"
+                    path="bSongFile"
+                    rule={[
+                      {
+                        required: false,
+                        message: '请选择上传.MID格式文件'
+                      }
+                    ]}
+                >
+                  <UploadFile
+                      desc={'上传伴唱'}
+                      disabled={state.previewMode}
+                      size={30}
+                      v-model:fileList={state.bSongFile}
+                      tips="仅支持上传.mp3格式文件"
+                      listType="image"
+                      accept=".mp3"
+                      bucketName="cloud-coach"
+                      text="点击上传伴唱文件"
+                  />
+                </NFormItemGi>
+              </NGrid>
+              <NGrid cols={2}>
+                <NFormItemGi
+                    label="上传唱名"
+                    path="solmizationFileUrl"
+                    rule={[
+                      {
+                        required: false,
+                        message: '请选择上传唱名',
+                        trigger: ['change', 'input']
+                      }
+                    ]}
+                >
+                  <UploadFile
+                      desc={'上传唱名'}
+                      disabled={state.previewMode}
+                      size={30}
+                      key={'xmlFileUrl'}
+                      v-model:fileList={forms.solmizationFileUrl}
+                      tips="仅支持上传.mp3格式文件"
+                      listType="image"
+                      accept=".mp3"
+                      bucketName="cloud-coach"
+                      text="点击上传唱名文件"
+                      onRemove={() => {
+                      }}
+                  />
+                </NFormItemGi>
+              </NGrid>
+              <NAlert showIcon={false} style={{marginBottom: '12px'}}>
+                演奏文件
+              </NAlert>
+              <NGrid cols={2}>
+                <NFormItemGi
+                    label="是否播放节拍器"
+                    path="isPlayBeat"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请选择是否播放节拍器'
+                      }
+                    ]}
+                >
+                  <NRadioGroup v-model:value={forms.isPlayBeat}>
+                    <NRadio value={true}>是</NRadio>
+                    <NRadio value={false}>否</NRadio>
+                  </NRadioGroup>
+                </NFormItemGi>
+                {forms.isPlayBeat && (
+                    <NFormItemGi
+                        label="播放方式"
+                        path="isUseSystemBeat"
+                        rule={[
+                          {
+                            required: true,
+                            message: '请选择播放方式'
+                          }
+                        ]}
+                    >
+                      <NRadioGroup v-model:value={forms.isUseSystemBeat}>
+                        <NRadio value={true}>系统节拍器</NRadio>
+                        <NRadio value={false}>MP3节拍器</NRadio>
+                      </NRadioGroup>
+                    </NFormItemGi>
+                )}
+              </NGrid>
+              <NGrid cols={2}>
+                <NFormItemGi
+                    label="重复节拍时长"
+                    path="repeatedBeats"
+                    rule={[
+                      {
+                        required: false,
+                        message: '请选择是否重复节拍时长'
+                      }
+                    ]}
+                >
+                  <NRadioGroup v-model:value={forms.repeatedBeats}>
+                    <NRadio value={true}>是</NRadio>
+                    <NRadio value={false}>否</NRadio>
+                  </NRadioGroup>
+                </NFormItemGi>
+                <NFormItemGi
+                    label="是否显示指法"
+                    path="isShowFingering"
+                    rule={[
+                      {
+                        required: true,
+                        message: '请选择是否显示指法'
+                      }
+                    ]}
+                >
+                  <NRadioGroup v-model:value={forms.isShowFingering}>
+                    <NRadio value={true}>是</NRadio>
+                    <NRadio value={false}>否</NRadio>
+                  </NRadioGroup>
+                </NFormItemGi>
+              </NGrid>
+              <NGrid cols={2}>
+                {forms.playMode === 'MP3' && (
+                    <NFormItemGi
+                        label="上传伴奏"
+                        path="musicSheetAccompanimentList"
+                        rule={[
+                          {
+                            required: false,
+                            message: '请选择上传.mp3'
+                          }
+                        ]}
+                    >
+                      <UploadFile
+                          disabled={state.previewMode}
+                          size={30}
+                          v-model:imageList={state.musicSheetAccompanimentUrlList}
+                          tips="仅支持上传.mp3格式文件"
+                          listType="image"
+                          accept=".mp3"
+                          bucketName="cloud-coach"
+                          text="点击上传伴奏文件"
+                          max={1}
+                          desc={'上传伴奏文件'}
+                          onUpload:success={(file) => {
+                            state.musicSheetAccompanimentUrls = [state.musicSheetAccompanimentUrls, file.url].filter(Boolean).join(',')
+                            state.musicSheetAccompanimentUrlList = state.musicSheetAccompanimentUrls?.split(',').filter(Boolean)
+
+                            // 清除伴奏
+                            // forms.musicSheetAccompanimentList = forms.musicSheetAccompanimentList.filter((next: any) => {
+                            //   return next.audioPlayType == 'SING'
+                            // })
+                            forms.musicSheetAccompanimentList = []
+                            for (let i = 0; i < state.musicSheetAccompanimentUrlList.length; i++) {
+                              forms.musicSheetAccompanimentList.push({
+                                audioFileUrl: state.musicSheetAccompanimentUrlList[i],
+                                sortNumber: i + 1,
+                                audioPlayType: 'PLAY'
+                              })
+                            }
+                          }}
+                          onRemove={() => {
+                            state.musicSheetAccompanimentUrlList = []
+                            state.musicSheetAccompanimentUrls = ''
+                          }}
+                          // onReadFileInputEventAsArrayBuffer={readFileInputEventAsArrayBuffer}
+                          multiple={true}
+                      />
+                    </NFormItemGi>
+                )}
+                {forms.isAllSubject && forms.musicSheetType == 'SINGLE' && (
+                    <NFormItemGi
+                        label="上传原音"
+                        path="musicSheetSoundList_all_subject"
+                        rule={[
+                          {
+                            required: false,
+                            message: '请选择上传原音',
+                            trigger: ['change', 'input']
+                          }
+                        ]}
+                    >
+                      <UploadFile
+                          desc={'上传原音'}
+                          disabled={state.previewMode}
+                          size={30}
+                          max={1}
+                          v-model:fileList={forms.musicSheetSoundList_all_subject}
+                          tips="仅支持上传.mp3格式文件"
+                          listType="image"
+                          accept=".mp3"
+                          bucketName="cloud-coach"
+                          text="点击上传原音"
+                          onRemove={() => {
+                          }}
+                      />
+                    </NFormItemGi>
+                )}
+              </NGrid>
+
+              {/*渐变速*/}
+              {!!gradualData.list.length && (
+                  <>
+                    <NAlert showIcon={false} type="info">
+                      识别到共1处渐变速度,请输入Dorico对应小节时间信息
+                    </NAlert>
+                    <NFormItem label="rit." required style={{marginTop: '10px'}}>
+                      <NSpace vertical>
+                        {gradualData.list.map((n: any, ni: number) => (
+                            <NInputGroup>
+                              <NFormItem
+                                  path={`graduals.${n[0].measureIndex}`}
+                                  rule={[
+                                    {required: true, message: '请输入合奏曲目时间'},
+                                    {
+                                      pattern: /^((\d{2}):?){2,3}$/,
+                                      message: '请输入正确的曲目时间',
+                                      trigger: 'blur'
+                                    }
+                                  ]}
+                              >
+                                <NInputGroup>
+                                  <NInputGroupLabel>{n[0].measureIndex}小节开始</NInputGroupLabel>
+                                  <NInput
+                                      placeholder="00:00:00"
+                                      v-model:value={forms.graduals[n[0].measureIndex]}
+                                  ></NInput>
+                                </NInputGroup>
+                              </NFormItem>
+                              <div style={{lineHeight: '30px', padding: '0 4px'}}>~</div>
+                              <NFormItem
+                                  path={`graduals.${n[1].measureIndex}`}
+                                  rule={[
+                                    {required: true, message: '请输入合奏曲目时间'},
+                                    {
+                                      pattern: /^((\d{2}):?){2,3}$/,
+                                      message: '请输入正确的曲目时间',
+                                      trigger: 'blur'
+                                    }
+                                  ]}
+                              >
+                                <NInputGroup>
+                                  <NInput
+                                      placeholder="00:00:00"
+                                      v-model:value={forms.graduals[n[1].measureIndex]}
+                                  ></NInput>
+                                  <NInputGroupLabel>{n[1].measureIndex}小节结束</NInputGroupLabel>
+                                </NInputGroup>
+                              </NFormItem>
+                            </NInputGroup>
+                        ))}
+                      </NSpace>
+                    </NFormItem>
+                  </>
+              )}
+              {/*独奏*/}
+              {forms.musicSheetType == 'SINGLE' && forms.playMode === 'MP3' && !forms.isAllSubject && forms.musicSheetSoundList_YZ.map((item: any, index: any) => {
+                return (
+                    <>
+                      {forms.musicalInstrumentIdList.includes(item.musicalInstrumentId) && (
+                          <NGrid class={styles.audioSection}>
+                            <NFormItemGi
+                                span={12}
+                                label={item.musicalInstrumentName}
+                                path={`musicSheetSoundList_YZ[${index}].audioFileUrl`}
+                                rule={[
+                                  {
+                                    required: true,
+                                    message: `请上传乐器演奏文件`
+                                  }
+                                ]}
+                            >
+                              <UploadFile
+                                  desc={'乐器演奏文件'}
+                                  disabled={state.previewMode}
+                                  size={100}
+                                  v-model:fileList={item.audioFileUrl}
+                                  tips="仅支持上传.mp3格式文件"
+                                  listType="image"
+                                  accept=".mp3"
+                                  text={"点击上传MP3文件"}
+                                  bucketName="cloud-coach"
+                              />
+                            </NFormItemGi>
+                          </NGrid>
+                      )}
+                    </>
+                )
+              })
+              }
+              {/*合奏*/}
+              {forms.musicSheetType == 'CONCERT' && forms.playMode === 'MP3' && forms.musicSheetSoundList_YY.length > 0 && (
+                  <>
+                    {forms.musicSheetSoundList_YY.map((item: any, index: number) => {
+                      return (
+                          <>
+                            {(!containOther(item.track) ||
+                                (item.track?.toLocaleUpperCase?.() != 'COMMON' &&
+                                    forms.multiTracksSelection.includes(item.track))) && (
+                                <NGrid
+                                    class={styles.audioSection}
+                                    // v-show={forms.multiTracksSelection.indexOf(item.track) > -1}
+                                >
+                                  <NFormItemGi
+                                      span={12}
+                                      label="原音"
+                                      path={`musicSheetSoundList_YY[${index}].audioFileUrl`}
+                                      rule={[
+                                        {
+                                          // required: forms.multiTracksSelection.indexOf(forms.musicSheetSoundList_YY[index].audioFileUrl) > -1,
+                                          required: true,
+                                          message: `请上传${
+                                              item.track ? item.track + '的' : '第' + (index + 1) + '个'
+                                          }原音`
+                                        }
+                                      ]}
+                                  >
+                                    <UploadFile
+                                        desc={'原音文件'}
+                                        disabled={state.previewMode}
+                                        size={100}
+                                        v-model:fileList={item.audioFileUrl}
+                                        tips="仅支持上传.mp3格式文件"
+                                        listType="image"
+                                        accept=".mp3"
+                                        bucketName="cloud-coach"
+                                    />
+                                  </NFormItemGi>
+                                  {state.partListNames.length > 0 && (
+                                      <NFormItemGi
+                                          span={12}
+                                          label="所属轨道"
+                                          path={`musicSheetSoundList_YY[${index}].track`}
+                                          rule={[
+                                            {
+                                              required: false,
+                                              message: '请选择所属轨道'
+                                            }
+                                          ]}
+                                      >
+                                        <NSelect
+                                            placeholder="请选择所属轨道"
+                                            value={item.track}
+                                            options={initPartsListStatus(item.track)}
+                                            onUpdateValue={(value: any) => {
+                                              const track = item.track
+
+                                              if (track) {
+                                                // 声轨交换
+                                                forms.musicSheetSoundList_YY.forEach((next: any) => {
+                                                  if (next.track == value) {
+                                                    next.track = track
+                                                  }
+                                                })
+
+                                                const index = forms.multiTracksSelection.indexOf(item.track)
+                                                forms.multiTracksSelection.splice(index, 1)
+                                              } else {
+                                                forms.musicSheetSoundList_YY = forms.musicSheetSoundList_YY.filter(
+                                                    (next: any) => {
+                                                      return next.track != value
+                                                    }
+                                                )
+                                              }
+
+                                              if (value && !forms.multiTracksSelection.includes(value)) {
+                                                forms.multiTracksSelection.push(value)
+                                              }
+                                              item.track = value
+                                            }}
+                                        />
+                                      </NFormItemGi>
+                                  )}
+                                  <NGi class={styles.btnRemove}>
+                                    <NButton
+                                        type="primary"
+                                        text
+                                        // disabled={forms.musicSheetSoundList_YY.length === 1}
+                                        onClick={() => removeSys(index)}
+                                    >
+                                      删除
+                                    </NButton>
+                                  </NGi>
+                                </NGrid>
+                            )}
+                          </>
+                      )
+                    })}
+                  </>
+              )}
+
+            </NForm>
+          </NSpin>
+          {props.type !== 'preview' && (
+              <NSpace justify="end" style="padding-top:12px">
+                <NButton type="default" onClick={() => emit('close')}>
+                  取消
+                </NButton>
+                <NButton
+                    type="primary"
+                    onClick={() => onSubmit()}
+                    loading={btnLoading.value}
+                    disabled={btnLoading.value}
+                >
+                  确认
+                </NButton>
+              </NSpace>
+          )}
+
+          <NModal
+              v-model:show={state.showMusicSheetOwnerDialog}
+              preset="dialog"
+              showIcon={false}
+              maskClosable={false}
+              title="所属人"
+              style={{width: '800px'}}
+          >
+            <MusicSheetOwnerDialog
+                musicSheetExtend={forms.musicSheetExtend}
+                sourceType={forms.sourceType}
+                appData={state.appData}
+                onClose={() => {
+                  state.showMusicSheetOwnerDialog = false
+                }}
+                onChoseMusicSheetOwnerData={(musicSheetOwnerData) => {
+                  forms.musicSheetExtend = {
+                    ...musicSheetOwnerData
+                  }
+                  setOwnerName()
+                }}
+            />
+          </NModal>
+
+          <NModal
+              class={styles.productModal}
+              title="自动生成曲谱图片"
+              v-model:show={state.productOpen}
+              preset="dialog"
+              closeOnEsc={false}
+              maskClosable={false}
+              showIcon={false}
+          >
+            <MusicCreateImg
+                xmlFileUrl={forms.xmlFileUrl || ''}
+                onClose={() => (state.productOpen = false)}
+                onConfirm={async (item: any) => {
+                  // 保存
+                  try {
+                    forms.musicImg = item.musicImg
+                    forms.musicFirstImg = item.musicFirstImg
+                    forms.musicJianImg = item.musicJianImg
+                    onSubmit()
+                  } catch (e: any) {
+                    //
+                    console.log(e, 'e')
+                  }
+                  setTimeout(() => {
+                    state.isAutoSave = false
+                  }, 50)
+                }}
+            />
+          </NModal>
+        </div>
+    )
+  }
+})

+ 5 - 3
src/views/music-library/project-music-sheet/module/gym/addMusic.tsx

@@ -156,6 +156,7 @@ export default defineComponent({
     const saveForm = ref()
 
     const onSearch = () => {
+      checkedRowKeysRef.value = []
       saveForm.value?.submit()
     }
     const onBtnReset = () => {
@@ -238,7 +239,7 @@ export default defineComponent({
         key: 'composer'
       },
       {
-        title: '多声轨渲染',
+        title: '谱面渲染',
         key: 'musicSheetType',
         render: (row: any) => {
           return (
@@ -770,9 +771,9 @@ export default defineComponent({
                     clearable
                   />
                 </NFormItem>
-                <NFormItem label="多声轨渲染" path="musicSheetType">
+                <NFormItem label="谱面渲染" path="musicSheetType">
                   <NSelect
-                    placeholder="请选择多声轨渲染"
+                    placeholder="请选择谱面渲染"
                     v-model:value={state.searchForm.musicSheetType}
                     options={getSelectDataFromObj(musicSheetType)}
                     clearable
@@ -864,6 +865,7 @@ export default defineComponent({
                 columns={columns()}
                 data={state.dataList}
                 rowKey={(row: any) => row.id}
+                v-model:checkedRowKeys={checkedRowKeysRef.value}
                 onUpdateCheckedRowKeys={handleCheck}
               ></NDataTable>
               <Pagination

+ 5 - 4
src/views/music-library/project-music-sheet/module/gym/music-sheet-gym.tsx

@@ -173,6 +173,7 @@ export default defineComponent({
     const saveForm = ref()
 
     const onSearch = () => {
+      checkedRowKeysRef.value = []
       saveForm.value?.submit()
     }
     const onBtnReset = () => {
@@ -346,7 +347,7 @@ export default defineComponent({
                 <NDescriptionsItem label="曲目来源">
                   {getMapValueByKey(row.sourceType, new Map(Object.entries(musicSheetSourceType)))}
                 </NDescriptionsItem>
-                <NDescriptionsItem label="多声轨渲染">
+                <NDescriptionsItem label="谱面渲染">
                   {getMapValueByKey(row.musicSheetType, new Map(Object.entries(musicSheetType)))}
                 </NDescriptionsItem>
                 <NDescriptionsItem label="所属人">
@@ -541,9 +542,9 @@ export default defineComponent({
                 clearable
               ></NSelect>
             </NFormItem>
-            <NFormItem label="多声轨渲染" path="subjectType">
+            <NFormItem label="谱面渲染" path="subjectType">
               <NSelect
-                placeholder="请选择多声轨渲染"
+                placeholder="请选择谱面渲染"
                 v-model:value={state.searchForm.musicSheetType}
                 options={getSelectDataFromObj(musicSheetType)}
                 clearable
@@ -684,7 +685,7 @@ export default defineComponent({
               columns={columns()}
               data={state.dataList}
               rowKey={(row: any) => row.applicationExtendId}
-              onUpdateCheckedRowKeys={handleCheck}
+              v-model:checkedRowKeys={checkedRowKeysRef.value}
               scrollX={'1400'}
             ></NDataTable>
 

+ 5 - 3
src/views/music-library/project-music-sheet/module/gyt/addMusic.tsx

@@ -152,6 +152,7 @@ export default defineComponent({
     const saveForm = ref()
 
     const onSearch = () => {
+      checkedRowKeysRef.value = []
       saveForm.value?.submit()
     }
     const onBtnReset = () => {
@@ -263,7 +264,7 @@ export default defineComponent({
         key: 'composer'
       },
       {
-        title: '多声轨渲染',
+        title: '谱面渲染',
         key: 'musicSheetType',
         render: (row: any) => {
           return (
@@ -795,9 +796,9 @@ export default defineComponent({
                     clearable
                   />
                 </NFormItem>
-                <NFormItem label="多声轨渲染" path="musicSheetType">
+                <NFormItem label="谱面渲染" path="musicSheetType">
                   <NSelect
-                    placeholder="请选择多声轨渲染"
+                    placeholder="请选择谱面渲染"
                     v-model:value={state.searchForm.musicSheetType}
                     options={getSelectDataFromObj(musicSheetType)}
                     clearable
@@ -888,6 +889,7 @@ export default defineComponent({
                 data={state.dataList}
                 rowKey={(row: any) => row.id}
                 onUpdateCheckedRowKeys={handleCheck}
+                v-model:checkedRowKeys={checkedRowKeysRef.value}
               ></NDataTable>
               <Pagination
                 v-model:page={state.pagination.page}

+ 4 - 3
src/views/music-library/project-music-sheet/module/gyt/music-sheet-gyt.tsx

@@ -130,6 +130,7 @@ export default defineComponent({
     const saveForm = ref()
 
     const onSearch = () => {
+      checkedRowKeysRef.value = []
       saveForm.value?.submit()
     }
     const onBtnReset = () => {
@@ -516,9 +517,9 @@ export default defineComponent({
                 clearable
               ></NSelect>
             </NFormItem>
-            <NFormItem label="多声轨渲染" path="subjectType">
+            <NFormItem label="谱面渲染" path="subjectType">
               <NSelect
-                placeholder="请选多声轨渲染"
+                placeholder="请选谱面渲染"
                 v-model:value={state.searchForm.musicSheetType}
                 options={getSelectDataFromObj(musicSheetType)}
                 clearable
@@ -650,7 +651,7 @@ export default defineComponent({
               columns={columns()}
               data={state.dataList}
               rowKey={(row: any) => row.applicationExtendId}
-              onUpdateCheckedRowKeys={handleCheck}
+              v-model:checkedRowKeys={checkedRowKeysRef.value}
               scrollX={'1200'}
             ></NDataTable>
 

+ 5 - 3
src/views/music-library/project-music-sheet/module/klx/addMusic.tsx

@@ -168,6 +168,7 @@ export default defineComponent({
     const saveForm = ref()
 
     const onSearch = () => {
+      checkedRowKeysRef.value = []
       saveForm.value?.submit()
     }
     const onBtnReset = () => {
@@ -299,7 +300,7 @@ export default defineComponent({
         key: 'composer'
       },
       {
-        title: '多声轨渲染',
+        title: '谱面渲染',
         key: 'musicSheetType',
         render: (row: any) => {
           return (
@@ -1161,9 +1162,9 @@ export default defineComponent({
                     clearable
                   />
                 </NFormItem>
-                <NFormItem label="多声轨渲染" path="musicSheetType">
+                <NFormItem label="谱面渲染" path="musicSheetType">
                   <NSelect
-                    placeholder="请选择多声轨渲染"
+                    placeholder="请选择谱面渲染"
                     v-model:value={state.searchForm.musicSheetType}
                     options={getSelectDataFromObj(musicSheetType)}
                     clearable
@@ -1255,6 +1256,7 @@ export default defineComponent({
                 data={state.dataList}
                 rowKey={(row: any) => row.id}
                 onUpdateCheckedRowKeys={handleCheck}
+                v-model:checkedRowKeys={checkedRowKeysRef.value}
               ></NDataTable>
               <Pagination
                 v-model:page={state.pagination.page}

+ 5 - 4
src/views/music-library/project-music-sheet/module/klx/music-sheet-klx.tsx

@@ -136,6 +136,7 @@ export default defineComponent({
     const saveForm = ref()
 
     const onSearch = () => {
+      checkedRowKeysRef.value = []
       saveForm.value?.submit()
     }
     const onBtnReset = () => {
@@ -337,7 +338,7 @@ export default defineComponent({
                 <NDescriptionsItem label="曲目来源">
                   {getMapValueByKey(row.sourceType, new Map(Object.entries(musicSheetSourceType)))}
                 </NDescriptionsItem>
-                <NDescriptionsItem label="多声轨渲染">
+                <NDescriptionsItem label="谱面渲染">
                   {getMapValueByKey(row.musicSheetType, new Map(Object.entries(musicSheetType)))}
                 </NDescriptionsItem>
                 <NDescriptionsItem label="所属人">
@@ -564,9 +565,9 @@ export default defineComponent({
                 clearable
               ></NSelect>
             </NFormItem>
-            <NFormItem label="多声轨渲染" path="subjectType">
+            <NFormItem label="谱面渲染" path="subjectType">
               <NSelect
-                placeholder="请选择多声轨渲染"
+                placeholder="请选择谱面渲染"
                 v-model:value={state.searchForm.musicSheetType}
                 options={getSelectDataFromObj(musicSheetType)}
                 clearable
@@ -697,7 +698,7 @@ export default defineComponent({
               columns={columns()}
               data={state.dataList}
               rowKey={(row: any) => row.applicationExtendId}
-              onUpdateCheckedRowKeys={handleCheck}
+              v-model:checkedRowKeys={checkedRowKeysRef.value}
               scrollX={'2000'}
             ></NDataTable>
 

+ 6 - 3
src/views/music-library/project-music-sheet/module/kt/addMusic.tsx

@@ -154,6 +154,7 @@ export default defineComponent({
     const saveForm = ref()
 
     const onSearch = () => {
+      checkedRowKeysRef.value = []
       saveForm.value?.submit()
     }
     const onBtnReset = () => {
@@ -243,7 +244,7 @@ export default defineComponent({
         key: 'composer'
       },
       {
-        title: '多声轨渲染',
+        title: '谱面渲染',
         key: 'musicSheetType',
         render: (row: any) => {
           return (
@@ -346,6 +347,7 @@ export default defineComponent({
               labelField="name"
               children-field="children"
               placeholder="请选择曲目分类"
+              checkStrategy={"child"}
               value={row.projectMusicCategoryId}
               options={state.musicSheetCategories}
               onUpdateValue={(value: any) => {
@@ -802,9 +804,9 @@ export default defineComponent({
                     clearable
                   />
                 </NFormItem>
-                <NFormItem label="多声轨渲染" path="musicSheetType">
+                <NFormItem label="谱面渲染" path="musicSheetType">
                   <NSelect
-                    placeholder="请选择多声轨渲染"
+                    placeholder="请选择谱面渲染"
                     v-model:value={state.searchForm.musicSheetType}
                     options={getSelectDataFromObj(musicSheetType)}
                     clearable
@@ -896,6 +898,7 @@ export default defineComponent({
                 data={state.dataList}
                 rowKey={(row: any) => row.id}
                 onUpdateCheckedRowKeys={handleCheck}
+                v-model:checkedRowKeys={checkedRowKeysRef.value}
               ></NDataTable>
               <Pagination
                 v-model:page={state.pagination.page}

+ 5 - 4
src/views/music-library/project-music-sheet/module/kt/music-sheet-kt.tsx

@@ -159,6 +159,7 @@ export default defineComponent({
     const saveForm = ref()
 
     const onSearch = () => {
+      checkedRowKeysRef.value = []
       saveForm.value?.submit()
     }
     const onBtnReset = () => {
@@ -318,7 +319,7 @@ export default defineComponent({
                 <NDescriptionsItem label="曲目来源">
                   {getMapValueByKey(row.sourceType, new Map(Object.entries(musicSheetSourceType)))}
                 </NDescriptionsItem>
-                <NDescriptionsItem label="多声轨渲染">
+                <NDescriptionsItem label="谱面渲染">
                   {getMapValueByKey(row.musicSheetType, new Map(Object.entries(musicSheetType)))}
                 </NDescriptionsItem>
                 <NDescriptionsItem label="所属人">
@@ -520,9 +521,9 @@ export default defineComponent({
                 clearable
               ></NSelect>
             </NFormItem>
-            <NFormItem label="多声轨渲染" path="subjectType">
+            <NFormItem label="谱面渲染" path="subjectType">
               <NSelect
-                placeholder="请选择多声轨渲染"
+                placeholder="请选择谱面渲染"
                 v-model:value={state.searchForm.musicSheetType}
                 options={getSelectDataFromObj(musicSheetType)}
                 clearable
@@ -664,7 +665,7 @@ export default defineComponent({
               columns={columns()}
               data={state.dataList}
               rowKey={(row: any) => row.applicationExtendId}
-              onUpdateCheckedRowKeys={handleCheck}
+              v-model:checkedRowKeys={checkedRowKeysRef.value}
               scrollX={'1400'}
             ></NDataTable>
 

+ 1 - 0
src/views/music-library/project-music-sheet/module/kt/updateMusic.tsx

@@ -105,6 +105,7 @@ export default defineComponent({
                     placeholder="请选择乐谱教材"
                     value={forms.musicSheetCategoryId}
                     options={state.musicSheetCategories}
+                    checkStrategy={"child"}
                     onUpdateValue={(value: any) => {
                       forms.musicSheetCategoryId = value
                     }}