import type { SelectOption } from 'naive-ui'
import {
  NAlert,
  NButton,
  NCascader,
  NCheckbox,
  NCheckboxGroup,
  NDivider,
  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, watch } 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 MusiceBeatTime from './musiceBeatTime'
import MusicPlatform from './music-platform'

/**
 * 获取指定元素下一个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 && getNextvNoteDuration(i)) {
        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')
        // measureIndex: measure?.getAttribute('number') ? Number(measure?.getAttribute('number')) : measures.indexOf(measure),
        type: ele.tagName,
        allDuration,
        leftDuration
      })
    }
  }

  // 结尾处手动插入一个音符节点
  eles.push({
    ele: notes[notes.length - 1],
    index: notes.length,
    noteInMeasureIndex: 0,
    textContent: '',
    type: 'metronome',
    allDuration: 1,
    leftDuration: 1,
    measureIndex: measures.length
  })

  const gradualNotes: 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 type FormatXMLInfo = {
  speed: number
  title: string
  composer: string
  partNames: string[]
}

/** 获取xml基本信息，标题，速度等信息 */
export const getXmlInfo = (xml: string): FormatXMLInfo => {
  const data: FormatXMLInfo = {
    /** 速度 */
    speed: 0,
    /** 标题 */
    title: '',
    /** 作曲人 */
    composer: '',
    /** 声部列表 */
    partNames: []
  }
  const xmlParse = new DOMParser().parseFromString(xml, 'text/xml')
  data.title = xmlParse.getElementsByTagName('work-title')[0]?.textContent || ''
  data.composer = xmlParse.getElementsByTagName('creator')[0]?.textContent || ''
  const measures = xmlParse.getElementsByTagName('measure')

  for (const item of Array.from(xmlParse.getElementsByTagName('part-name'))) {
    if (item.textContent?.trim()) {
      data.partNames.push(item.textContent)
    }
  }

  for (const measure of Array.from(measures)) {
    const perMinute = measure.getElementsByTagName('per-minute')
    if (perMinute.length && perMinute[perMinute.length - 1]) {
      data.speed = parseFloat(perMinute[perMinute.length - 1].textContent || '0')
      break
    }
  }
  return data
}

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 as any, // 音乐人
      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: true,
      musicSheetType: 'CONCERT', // 曲目类型
      sourceType: 'PLATFORM' 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, // 适用声部
      isMixBeat: true, // 是否生成节拍器
      musicPdfUrl: '', // 总谱五线谱PDF
      firstPdfUrl: '',  // 总谱首调PDF
      jianPdfUrl: '', // 总谱固定PDF

      fSongList: [] as any, // 范唱列表
      isScoreRender: true, // 总谱渲染
      defaultScoreRender: true, // 演奏是否默认展示总谱渲染
      scoreAudioFileUrl: null as any // 总谱文件
    })
    const state = reactive({
      loading: false,
      musicUpdateLoading: false, // 是否在加载 中
      previewMode: false, //是否是预览模式
      tagList: [...props.tagList] as any, // 标签列表
      xmlFirstSpeed: null as any, // 第一个音轨速度
      partListNames: [] as any, // 所有音轨声部列表
      musicSheetCategories: [] as any,
      musicSheetAccompanimentUrl: null as any,
      instrumentData: [],
      instrumentList: [] as any,
      instrumentIdNameMap: new Map() as any,
      subjectList: [] as any,
      showMusicSheetOwnerDialog: false, //所属人弹框
      // musicSheetOwnerData: {}, //所属人信息
      multiTracks: null as any,
      multiInstruments: null,
      appData: [], // 应用列表
      ownerName: null as any, // 所属人名称描述

      productOpen: false, // 是否打开自动生成图片
      productItem: {} as any,
      productIfameSrc: '',
      isAutoSave: false, // 是否自动保存
      bSongFile: null as any, // 伴唱
      musicSheetSoundList: [] as any,

      subjectDisabled: false, // 声部不可用
      instrumentDisabled: false, // 乐器不可用
      initFSongMap: new Map() as any, //初始化的范唱

      showUseProject: false,
      showUseProjectId: null as any,
      useProjectData: [] as any,

      // 修改：修改内容XML（生成图片）、MP3（生成节拍器）；其他情况无需生成图片、节拍器
      isCreateImg: false, // 是否生成图片
      isBeatTime: false // 是否生成节拍器
    })
    const gradualData = reactive({
      list: [] as any[],
      gradualRefs: [] as any[]
    })
    const beatTimeData = reactive({
      beatTimeOpen: false,
      musicId: ''
    })
    watch(
      () => forms.multiTracksSelection,
      (value) => {
        // 在修改的时候不用自动更新
        if (state.musicUpdateLoading) {
          state.musicUpdateLoading = false
          return
        }
        initInstrumentAndSubjectByTrack(value)
        initFSongList()
      }
    )

    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) => {
                set.push(code.replaceAll(' ', '').toLocaleLowerCase())
              })
            }
          })
          let unDefinedTrack = [] as any
          forms.multiTracksSelection.forEach((item: any) => {
            if (item && !isPtrack(item)) {
              let contain = false
              let code = item.replace(' ', '').toLocaleLowerCase()
              for (let i = 0; i < set.length; i++) {
                if (code.startsWith(set[i])) {
                  contain = true
                  break
                }
              }
              if (!contain) {
                unDefinedTrack.push(item)
              }
            }
          })
          if (unDefinedTrack.length > 0) {
            dialog.warning({
              title: '提示',
              content: `声轨未配置：${unDefinedTrack.join(',')}`,
              positiveText: '确定',
              onPositiveClick: () => {}
            })
            return
          }
        }

        try {
          //extConfigJson: {"repeatedBeats":0,"gradualTimes":{"75":"02:38:60","77":"02:43:39"}}
          let audioPlayTypes = new Set() as any
          let musicSheetSoundList = []
          let musicSheetType = forms.musicSheetType

          let existYzFile = false
          // console.log({
          //   musicSheetType,
          //   fSongList: forms.fSongList,
          //   isAllSubject: forms.isAllSubject,
          //   musicSheetSoundList_all_subject: forms.musicSheetSoundList_all_subject,
          //   musicSheetSoundList_YZ: forms.musicSheetSoundList_YZ,
          //   playMode: forms.playMode,
          //   musicalInstrumentIdList: forms.musicalInstrumentIdList
          // })

          // 判断 伴唱 范唱 唱名只有上传一个都可以上传
          let existFSFile = false
          for (let i = 0; i < forms.fSongList.length; i++) {
            let fSong = forms.fSongList[i]
            if (fSong.audioFileUrl || fSong.solmizationFileUrl || fSong.femaleSolmizationFileUrl) {
              musicSheetSoundList.push(fSong)
              audioPlayTypes.add('SING')
              existFSFile = true
            }
          }

          if (musicSheetType == 'SINGLE') {
            if (forms.isAllSubject) {
              if (forms.musicSheetSoundList_all_subject) {
                audioPlayTypes.add('PLAY')
                musicSheetSoundList.push({
                  audioFileUrl: forms.musicSheetSoundList_all_subject,
                  musicSheetId: props.data.id,
                  audioPlayType: 'PLAY'
                })
                existYzFile = true
              }
            } else {
              if (forms.musicSheetSoundList_YZ.length > 0) {
                forms.musicSheetSoundList_YZ.forEach((musicSheetSound: any) => {
                  if (
                    forms.musicalInstrumentIdList.includes(musicSheetSound.musicalInstrumentId) &&
                    musicSheetSound.audioFileUrl
                  ) {
                    existYzFile = true
                    musicSheetSoundList.push({
                      ...musicSheetSound,
                      musicSheetId: props.data.id
                    })
                    // 判断是否显示
                    if (!audioPlayTypes.has('PLAY')) {
                      audioPlayTypes.add('PLAY')
                    }
                  }
                })
              }
            }
          } else if (musicSheetType == 'CONCERT') {
            forms.musicSheetSoundList_YY.forEach((musicSheetSound: any) => {
              if (
                musicSheetSound.audioFileUrl &&
                forms.multiTracksSelection.includes(musicSheetSound.track)
              ) {
                musicSheetSoundList.push({
                  ...musicSheetSound,
                  musicalInstrumentId:
                    musicSheetSound.musicalInstrumentId ||
                    instrumentCodeToInstrumentId(musicSheetSound.track),
                  musicSheetId: props.data.id,
                  audioPlayType: 'PLAY'
                })
                existYzFile = true

                if (!audioPlayTypes.has('PLAY')) {
                  audioPlayTypes.add('PLAY')
                }
              }
            })
          }

          

          // 总谱 伴唱判断
          if (forms.scoreAudioFileUrl || state.bSongFile) {
            existFSFile = true
          }
          // 演唱 演奏只要有一个上传都可以
          if (!existFSFile && !existYzFile) {
            message.warning('请上传音频文件')
            return
          }

          // 生成图片
          if (!state.isAutoSave && state.isCreateImg) {
            state.isAutoSave = true
            state.productOpen = true
            return
          }

          // 判断是否有总谱
          // console.log(forms.scoreAudioFileUrl, 'forms.scoreAudioFileUrl')
          if (forms.scoreAudioFileUrl) {
            forms.musicSheetAccompanimentList.push({
              musicSheetId: props.data.id,
              audioFileUrl: state.bSongFile,
              scoreAudioFileUrl:
                forms.multiTracksSelection.length > 1 &&
                forms.isScoreRender &&
                forms.scoreAudioFileUrl
                  ? forms.scoreAudioFileUrl
                  : null,
              audioPlayType: 'SING'
            })
          } else {
            if(state.bSongFile) {
              forms.musicSheetAccompanimentList.push({
                musicSheetId: props.data.id,
                audioFileUrl: state.bSongFile,
                audioPlayType: 'SING'
              })
            }
            
          }

          if (state.musicSheetAccompanimentUrl) {
            forms.musicSheetAccompanimentList.push({
              musicSheetId: props.data.id,
              audioFileUrl: state.musicSheetAccompanimentUrl,
              audioPlayType: 'PLAY'
            })
          }

          let isScoreRender
          let defaultScoreRender
          if (forms.multiTracksSelection.length > 1) {
            isScoreRender = forms.isScoreRender
            if (forms.isScoreRender) {
              defaultScoreRender = forms.defaultScoreRender
            }
          }

          const obj = {
            musicCategoryId: forms.musicCategoryId,
            musicCover: forms.musicCover,
            name: forms.name,
            appAuditFlag: forms.appAuditFlag,
            subjectIds: forms.isAllSubject ? '' : forms.subjectIds.join(','),
            remark: forms.remark,
            audioPlayTypes: Array.from(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.multiTracksSelection.join(','),
            playSpeed: forms.playSpeed,
            playMode: forms.playMode,
            xmlFileUrl: forms.xmlFileUrl,
            isMixBeat: forms.isMixBeat,
            musicImg: forms.musicImg,
            musicFirstImg: forms.musicFirstImg,
            musicJianImg: forms.musicJianImg,
            musicPdfUrl: forms.musicPdfUrl,
            firstPdfUrl: forms.firstPdfUrl,
            jianPdfUrl: forms.jianPdfUrl,
            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,
            musicSheetExtend: forms.sourceType == 'PLATFORM' ? null : forms.musicSheetExtend,
            isScoreRender: isScoreRender,
            defaultScoreRender: defaultScoreRender
          }
          if (forms.audioType == 'MIDI') {
            obj.musicSheetSoundList = []
          }

          console.log(obj, 'obj')
          // return
          btnLoading.value = true
          let resData: any
          if (props.type === 'add') {
            resData = await musicSheetSave(obj)
          } else if (props.type === 'edit') {
            resData = await musicSheetSave({ ...obj, id: props.data.id })
          }
          //if (state.isBeatTime && forms.isMixBeat) {
          if (forms.isMixBeat) {
            beatTimeData.beatTimeOpen = true
            beatTimeData.musicId = resData.data
            state.showUseProjectId = resData.data
          } else {
            state.showUseProjectId = resData.data
            state.showUseProject = true
            setTimeout(() => {
              btnLoading.value = false
              state.isAutoSave = false
            }, 100)
          }
        } catch (e) {
          console.log(e)
          setTimeout(() => {
            btnLoading.value = false
            state.isAutoSave = false
          }, 100)
        }
      })
    }
    // 合成节拍器的回调
    function handlerMusiceBeatTimeClose(val: any) {
      if (!val) {
        if (props.type === 'add') {
          message.success('添加成功')
        } else if (props.type === 'edit') {
          message.success('修改成功')
        }
      }

      emit('getList')
      emit('close')
      setTimeout(() => {
        btnLoading.value = false
        state.isAutoSave = false
      }, 100)
    }
    const isPtrack = async (track: string) => {
      if (track && (track == 'P1' || track == 'P2' || track == 'P3' || track == 'P4')) {
        return true
      }
      return false
    }

    const initFSongList = async () => {
      forms.fSongList.forEach((fSong: any) => {
        state.initFSongMap.set(fSong.track, fSong)
      })

      let fSongList = [] as any
      forms.multiTracksSelection.forEach((item: any) => {
        if (state.initFSongMap.has(item)) {
          fSongList.push(state.initFSongMap.get(item))
        } else {
          fSongList.push({
            musicSheetId: props.data.id,
            audioFileUrl: null,
            audioPlayType: 'SING',
            musicalInstrumentId: null,
            track: item,
            // musicalInstrumentName: state.instrumentIdNameMap.get(item),
            musicalInstrumentName: null,
            solmizationFileUrl: null, // 唱名男
            femaleSolmizationFileUrl: null // 唱名女
          })
        }
      })
      forms.fSongList = fSongList
    }

    // 上传XML，初始化音轨 音轨速度 乐器、声部
    const readFileInputEventAsArrayBuffer = (file: any) => {
      state.isCreateImg = true // 更换XML
      // 是否是evxml
      const xmlRead = new FileReader()
      xmlRead.onload = (res) => {
        try {
          gradualData.list = getGradualLengthByXml(res?.target?.result as any).filter(
            (item: any) => item.length === 2
          )

          // 音乐人中有值，则不做更新
          const result = getXmlInfo(res?.target?.result as any)
          if (!forms.composer) {
            forms.composer = result.composer
          }
        } catch (error) {}
        forms.musicSheetSoundList_YY = forms.musicSheetSoundList_YY.filter((item: any) => {
          return (
            !item.track ||
            !containOther(item.track) ||
            (item.track?.toLocaleUpperCase?.() != 'COMMON' &&
              forms.multiTracksSelection.includes(item.track))
          )
        })

        state.partListNames = getPartListNames(res?.target?.result as any) as any
        // parseInstrumentAndSubject(res?.target?.result as any)
        // 这里是如果没有当前音轨就重新写

        let map = new Map<String, String>()
        for (let i = 0; i < forms.musicSheetSoundList_YY.length; i++) {
          let track = forms.musicSheetSoundList_YY[i].track
          if (track) {
            map.set(track, forms.musicSheetSoundList_YY[i])
          }
        }

        let newMusicSheetSoundList = []
        let tracks = [] as any
        for (let j = 0; j < state.partListNames.length; j++) {
          let track = state.partListNames[j].value
          if (map.has(track)) {
            newMusicSheetSoundList.push(map.get(track))
          } else {
            newMusicSheetSoundList.push({
              audioFileUrl: null,
              track: track,
              musicalInstrumentId: null
            })
          }
          tracks.push(track)
          if (!forms.multiTracksSelection.includes(track)) {
            forms.multiTracksSelection.push(track)
          }
        }

        for (let i = 0; i < forms.musicSheetSoundList_YY.length; i++) {
          let track = forms.musicSheetSoundList_YY[i].track
          if (!track || !tracks.includes(track)) {
            forms.musicSheetSoundList_YY[i].track = null
            newMusicSheetSoundList.push(forms.musicSheetSoundList_YY[i])
          }
        }
        forms.musicSheetSoundList_YY = newMusicSheetSoundList

        forms.multiTracksSelection = forms.multiTracksSelection.filter((track: any) => {
          return tracks.includes(track)
        })
        // 全选选中
        state.multiTracks = 'all'

        // 循环添加所在音轨的原音
        // for (let index = forms.musicSheetSoundList.length; index < state.partListNames.length; index++) {
        //   const part = state.partListNames[index].value
        //   const sysData = {
        //     ...forms.musicSheetSoundList[0],
        //     track: part
        //   }
        //   if (!sysData.speed) {
        //     sysData.speed = state.xmlFirstSpeed
        //   }
        //   createSys(sysData)
        // }

        if (forms.musicSheetSoundList_YY.length == 0) {
          forms.musicSheetSoundList_YY.push({ audioFileUrl: '', track: '', musicPdfUrl: '', firstPdfUrl: '', jianPdfUrl: '' })
        }
      }
      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 validSoundNum = () => {
      return forms.musicSheetSoundList_YY.filter((item: any) => {
        return (
          !item.track ||
          !containOther(item.track) ||
          (item.track?.toLocaleUpperCase?.() != 'COMMON' &&
            forms.multiTracksSelection.includes(item.track))
        )
      }).length
    }

    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]
        let instrumentCode = note.getElementsByTagName('virtual-name')?.[0]?.textContent || ''
        instrumentCode = instrumentCode.toLocaleLowerCase().trim()
        if (instrumentCode && !instrumentCodeList.includes(instrumentCode)) {
          instrumentCodeList.push(instrumentCode)
        }
      }
      // 乐器支持多编码，暂不开放
      initInstrumentAndSubjectByTrack(instrumentCodeList)
    }

    /** 通过声轨反显乐器和声部 */
    const initInstrumentAndSubjectByTrack = async (tracks: string[]) => {
      // 选择一个声轨，独奏
      // 选择了多个声轨，合奏，乐器和声部自动反显，不可修改
      // if (!tracks || tracks.length <= 1) {
      //   forms.musicSheetType = 'SINGLE'
      //   state.subjectDisabled = false
      //   state.instrumentDisabled = false
      //   return
      // }
      forms.musicSheetType = !tracks || tracks.length <= 1 ? 'SINGLE' : 'CONCERT'
      state.subjectDisabled = true
      state.instrumentDisabled = true
      await initInstrumentAndSubjectByCode(tracks)
    }

    /** 获取分轨名称 */
    const getInstrumentName = (instruments: any, name = '') => {
      name = name.toLocaleLowerCase().replace(/ /g, '').replace(/\d*/gi, '')
      if (!name) return ''
      for (let key of instruments) {
        const _key = key.toLocaleLowerCase().replace(/ /g, '')
        // if (_key.includes(name)) {
        //   return key
        // }
        if (_key === name) {
          return _key
        }
      }
      // for (let key of instruments) {
      //   const _key = key.toLocaleLowerCase().replace(/ /g, '')
      //   if (name.includes(_key)) {
      //     return key
      //   }
      // }
      return ''
    }

    // 通过乐器编码反显乐器和声部
    const initInstrumentAndSubjectByCode = async (codes: string[]) => {
      // forms.musicalInstrumentIdList = []
      console.log('1111')
      forms.subjectIds = []
      const codeIdMap = new Map<string, []>() as any
      const codeMapKeys: string[] = []
      state.instrumentData.forEach((data: any) => {
        if (!data.disabled) {
          const codes = data.code.split(/[,，]/)
          codes.forEach((code: string) => {
            let codeTemp = code.replaceAll(' ', '').toLowerCase()
            codeMapKeys.push(codeTemp)
            if (codeIdMap.has(codeTemp)) {
              codeIdMap.get(codeTemp).push(data.id + '')
            } else {
              const arr = [] as any
              arr.push(data.id + '')
              codeIdMap.set(codeTemp, arr)
            }
          })
        }
      })

      for (let i = 0; i < codes.length; i++) {
        let code = codes[i].replaceAll(' ', '').toLowerCase()
        const tempCode = getInstrumentName(codeMapKeys, code)
        if (codeIdMap.has(tempCode)) {
          codeIdMap.get(tempCode).forEach((c: any) => {
            const index = state.instrumentList.findIndex((item: any) => item.id.toString() === c)
            if (!forms.musicalInstrumentIdList.includes(c) && index !== -1) {
              forms.musicalInstrumentIdList.push(c)
            }
          })
        }
      }

      // 声部
      if (forms.musicalInstrumentIdList.length > 0) {
        await showBackSubject(forms.musicalInstrumentIdList)
        // changeSubject(forms.subjectIds)
      }
    }

    // 通过乐器编码返回乐器编号
    const instrumentCodeToInstrumentId = (code: string) => {
      const codeIdMap = new Map<string, []>() as any
      const codeMapKeys: string[] = []
      state.instrumentData.forEach((data: any) => {
        if (!data.disabled) {
          const codes = data.code.split(/[,，]/)
          codes.forEach((code: string) => {
            let codeTemp = code.replaceAll(' ', '').toLowerCase()
            codeMapKeys.push(codeTemp)
            if (codeIdMap.has(codeTemp)) {
              codeIdMap.get(codeTemp).push(data.id + '')
            } else {
              const arr = [] as any
              arr.push(data.id + '')
              codeIdMap.set(codeTemp, arr)
            }
          })
        }
      })

      if (!code) {
        return ''
      }
      code = code.replaceAll(' ', '').toLowerCase()
      const tempCode = getInstrumentName(codeMapKeys, code)
      if (codeIdMap.has(tempCode)) {
        const result = codeIdMap.get(tempCode)
        console.log('result:', result)
        return result[0] || ''
      }
      return ''
    }

    // 获取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]
        // evxml没有分轨，需要手动设置一个默认的名称，用于上传原音
        let track = ''
        // if (forms.isEvxml) {
        //   // 秒极客曲目，取ID
        //   let id = item.getAttribute('id')
        //   if (id) {
        //     track = id
        //   }
        // } else {
        // 优先解析声轨，没有就取id值
        if (part && part.textContent?.trim()) {
          track = part.textContent || ''
        } else {
          let id = item.getAttribute('id')
          if (id) {
            track = id
          }
        }
        // }
        return {
          value: track.trim(),
          label: track.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 = forms.musicSheetSoundList.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: []) => {
      if (!musicalInstrumentIdList || musicalInstrumentIdList.length == 0) {
        forms.subjectIds = []
        return
      }
      try {
        const { data } = await subjectPage({
          page: 1,
          rows: 999,
          musicalInstrumentIdList: musicalInstrumentIdList
        })
        const tempList = data.rows || []
        const tempSubject: any[] = []
        tempList.forEach((item: any) => {
          if (item.enableFlag) {
            tempSubject.push(item.id + '')
          }
        })
        forms.subjectIds = tempSubject
      } 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]
          let track = sound.track
          // if (!track) {
          //   track = ''
          // }
          // if (track) {
          const selectIndex = forms.multiTracksSelection.indexOf(track)
          if (selectIndex > -1) {
            forms.multiTracksSelection.splice(selectIndex, 1)
          } else {
            forms.musicSheetSoundList_YY.splice(index, 1)
          }

          if (
            state.multiTracks == 'all' &&
            state.partListNames.length != forms.multiTracksSelection.length
          ) {
            state.multiTracks = null
          }
        }
      })
    }

    const checkMultiTracks = (value: string) => {
      if (!value) {
        return
      }
      let tempMultiTracksSelection = [] as any
      if (value === 'all') {
        state.partListNames.forEach((next: any) => {
          tempMultiTracksSelection.push(next.value)
        })
      } else if (value === 'invert') {
        state.partListNames.forEach((next: any) => {
          if (!forms.multiTracksSelection.includes(next.value)) {
            tempMultiTracksSelection.push(next.value)
          }
        })
      }
      forms.multiTracksSelection = tempMultiTracksSelection
    }

    const setOwnerName = () => {
      if (forms.sourceType == 'PLATFORM') {
        state.ownerName = ''
        return
      }
      if (!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 = state.ownerName
          ? state.ownerName + '-' + forms.musicSheetExtend.organizationRole
          : forms.musicSheetExtend.organizationRole
      } else if (forms.sourceType == 'PERSON') {
        state.ownerName = state.ownerName
          ? state.ownerName +
            '-' +
            getMapValueByKey(forms.musicSheetExtend.clientType, new Map(Object.entries(clientType)))
          : getMapValueByKey(forms.musicSheetExtend.clientType, new Map(Object.entries(clientType)))
        if (forms.musicSheetExtend.userName) {
          state.ownerName = state.ownerName
            ? state.ownerName + '-' + forms.musicSheetExtend.userName
            : forms.musicSheetExtend.userName
        }
        if (forms.musicSheetExtend.phone) {
          state.ownerName += '(' + forms.musicSheetExtend.phone + ')'
        }
      }
    }

    // 声轨数据兼容
    const formatTrack = (track: string) => {
      if (!track) {
        return ''
      }
      const trim = track.trim().toUpperCase()
      // 导入后的脏数据兼容
      if (trim == 'P1' || trim == 'NULL') {
        return ''
      }
      return track.trim()
    }

    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 = deepClone(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,
          hiddenFlag: true
        })
        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.useProjectData = filter

        const tempFilter = tempList.filter((next: any) => {
          return appKeys.includes(next.appKey) && next.appKey !== 'KLX_JG'
        })
        tempFilter.forEach((item: any) => {
          item.label = item.appName
          item.value = item.id
        })
        state.appData = tempFilter
      }

      // 获取分类信息
      {
        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.defaultScoreRender = data.defaultScoreRender
          forms.isScoreRender = data.isScoreRender
          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.isMixBeat = data.isMixBeat

          forms.musicFirstImg = data.musicFirstImg
          forms.musicJianImg = data.musicJianImg
          forms.musicImg = data.musicImg

          forms.musicPdfUrl = data.musicPdfUrl
          forms.firstPdfUrl = data.firstPdfUrl
          forms.jianPdfUrl = data.jianPdfUrl
          forms.isAllSubject = data.isAllSubject
          forms.isUseSingSystemBeat = data.isUseSingSystemBeat
          forms.isPlaySingBeat = data.isPlaySingBeat
          forms.subjectIds = []
          if (data.subjectIds) {
            const subjectIds = data.subjectIds.split(',') || []
            console.log(subjectIds, 'subjectIds', forms.subjectIds)
            subjectIds.forEach((subjectId: any) => {
              if (!forms.subjectIds.includes(subjectId)) {
                forms.subjectIds.push(subjectId)
              }
            })

            state.subjectList = state.subjectList.filter((subject: any) => {
              return !subject.disabled || subjectIds.includes(subject.value)
            })
          }
          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
              forms.scoreAudioFileUrl = next.scoreAudioFileUrl
            } else {
              state.musicSheetAccompanimentUrl = next.audioFileUrl
            }
          })

          // 初始化演奏
          for (let i = 0; i < state.musicSheetSoundList.length; i++) {
            if (
              state.musicSheetSoundList[i].audioPlayType == 'SING' &&
              state.musicSheetSoundList[i].track != null
            ) {
              // 范唱 唱名
              state.initFSongMap.set(state.musicSheetSoundList[i].track, {
                ...state.musicSheetSoundList[i]
                // musicalInstrumentName: state.instrumentIdNameMap.get(state.musicSheetSoundList[i].musicalInstrumentId),
              })
            } 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
                  }
                }
              }
            }
          }

          forms.musicalInstrumentIdList = data.musicalInstrumentIds
            ? data.musicalInstrumentIds.split(',')
            : []
          // 乐器下拉格式化,停用的过滤
          state.instrumentList = state.instrumentList.filter((next: any) => {
            return next.enableFlag || forms.musicalInstrumentIdList.includes(next.id + '')
          })

          setOwnerName()
          axios.get(data.xmlFileUrl).then((res: any) => {
            if (res?.data) {
              state.musicUpdateLoading = true
              gradualData.list = getGradualLengthByXml(res?.data as any).filter(
                (item: any) => item.length === 2
              )
              state.partListNames = getPartListNames(res?.data as any) as any

              // 初始化音轨和原音
              let multiTracksSelection = [] as any
              if (data.multiTracksSelection) {
                data.multiTracksSelection = data.multiTracksSelection.toLocaleUpperCase()
              }
              if (
                !data.multiTracksSelection ||
                data.multiTracksSelection.trim() == '' ||
                data.multiTracksSelection.trim() == 'NULL'
              ) {
                multiTracksSelection.push('')
              } else {
                data.multiTracksSelection.split(',').forEach((next: any) => {
                  multiTracksSelection.push(next.trim())
                })
              }
              let names = state.partListNames.map((next: any) => next.label)
              multiTracksSelection = names.filter((next: any) =>
                multiTracksSelection.includes(next.toLocaleUpperCase())
              )
              forms.multiTracksSelection = multiTracksSelection
              // 根据声轨数量判断独奏合奏
              forms.musicSheetType = forms.multiTracksSelection.length > 1 ? 'CONCERT' : 'SINGLE'

              const existSoundList = data.musicSheetSoundList ? data.musicSheetSoundList : []
              // 如果只有一个原音文件，并且原音没有对应声轨，取xml解析中的第一个声轨绑定当当前原音
              // if (existSoundList.length === 1 && !formatTrack(existSoundList[0].track)) {
              //   let track = state.partListNames.length > 0 ? state.partListNames[0].value : null;
              //   forms.musicSheetSoundList_YY.push({
              //     audioFileUrl: existSoundList[0].audioFileUrl, // 原音
              //     musicalInstrumentId: existSoundList[0].musicalInstrumentId,
              //     track: track, // 轨道
              //     audioPlayType: 'PLAY'
              //   })
              //   if (track && !forms.multiTracksSelection.includes(track)) {
              //     forms.multiTracksSelection.push(track)
              //   }
              // } else {
              const tracks = [] as any
              state.partListNames.forEach((item: any) => {
                let audioFileUrl = null
                let musicalInstrumentId = null
                let musicPdfUrl = null
                let firstPdfUrl = null
                let jianPdfUrl = null
                if (forms.musicSheetType == 'CONCERT') {
                  existSoundList.forEach((next: any) => {
                    if (next.audioPlayType == 'PLAY') {
                      let track = ''
                      if (next.track) {
                        track = next.track.trim()
                      }
                      if (track == item.value) {
                        audioFileUrl = next.audioFileUrl
                        musicalInstrumentId = next.musicalInstrumentId
                        musicPdfUrl = next.musicPdfUrl
                        firstPdfUrl = next.firstPdfUrl
                        jianPdfUrl = next.jianPdfUrl
                      }
                    }
                  })
                }
                forms.musicSheetSoundList_YY.push({
                  audioFileUrl: audioFileUrl, // 原音
                  musicPdfUrl, // 五线谱pdf
                  firstPdfUrl,// 首调pdf
                  jianPdfUrl,// 固定调pdf
                  musicalInstrumentId: musicalInstrumentId, // 乐器
                  track: item.value, // 轨道
                  audioPlayType: 'PLAY'
                })
                tracks.push(item.value)
              })

              if (tracks.length == forms.multiTracksSelection.length) {
                state.multiTracks = 'all'
              }

              // 处理没有声轨，但有原音
              if (forms.musicSheetType == 'CONCERT') {
                state.musicSheetSoundList.forEach((next: any) => {
                  if (next.audioPlayType == 'PLAY') {
                    if (
                      next.track &&
                      !tracks.includes(next.track.trim()) &&
                      next.audioPlayType == 'PLAY'
                    ) {
                      forms.musicSheetSoundList_YY.push({
                        audioFileUrl: next.audioFileUrl, // 原音
                        musicalInstrumentId: next.musicalInstrumentId,
                        track: next.track ? next.track.trim() : '', // 轨道
                        audioPlayType: 'PLAY'
                      })
                    }
                  }
                })
                // }
              }

              initFSongList()
              // state.musicUpdateLoading = false
            }
          })
        } 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: false,
                    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: false,
                    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>
                  {forms.playMode == 'MIDI' && props.type === 'preview' && (
                    <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="总谱五线谱PDF"
                path="musicPdfUrl"
                rule={[
                  {
                    required: false,
                    message: '请选择总谱五线谱PDF',
                    trigger: ['change', 'input']
                  }
                ]}
              >
                <UploadFile
                  desc={'总谱五线谱PDF'}
                  disabled={state.previewMode}
                  size={30}
                  max={1}
                  v-model:fileList={forms.musicPdfUrl}
                  tips="仅支持上传.pdf格式文件"
                  listType="image"
                  accept=".pdf"
                  bucketName="cloud-coach"
                  text="点击上传PDF"
                />
              </NFormItemGi>
              <NFormItemGi
                label="总谱首调PDF"
                path="firstPdfUrl"
                rule={[
                  {
                    required: false,
                    message: '请选择总谱首调PDF',
                    trigger: ['change', 'input']
                  }
                ]}
              >
                <UploadFile
                  desc={'总谱首调PDF'}
                  disabled={state.previewMode}
                  size={30}
                  max={1}
                  v-model:fileList={forms.firstPdfUrl}
                  tips="仅支持上传.pdf格式文件"
                  listType="image"
                  accept=".pdf"
                  bucketName="cloud-coach"
                  text="点击上传PDF"
                />
              </NFormItemGi>
              <NFormItemGi
                label="总谱固定PDF"
                path="jianPdfUrl"
                rule={[
                  {
                    required: false,
                    message: '请选择总谱固定PDF',
                    trigger: ['change', 'input']
                  }
                ]}
              >
                <UploadFile
                  desc={'总谱固定PDF'}
                  disabled={state.previewMode}
                  size={30}
                  max={1}
                  v-model:fileList={forms.jianPdfUrl}
                  tips="仅支持上传.pdf格式文件"
                  listType="image"
                  accept=".pdf"
                  bucketName="cloud-coach"
                  text="点击上传PDF"
                />
              </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>
              <NFormItemGi
                label="速度"
                path="playSpeed"
                rule={[
                  {
                    required: false,
                    message: '请输入速度'
                  }
                ]}
              >
                <NInputNumber
                  placeholder="请输入速度"
                  v-model:value={forms.playSpeed}
                  min={0}
                  style="width:100%"
                />
              </NFormItemGi>
            </NGrid>
            {!forms.isAllSubject && (
              <NGrid cols={2}>
                <NFormItemGi
                  label="可用乐器"
                  path="musicalInstrumentIdList"
                  rule={[
                    {
                      required: true,
                      message: '请选择可用乐器',
                      trigger: 'change',
                      type: 'array'
                    }
                  ]}
                >
                  <NSelect
                    placeholder="请选择可用乐器"
                    options={state.instrumentList}
                    v-model:value={forms.musicalInstrumentIdList}
                    // disabled = {state.instrumentDisabled}
                    clearable
                    multiple
                    filterable
                    maxTagCount={10}
                    onUpdateValue={async (value: any) => {
                      await showBackSubject(value)
                    }}
                  />
                </NFormItemGi>
                <NFormItemGi
                  label="可用声部"
                  path="subjectIds"
                  rule={[
                    {
                      required: true,
                      message: '请选择可用声部',
                      trigger: 'change',
                      type: 'array'
                    }
                  ]}
                >
                  <NSelect
                    v-model:value={forms.subjectIds}
                    options={state.subjectList}
                    // disabled={true}
                    multiple
                    filterable
                    clearable
                    placeholder="请选择可用声部"
                    maxTagCount={10}
                    onUpdateValue={async (val: any) => {
                      // await changeSubject(val)
                    }}
                  />
                </NFormItemGi>
              </NGrid>
            )}
            <NGrid cols={1}>
              <NFormItemGi
                  label="是否生成节拍器"
                  path="isMixBeat"
                  rule={[
                    {
                      required: true,
                      message: '请选择是否生成节拍器'
                    }
                  ]}
                >
                  <NRadioGroup v-model:value={forms.isMixBeat} onUpdate:value={()=>{ state.isBeatTime = true }}>
                    <NRadio value={true}>是</NRadio>
                    <NRadio value={false}>否</NRadio>
                  </NRadioGroup>
                </NFormItemGi>
              </NGrid>
            
            <NGrid cols={1}>
              <NFormItemGi
                label={'切换声轨'}
                path="multiTracksSelection"
                rule={[
                  {
                    required: true,
                    message: `请选择切换声轨`,
                    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}
                          onUpdateValue={(val: any) => {
                            if (state.partListNames.length != val.length) {
                              state.multiTracks = null
                            } else {
                              state.multiTracks = 'all'
                            }
                          }}
                        >
                          <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>
            {forms.multiTracksSelection.length > 1 && (
              <NGrid cols={2}>
                <NFormItemGi
                  label="总谱渲染"
                  path="isScoreRender"
                  rule={[
                    {
                      required: true,
                      message: '请选择总谱渲染'
                    }
                  ]}
                >
                  <NRadioGroup v-model:value={forms.isScoreRender}>
                    <NRadio value={true}>支持</NRadio>
                    <NRadio value={false}>不支持</NRadio>
                  </NRadioGroup>
                </NFormItemGi>
                {/* 支持总谱渲染的时候才显示 */}
                {forms.isScoreRender && (
                  <NFormItemGi
                    label="默认显示"
                    path="defaultScoreRender"
                    rule={[
                      {
                        required: false
                      }
                    ]}
                  >
                    <NRadioGroup v-model:value={forms.defaultScoreRender}>
                      <NRadio value={true}>总谱</NRadio>
                      <NRadio value={false}>分轨</NRadio>
                    </NRadioGroup>
                  </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:fileList={state.musicSheetAccompanimentUrl}
                    onUpdate:fileList={() => {
                      state.isBeatTime = true
                    }}
                    tips="仅支持上传.mp3格式文件"
                    listType="image"
                    accept=".mp3"
                    bucketName="cloud-coach"
                    text="点击上传伴奏文件"
                    max={1}
                    desc={'上传伴奏文件'}
                    // onReadFileInputEventAsArrayBuffer={readFileInputEventAsArrayBuffer}
                  />
                </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}
                    onUpdate:fileList={() => {
                      state.isBeatTime = true
                    }}
                    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 + 1}小节开始</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: false,
                              message: `请上传乐器演奏文件`
                            }
                          ]}
                        >
                          <UploadFile
                            desc={'乐器演奏文件'}
                            disabled={state.previewMode}
                            size={100}
                            v-model:fileList={item.audioFileUrl}
                            onUpdate:fileList={() => {
                              state.isBeatTime = true
                            }}
                            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: false,
                                  message: `请上传${
                                    item.track ? item.track + '的' : '第' + (index + 1) + '个'
                                  }原音`
                                }
                              ]}
                            >
                              <UploadFile
                                desc={'原音文件'}
                                disabled={state.previewMode}
                                size={100}
                                v-model:fileList={item.audioFileUrl}
                                onUpdate:fileList={() => {
                                  state.isBeatTime = true
                                }}
                                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 != null &&
                                      !forms.multiTracksSelection.includes(value)
                                    ) {
                                      forms.multiTracksSelection.push(value)
                                    }
                                    item.track = value

                                    if (
                                      state.partListNames.length ==
                                      forms.multiTracksSelection.length
                                    ) {
                                      state.multiTracks = 'all'
                                    }
                                  }}
                                />
                              </NFormItemGi>
                            )}
                            <NFormItemGi
                              span={12}
                              label="五线谱PDF"
                              path={`musicSheetSoundList_YY[${index}].musicPdfUrl`}
                              rule={[
                                {
                                  required: false,
                                  message: '请选择五线谱PDF',
                                  trigger: ['change', 'input']
                                }
                              ]}
                            >
                              <UploadFile
                                desc={'五线谱PDF'}
                                disabled={state.previewMode}
                                size={30}
                                max={1}
                                v-model:fileList={item.musicPdfUrl}
                                tips="仅支持上传.pdf格式文件"
                                listType="image"
                                accept=".pdf"
                                bucketName="cloud-coach"
                                text="点击上传PDF"
                              />
                            </NFormItemGi>
                            <NFormItemGi
                              span={12}
                              label="首调PDF"
                              path={`musicSheetSoundList_YY[${index}].firstPdfUrl`}
                              rule={[
                                {
                                  required: false,
                                  message: '请选择首调PDF',
                                  trigger: ['change', 'input']
                                }
                              ]}
                            >
                              <UploadFile
                                desc={'首调PDF'}
                                disabled={state.previewMode}
                                size={30}
                                max={1}
                                v-model:fileList={item.firstPdfUrl}
                                tips="仅支持上传.pdf格式文件"
                                listType="image"
                                accept=".pdf"
                                bucketName="cloud-coach"
                                text="点击上传PDF"
                              />
                            </NFormItemGi>
                            <NFormItemGi
                              span={12}
                              label="固定PDF"
                              path={`musicSheetSoundList_YY[${index}].jianPdfUrl`}
                              rule={[
                                {
                                  required: false,
                                  message: '请选择固定PDF',
                                  trigger: ['change', 'input']
                                }
                              ]}
                            >
                              <UploadFile
                                desc={'固定PDF'}
                                disabled={state.previewMode}
                                size={30}
                                max={1}
                                v-model:fileList={item.jianPdfUrl}
                                tips="仅支持上传.pdf格式文件"
                                listType="image"
                                accept=".pdf"
                                bucketName="cloud-coach"
                                text="点击上传PDF"
                              />
                            </NFormItemGi>
                            <NGi class={styles.btnRemove}>
                              <NButton
                                type="primary"
                                text
                                // disabled={forms.musicSheetSoundList_YY.length === 1}
                                onClick={() => removeSys(index)}
                              >
                                删除
                              </NButton>
                            </NGi>
                          </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="bSongFile"
                rule={[
                  {
                    required: false
                  }
                ]}
              >
                <UploadFile
                  desc={'上传伴唱'}
                  disabled={state.previewMode}
                  size={30}
                  v-model:fileList={state.bSongFile}
                  onUpdate:fileList={() => {
                    state.isBeatTime = true
                  }}
                  tips="仅支持上传.mp3格式文件"
                  listType="image"
                  accept=".mp3"
                  bucketName="cloud-coach"
                  text="点击上传伴唱文件"
                />
              </NFormItemGi>
            </NGrid>
            {forms.fSongList.length > 0 &&
              forms.fSongList.map((item: any) => {
                return (
                  <NGrid class={styles.audioSection}>
                    <NFormItemGi
                      span={12}
                      label={item.track + '范唱'}
                      path={item.audioFileUrl}
                      rule={[
                        {
                          required: false
                        }
                      ]}
                    >
                      <UploadFile
                        desc={'上传范唱'}
                        disabled={state.previewMode}
                        size={100}
                        v-model:fileList={item.audioFileUrl}
                        onUpdate:fileList={() => {
                          state.isBeatTime = true
                        }}
                        tips="仅支持上传.mp3格式文件"
                        listType="image"
                        accept=".mp3"
                        bucketName="cloud-coach"
                        text={'点击上传范唱文件'}
                      />
                    </NFormItemGi>
                  </NGrid>
                )
              })}
            {forms.multiTracksSelection.length > 1 && forms.isScoreRender && (
              <NGrid cols={2} class={styles.audioSection}>
                <NFormItemGi
                  label="总谱范唱"
                  path="scoreRenderFile"
                  rule={[
                    {
                      required: false
                    }
                  ]}
                >
                  <UploadFile
                    desc={'上传总谱范唱'}
                    disabled={state.previewMode}
                    size={30}
                    v-model:fileList={forms.scoreAudioFileUrl}
                    onUpdate:fileList={() => {
                      state.isBeatTime = true
                    }}
                    tips="仅支持上传.mp3格式文件"
                    listType="image"
                    accept=".mp3"
                    bucketName="cloud-coach"
                    text="点击上传总谱范唱"
                  />
                </NFormItemGi>
              </NGrid>
            )}
            {forms.fSongList.length > 0 &&
              forms.fSongList.map((item: any) => {
                return (
                  <NGrid cols={2}>
                    <NFormItemGi
                      label={item.track + '唱名(男)'}
                      path={item.solmizationFileUrl}
                      rule={[
                        {
                          required: false
                        }
                      ]}
                    >
                      <UploadFile
                        desc={'上传范唱'}
                        disabled={state.previewMode}
                        size={100}
                        v-model:fileList={item.solmizationFileUrl}
                        onUpdate:fileList={() => {
                          state.isBeatTime = true
                        }}
                        tips="仅支持上传.mp3格式文件"
                        listType="image"
                        accept=".mp3"
                        bucketName="cloud-coach"
                        text={'点击上传唱名文件'}
                      />
                    </NFormItemGi>
                    <NFormItemGi
                      label={item.track + '唱名(女)'}
                      path={item.femaleSolmizationFileUrl}
                      rule={[
                        {
                          required: false
                        }
                      ]}
                    >
                      <UploadFile
                        desc={'上传范唱'}
                        disabled={state.previewMode}
                        size={100}
                        v-model:fileList={item.femaleSolmizationFileUrl}
                        onUpdate:fileList={() => {
                          state.isBeatTime = true
                        }}
                        tips="仅支持上传.mp3格式文件"
                        listType="image"
                        accept=".mp3"
                        bucketName="cloud-coach"
                        text={'点击上传唱名文件'}
                      />
                    </NFormItemGi>
                  </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}
          onClose={() => {
            state.isAutoSave = 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
                await onSubmit()
              } catch (e: any) {
                //
                console.log(e, 'e')
              }
              // setTimeout(() => {
              //   state.isAutoSave = false
              // }, 50)
            }}
          />
        </NModal>
        {beatTimeData.beatTimeOpen && (
          <MusiceBeatTime
            id={beatTimeData.musicId}
            // onClose={handlerMusiceBeatTimeClose}
            onClose={(val: any) => {
              beatTimeData.beatTimeOpen = false
              if (val) return

              state.showUseProject = true
            }}
          ></MusiceBeatTime>
        )}

        <NModal
          blockScroll={true}
          v-model:show={state.showUseProject}
          preset="dialog"
          showIcon={false}
          title={'适用项目'}
          style={{ width: '1200px' }}
          onMaskClick={() => {
            emit('getList')
            emit('close')
            setTimeout(() => {
              btnLoading.value = false
              state.isAutoSave = false
            }, 100)
          }}
          onClose={() => {
            emit('getList')
            emit('close')
            setTimeout(() => {
              btnLoading.value = false
              state.isAutoSave = false
            }, 100)
          }}
        >
          <MusicPlatform  
            type={props.type}
            id={state.showUseProjectId}
            useProject={state.useProjectData}
            onClose={handlerMusiceBeatTimeClose}
          />
        </NModal>
      </div>
    )
  }
})
