import type { SelectOption } from 'naive-ui'
import {
  NAlert,
  NButton,
  NCascader,
  NCheckbox,
  NCheckboxGroup,
  NForm,
  NFormItem,
  NFormItemGi,
  NGi,
  NGrid,
  NInput,
  NInputGroup,
  NInputGroupLabel,
  NInputNumber,
  NModal,
  NRadio,
  NRadioGroup,
  NSelect,
  NSpace,
  NSpin,
  useDialog,
  useMessage
} from 'naive-ui'
import { defineComponent, nextTick, onMounted, PropType, reactive, ref } from 'vue'
import { musicSheetCategoriesQueryTree, musicSheetDetail, musicSheetSave } from '../../api'
import UploadFile from '@/components/upload-file'
import styles from './index.module.less'
import deepClone from '@/utils/deep.clone'
import axios from 'axios'
import { appKey, clientType, musicSheetSourceType, musicSheetType } 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 { onUpdated } from 'vue-demi'

/**
 * 获取指定元素下一个Note元素
 * @param ele 指定元素
 * @param selectors 选择器
 */
const getNextNote = (ele: any, selectors: any) => {
  let index = 0
  const parentEle = ele.closest(selectors)
  let pointer = parentEle
  const measure = parentEle?.closest('measure')
  let siblingNote = null
  // 查找到相邻的第一个note元素
  while (!siblingNote && index < (measure?.childNodes.length || 50)) {
    index++
    if (pointer?.nextElementSibling?.tagName === 'note') {
      siblingNote = pointer?.nextElementSibling
    }
    pointer = pointer?.nextElementSibling
  }
  return siblingNote
}

export const onlyVisible = (xml: any, partIndex: any) => {
  if (!xml) return ''
  const xmlParse = new DOMParser().parseFromString(xml, 'text/xml')
  const partList =
    xmlParse.getElementsByTagName('part-list')?.[0]?.getElementsByTagName('score-part') || []
  const parts = xmlParse.getElementsByTagName('part')
  const visiblePartInfo = partList[partIndex]
  if (visiblePartInfo) {
    const id = visiblePartInfo.getAttribute('id')
    Array.from(parts).forEach((part) => {
      if (part && part.getAttribute('id') !== id) {
        part.parentNode?.removeChild(part)
        // 不等于第一行才添加避免重复添加
      }

      // 最后一个小节的结束线元素不在最后 调整
      if (part && part.getAttribute('id') === id) {
        const barlines = part.getElementsByTagName('barline')
        const lastParent = barlines[barlines.length - 1]?.parentElement
        if (lastParent?.lastElementChild?.tagName !== 'barline') {
          const children: any[] = (lastParent?.children as any) || []
          for (let el of children) {
            if (el.tagName === 'barline') {
              // 将结束线元素放到最后
              lastParent?.appendChild(el)
              break
            }
          }
        }
      }
    })
    Array.from(partList).forEach((part) => {
      if (part && part.getAttribute('id') !== id) {
        part.parentNode?.removeChild(part)
      }
    })
    // 处理装饰音问题
    const notes = xmlParse.getElementsByTagName('note')
    const getNextvNoteDuration = (i: any) => {
      let nextNote = notes[i + 1]
      // 可能存在多个装饰音问题，取下一个非装饰音时值
      for (let index = i; index < notes.length; index++) {
        const note = notes[index]
        if (!note.getElementsByTagName('grace')?.length) {
          nextNote = note
          break
        }
      }
      return nextNote?.getElementsByTagName('duration')[0]
    }
    Array.from(notes).forEach((note, i) => {
      const graces = note.getElementsByTagName('grace')
      if (graces && graces.length) {
        note.appendChild(getNextvNoteDuration(i)?.cloneNode(true))
      }
    })
  }
  return new XMLSerializer().serializeToString(xmlParse)
}

const speedInfo = {
  'rall.': 1.333333333,
  'poco rit.': 1.333333333,
  'rit.': 1.333333333,
  'molto rit.': 1.333333333,
  'molto rall': 1.333333333,
  molto: 1.333333333,
  lentando: 1.333333333,
  allargando: 1.333333333,
  morendo: 1.333333333,
  'accel.': 0.8,
  calando: 2,
  'poco accel.': 0.8,
  'gradually slowing': 1.333333333,
  slowing: 1.333333333,
  slow: 1.333333333,
  slowly: 1.333333333,
  faster: 1.333333333,
  "molto allargando": 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) || k === textContent
    })
    if (
      ele.type === 'metronome' ||
      (ele.type === 'words' && (textContent.startsWith('a tempo') || isKeyWork)) ||
      isLastNoteAndNotClosed
    ) {
      const indexOf = gradualNotes.findIndex((item) => item.length === 1)
      if (indexOf > -1 && ele.index > gradualNotes[indexOf]?.[0].start) {
        gradualNotes[indexOf][1] = {
          start: ele.index,
          measureIndex: ele.measureIndex,
          noteInMeasureIndex: ele.noteInMeasureIndex,
          allDuration: ele.allDuration,
          leftDuration: ele.leftDuration,
          type: textContent
        }
      }
    }
    if (ele.type === 'words' && isKeyWork) {
      gradualNotes.push([
        {
          start: ele.index,
          measureIndex: ele.measureIndex,
          noteInMeasureIndex: ele.noteInMeasureIndex,
          allDuration: ele.allDuration,
          leftDuration: ele.leftDuration,
          type: textContent
        }
      ])
    }
  }
  return gradualNotes
}

export default defineComponent({
  name: 'music-operation',
  props: {
    type: {
      type: String,
      default: 'add'
    },
    data: {
      type: Object as PropType<any>,
      default: () => {}
    },
    tagList: {
      type: Array as PropType<Array<SelectOption>>,
      default: () => []
    },
    subjectList: {
      type: Array as PropType<Array<SelectOption>>,
      default: () => []
    }
    // musicSheetCategories: {
    //   type: Array as PropType<Array<SelectOption>>,
    //   default: () => []
    // }
  },
  emits: ['close', 'getList'],

  setup(props, { slots, attrs, emit }) {
    const forms = reactive({
      details: {} as any, // 曲目详情
      graduals: {} as any, // 渐变速度
      playMode: 'MP3', // 播放类型
      xmlFileUrl: null, // XML
      midiUrl: null, // mid
      name: null, // 曲目名称
      // musicTag: [] as any, // 曲目标签
      composer: null, // 音乐人
      playSpeed: null as any, // 曲谱速度
      // showFingering: null as any, // 是否显示指法
      // canEvaluate: null as any, // 是否评测
      // notation: null as any, // 能否转和简谱
      // auditVersion: null as any, // 审核版本
      // sortNumber: null, // 排序
      musicCover: null, // 曲谱封面
      remark: null, // 曲谱描述
      musicSheetSoundList: [] as any, // 原音
      // musicSheetCategoriesId: null,
      status: false,
      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:是)
      repeatedBeats: false, // 是否重复节拍时长
      evaluationStandard: 'FREQUENCY', // 评分标准 节奏 AMPLITUDE 音准 FREQUENCY 分贝 DECIBELS
      multiTracksSelection: [] as any, // 声轨
      musicSheetExtend: {} as any, //所属人信息
      musicImg: '', // 五线谱图片
      musicFirstImg: '', //首调图片
      musicJianImg: '', // 简谱固定调
      isEvxml: false, // 是否是evxml
      isShowFingering: true // 是否显示指法
    })
    const state = reactive({
      loading: false,
      previewMode: false, //是否是预览模式
      tagList: [...props.tagList] as any, // 标签列表
      xmlFirstSpeed: null as any, // 第一个音轨速度
      partListNames: [] as any, // 所有音轨声部列表
      musicSheetCategories: [] as any,
      musicSheetAccompanimentUrls: '' as any,
      musicSheetAccompanimentUrlList: [] as any,
      instrumentData: [],
      instrumentList: [],
      subjectList: [] as any,
      showMusicSheetOwnerDialog: false, //所属人弹框
      // musicSheetOwnerData: {}, //所属人信息
      multiTracks: null as any,
      appData: [], // 应用列表
      ownerName: null as any, // 所属人名称描述

      productOpen: false, // 是否打开自动生成图片
      productItem: {} as any,
      productIfameSrc: '',
      isAutoSave: false // 是否自动保存
    })
    const gradualData = reactive({
      list: [] as any[],
      gradualRefs: [] as any[]
    })

    const btnLoading = ref(false)
    const formsRef = ref()
    const message = useMessage()
    const dialog = useDialog()

    // 提交记录
    const onSubmit = async () => {
      formsRef.value.validate(async (error: any) => {
        if (error) {
          return
        }
        if (!state.isAutoSave) {
          state.isAutoSave = true
          state.productOpen = true
          return
        }
        try {
          //extConfigJson: {"repeatedBeats":0,"gradualTimes":{"75":"02:38:60","77":"02:43:39"}}
          const obj = {
            ...forms,
            musicSheetExtend: forms.sourceType == 'PLATFORM' ? null : forms.musicSheetExtend,
            musicTag: '-1',
            multiTracksSelection: forms.multiTracksSelection.join(','),
            musicSheetSoundList: forms.musicSheetSoundList.filter((next: any) => {
              return (
                !!next.audioFileUrl &&
                (!next.track || forms.multiTracksSelection.includes(next.track))
              )
            }),
            musicalInstrumentIds: forms.musicalInstrumentIdList.join(','),
            extConfigJson: JSON.stringify({
              repeatedBeats: forms.repeatedBeats ? 1 : 0,
              gradualTimes: forms.graduals,
              isEvxml: forms.isEvxml ? 1 : 0
            }),
            subjectIds: forms.subjectIds.join(',')
          }
          if (forms.audioType == 'MIDI') {
            obj.musicSheetSoundList = []
          }
          btnLoading.value = true
          if (props.type === 'add') {
            await musicSheetSave(obj)
            message.success('添加成功')
          } else if (props.type === 'edit') {
            await musicSheetSave({ ...obj, id: props.data.id })
            message.success('修改成功')
          }
          emit('getList')
          emit('close')
        } catch (e) {
          console.log(e)
        }
        setTimeout(() => {
          btnLoading.value = false
        }, 100)
      })
    }

    // 上传XML，初始化音轨 音轨速度 乐器、声部
    const readFileInputEventAsArrayBuffer = (file: any) => {
      // 是否是evxml
      // forms.isEvxml = file?.name?.includes('.evxml') ? true : false;
      const xmlRead = new FileReader()
      xmlRead.onload = (res) => {
        try {
          gradualData.list = getGradualLengthByXml(res?.target?.result as any).filter(
            (item: any) => item.length === 2
          )
        } catch (error) {}

        forms.musicSheetSoundList = forms.musicSheetSoundList.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.length; i++) {
          let track = forms.musicSheetSoundList[i].track
          if (track) {
            map.set(track, forms.musicSheetSoundList[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.length; i++) {
          let track = forms.musicSheetSoundList[i].track
          if (!track || !tracks.includes(track)) {
            forms.musicSheetSoundList[i].track = null
            newMusicSheetSoundList.push(forms.musicSheetSoundList[i])
          }
        }
        forms.musicSheetSoundList = 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.length == 0) {
          forms.musicSheetSoundList.push({ audioFileUrl: '', track: '' })
        }
      }
      xmlRead.readAsText(file)
    }

    const containOther = (track: any) => {
      for (let i = 0; i < state.partListNames.length; i++) {
        if (state.partListNames[i].value == track) {
          return true
        }
      }
      return false
    }

    const validSoundNum = () => {
      return forms.musicSheetSoundList.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('score-part')
      const instrumentEle: any =
        xmlParse.getElementsByTagName('part-list')?.[0]?.getElementsByTagName('score-part') || []
      for (let index = 0; index < instrumentEle.length; index++) {
        const note = instrumentEle[index]
        let instrumentCode = note.getElementsByTagName('part-name')?.[0]?.textContent || ''
        instrumentCode = instrumentCode.toLocaleLowerCase().trim()
        if (instrumentCode && !instrumentCodeList.includes(instrumentCode)) {
          instrumentCodeList.push(instrumentCode)
        }
      }
      // 乐器支持多编码，暂不开放
      const codeIdMap = new Map<string, []>() as any
      state.instrumentData.forEach((data: any) => {
        if (!data.disabled) {
          const codes = data.code.split(/[,，]/)
          codes.forEach((code: string) => {
            let codeTemp = code.trim().toLowerCase()
            if (codeIdMap.has(codeTemp)) {
              codeIdMap.get(codeTemp).push(data.id + '')
            } else {
              const arr = [] as any
              arr.push(data.id + '')
              codeIdMap.set(codeTemp, arr)
            }
          })
        }
      })
      forms.musicalInstrumentIdList = []

      instrumentCodeList.forEach((code: string) => {
        if (codeIdMap.has(code)) {
          codeIdMap.get(code).forEach((c: any) => {
            if (!forms.musicalInstrumentIdList.includes(c)) {
              forms.musicalInstrumentIdList.push(c)
            }
          })
        }
      })
      // const codeIdMap = new Map<string, string>()
      // state.instrumentData.forEach((data: any) => {
      //   if (!data.disabled) {
      //     codeIdMap.set(data.code.toLocaleLowerCase().trim(), data.id + '')
      //   }
      // })
      // forms.musicalInstrumentIdList = []
      // instrumentCodeList.forEach((code: string) => {
      //   if (codeIdMap.has(code)) {
      //     forms.musicalInstrumentIdList.push(codeIdMap.get(code))
      //   }
      // })

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

    // 获取xml中所有轨道 乐器
    const getPartListNames = (xml: any) => {
      if (!xml) return []
      const xmlParse = new DOMParser().parseFromString(xml, 'text/xml')
      const partList: any =
        xmlParse.getElementsByTagName('part-list')?.[0]?.getElementsByTagName('score-part') || []
      let partListNames = Array.from(partList).map((item: any) => {
        let part = item.getElementsByTagName('part-name')?.[0]
        // evxml没有分轨，需要手动设置一个默认的名称，用于上传原音
        // if (forms.isEvxml) {
        //   part = part || 'noPartName'
        // }
        // 优先解析声轨，没有就取id值
        let track = ''
        if (part) {
          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: []) => {
      try {
        const { data } = await subjectPage({
          page: 1,
          rows: 999,
          musicalInstrumentIdList: musicalInstrumentIdList
        })
        const tempList = data.rows || []
        tempList.forEach((item: any) => {
          forms.subjectIds.push(item.id + '')
        })
      } catch {}
    }

    // 添加原音
    const createSys = (initData?: any) => {
      forms.musicSheetSoundList.push({
        audioFileUrl: null, // 原音
        track: null, // 轨道
        ...initData
      })
    }
    // 删除原音
    const removeSys = (index: number) => {
      dialog.warning({
        title: '提示',
        content: `是否确认删除此原音？`,
        positiveText: '确定',
        negativeText: '取消',
        onPositiveClick: async () => {
          const sound = forms.musicSheetSoundList[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.splice(index, 1)
          }
        }
      })
    }

    const checkMultiTracks = (value: string) => {
      if (!value) {
        return
      }
      if (value === 'all') {
        forms.multiTracksSelection = []
        state.partListNames.forEach((next: any) => {
          forms.multiTracksSelection.push(next.value)
        })
      } else if (value === 'invert') {
        state.partListNames.forEach((next: any) => {
          const indexOf = forms.multiTracksSelection.indexOf(next.value)
          if (indexOf > -1) {
            forms.multiTracksSelection.splice(indexOf, 1)
          } else {
            forms.multiTracksSelection.push(next.value)
          }
        })
      } else if (value === 'allUncheck') {
        forms.multiTracksSelection = []
      }
    }

    const setOwnerName = () => {
      if (forms.sourceType == 'PLATFORM') {
        state.ownerName = ''
        return
      }
      if (!forms.sourceType || !forms.musicSheetExtend?.userId) {
        return
      }
      const appId = forms.musicSheetExtend.applicationId
      const app = state.appData.filter((next: any) => {
        return next.id == appId
      }) as any
      if (app.length > 0) {
        state.ownerName = app[0].appName
      }
      if (forms.sourceType == 'ORG') {
        state.ownerName += '-' + forms.musicSheetExtend.organizationRole
      } else if (forms.sourceType == 'PERSON') {
        state.ownerName +=
          '-' +
          getMapValueByKey(forms.musicSheetExtend.clientType, new Map(Object.entries(clientType)))
        if (forms.musicSheetExtend.userName) {
          state.ownerName += '-' + forms.musicSheetExtend.userName
        }
        if (forms.musicSheetExtend.phone) {
          state.ownerName += '(' + forms.musicSheetExtend.phone + ')'
        }
      }
    }

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

    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 || []
          state.instrumentData = tempList
          tempList.forEach((item: any) => {
            item.label = item.name
            item.value = item.id + ''
            item.disabled = !item.enableFlag
          })
          state.instrumentList = tempList
        } catch {}
      }
      state.subjectList = deepClone(props.subjectList)
      state.subjectList.forEach((subject: any) => {
        subject.disabled = !subject.enableFlag
      })

      // 初始化应用
      {
        const appKeys = Object.keys(appKey)

        const { data } = await sysApplicationPage({ page: 1, rows: 999, parentId: 0 })
        const tempList = data.rows || []
        const filter = tempList.filter((next: any) => {
          return appKeys.includes(next.appKey)
        })
        filter.forEach((item: any) => {
          item.label = item.appName
          item.value = item.id
        })
        state.appData = filter
      }

      // 获取分类信息
      {
        try {
          const { data } = await musicSheetCategoriesQueryTree({ enable: true })
          state.musicSheetCategories = filterPointCategory(data, 'musicSheetCategoriesList')
        } catch (e) {}
      }

      if (props.type === 'edit' || props.type === 'preview') {
        const detail = props.data
        try {
          const { data } = await musicSheetDetail({ id: detail.id })
          forms.details = data
          forms.playMode = data.playMode
          forms.xmlFileUrl = data.xmlFileUrl
          forms.midiUrl = data.midiUrl
          forms.name = data.name
          // forms.musicTag = data.musicTag?.split(',')
          forms.composer = data.composer
          forms.playSpeed = data.playSpeed ? Number.parseFloat(data.playSpeed) : 100
          // forms.showFingering = Number(data.showFingering)
          // forms.canEvaluate = Number(data.canEvaluate)
          // forms.notation = Number(data.notation)
          // forms.auditVersion = Number(data.auditVersion)
          // forms.sortNumber = data.sortNumber
          forms.musicCover = data.musicCover
          forms.remark = data.remark
          forms.status = data.status
          forms.musicSheetType = data.musicSheetType || 'SINGLE'
          forms.sourceType = data.sourceType
          forms.appAuditFlag = data.appAuditFlag ? 1 : 0
          forms.midiFileUrl = data.midiFileUrl
          forms.isShowFingering = data.isShowFingering
          forms.subjectIds = []
          if (data.subjectIds) {
            const subjectIds = data.subjectIds.split(',') || []
            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.musicalInstrumentIdList = data.musicalInstrumentIds
            ? data.musicalInstrumentIds.split(',')
            : []
          forms.musicCategoryId = data.musicCategoryId
          data.musicSheetAccompanimentList?.forEach((next: any) => {
            state.musicSheetAccompanimentUrlList.push(next.audioFileUrl)
          })
          forms.musicSheetAccompanimentList = data.musicSheetAccompanimentList
          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
          } catch (error) {}
          forms.evaluationStandard = data.evaluationStandard
          forms.musicSheetExtend = data.musicSheetExtend

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

              // 初始化音轨和原音
              let tracks = state.partListNames.map((next: any) => next.label)
              if (data.multiTracksSelection) {
                forms.multiTracksSelection = data.multiTracksSelection
                  .toLocaleUpperCase()
                  .split(',')
              } else {
                forms.multiTracksSelection.push('')
              }
              forms.multiTracksSelection = tracks.filter((next: any) =>
                forms.multiTracksSelection.includes(next.toLocaleUpperCase())
              )

              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.push({
                  audioFileUrl: existSoundList[0].audioFileUrl, // 原音
                  musicalInstrumentId: existSoundList[0].musicalInstrumentId,
                  track: track // 轨道
                })
                if (track && !forms.multiTracksSelection.includes(track)) {
                  forms.multiTracksSelection.push(track)
                }
              } else {
                state.partListNames.forEach((item: any) => {
                  let audioFileUrl = null
                  let musicalInstrumentId = null
                  existSoundList.forEach((next: any) => {
                    if (!next.track || next.track.trim() == '') {
                      next.track = ''
                    }
                    if (next.track == item.value) {
                      audioFileUrl = next.audioFileUrl
                      musicalInstrumentId = next.musicalInstrumentId
                    }
                  })
                  forms.musicSheetSoundList.push({
                    audioFileUrl: audioFileUrl, // 原音
                    musicalInstrumentId: musicalInstrumentId, // 乐器
                    track: item.value // 轨道
                  })
                })

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

                // 处理没有声轨，但有原音
                existSoundList
                  .filter((next: any) => {
                    return !tracks.includes(next.track)
                  })
                  .forEach((next: any) => {
                    forms.musicSheetSoundList.push({
                      audioFileUrl: next.audioFileUrl, // 原音
                      musicalInstrumentId: next.musicalInstrumentId,
                      track: next.track ? next.track : null // 轨道
                    })
                  })
              }
            }
          })
        } catch (error) {}
      } else {
        // 新增只能使用启用状态的数据
        state.subjectList = state.subjectList.filter((next: any) => {
          return next.enableFlag == true
        })
        state.instrumentList = state.instrumentList.filter((next: any) => {
          return next.enableFlag == true
        })
      }
      state.loading = false
    })

    return () => (
      <div style="background: #fff; padding-top: 12px">
        <NSpin show={state.loading}>
          <NForm
            class={styles.formContainer}
            model={forms}
            ref={formsRef}
            label-placement="left"
            label-width="150"
            disabled={state.previewMode}
          >
            <NAlert showIcon={false} style={{ marginBottom: '12px' }}>
              曲目信息
            </NAlert>
            <NGrid cols={2}>
              <NFormItemGi
                label="曲目名称"
                path="name"
                rule={[
                  {
                    required: true,
                    message: '请输入曲目名称',
                    trigger: ['input', 'blur']
                  }
                ]}
              >
                <NInput
                  v-model:value={forms.name}
                  placeholder="请输入曲目名称"
                  maxlength={50}
                  showCount
                />
              </NFormItemGi>
              <NFormItemGi
                label="音乐人"
                path="composer"
                rule={[
                  {
                    required: true,
                    message: '请输入音乐人',
                    trigger: ['input', 'blur']
                  }
                ]}
              >
                <NInput
                  v-model:value={forms.composer}
                  placeholder="请输入音乐人名称"
                  showCount
                  maxlength={14}
                />
              </NFormItemGi>
            </NGrid>
            <NGrid cols={2}>
              <NFormItemGi label="曲目描述" path="remark">
                <NInput
                  placeholder="请输入曲目描述"
                  type="textarea"
                  rows={4}
                  showCount
                  maxlength={200}
                  v-model:value={forms.remark}
                />
              </NFormItemGi>
              <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>
            </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>
              <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="repeatedBeats"
                rule={[
                  {
                    required: false,
                    message: '请选择是否重复节拍时长'
                  }
                ]}
              >
                <NRadioGroup v-model:value={forms.repeatedBeats}>
                  <NRadio value={true}>是</NRadio>
                  <NRadio value={false}>否</NRadio>
                </NRadioGroup>
              </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="playSpeed"
                rule={[
                  {
                    required: true,
                    message: '请输入速度'
                  }
                ]}
              >
                <NInputNumber
                  placeholder="请输入速度"
                  v-model:value={forms.playSpeed}
                  min="0"
                  style="width:100%"
                />
              </NFormItemGi>
            </NGrid>
            <NAlert showIcon={false} style={{ marginBottom: '12px' }}>
              曲目上传
            </NAlert>
            <NGrid cols={2}>
              <NFormItemGi
                label="播放模式"
                path="playMode"
                rule={[
                  {
                    required: true,
                    message: '请选择播放模式'
                  }
                ]}
              >
                <NRadioGroup
                  v-model:value={forms.playMode}
                  onUpdateValue={(value: string | number | boolean) => {
                    if (value === 'MP3') {
                      forms.playMode = 'MP3'
                    } else {
                      forms.playMode = 'MIDI'
                    }
                  }}
                >
                  <NRadio value="MP3">MP3</NRadio>
                  <NRadio value="MIDI">MID</NRadio>
                </NRadioGroup>
              </NFormItemGi>
              {forms.playMode === 'MP3' && (
                <NFormItemGi
                  label="伴奏类型"
                  path="audioType"
                  rule={[
                    {
                      required: true,
                      message: '请选择伴奏类型'
                    }
                  ]}
                >
                  <NRadioGroup v-model:value={forms.audioType}>
                    <NRadio value={'HOMEMODE'}>自制伴奏</NRadio>
                    <NRadio value={'COMMON'}>普通伴奏</NRadio>
                  </NRadioGroup>
                </NFormItemGi>
              )}
            </NGrid>
            <NGrid cols={2}>
              {forms.playMode === 'MP3' && (
                <NFormItemGi
                  label="上传伴奏"
                  path="musicSheetAccompanimentList"
                  rule={[
                    {
                      required: false,
                      message: '请选择上传.mp3'
                    }
                  ]}
                >
                  <UploadFile
                    disabled={state.previewMode}
                    size={30}
                    v-model:imageList={state.musicSheetAccompanimentUrlList}
                    tips="仅支持上传.mp3格式文件"
                    listType="image"
                    accept=".mp3"
                    bucketName="cloud-coach"
                    text="点击上传伴奏文件"
                    max={10}
                    desc={'上传伴奏文件'}
                    onUpload:success={(file) => {
                      state.musicSheetAccompanimentUrls = [
                        state.musicSheetAccompanimentUrls,
                        file.url
                      ]
                        .filter(Boolean)
                        .join(',')
                      state.musicSheetAccompanimentUrlList = state.musicSheetAccompanimentUrls
                        ?.split(',')
                        .filter(Boolean)
                      forms.musicSheetAccompanimentList = []
                      for (let i = 0; i < state.musicSheetAccompanimentUrlList.length; i++) {
                        forms.musicSheetAccompanimentList.push({
                          audioFileUrl: state.musicSheetAccompanimentUrlList[i],
                          sortNumber: i + 1
                        })
                      }
                    }}
                    onRemove={() => {
                      state.musicSheetAccompanimentUrlList = []
                      state.musicSheetAccompanimentUrls = ''
                    }}
                    // onReadFileInputEventAsArrayBuffer={readFileInputEventAsArrayBuffer}
                    multiple={true}
                  />
                </NFormItemGi>
              )}
              {forms.playMode === 'MIDI' && (
                <NFormItemGi
                  label="上传MID"
                  path="midiFileUrl"
                  rule={[
                    {
                      required: true,
                      message: '请选择上传.MID格式文件'
                    }
                  ]}
                >
                  <UploadFile
                    desc={'MIDI文件'}
                    disabled={state.previewMode}
                    size={30}
                    v-model:fileList={forms.midiFileUrl}
                    tips="仅支持上传.MID格式文件"
                    listType="image"
                    accept=".mid"
                    bucketName="cloud-coach"
                    text="点击上传MID文件"
                    // onReadFileInputEventAsArrayBuffer={readFileInputEventAsArrayBuffer}
                  />
                </NFormItemGi>
              )}
              <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 = []
                    forms.musicalInstrumentIdList = []
                    forms.subjectIds = []
                  }}
                />
              </NFormItemGi>
            </NGrid>

            <NGrid cols={2}>
              <NFormItemGi
                label="可用声部"
                path="subjectIds"
                rule={[
                  {
                    required: true,
                    message: '请选择可用声部',
                    trigger: 'change',
                    type: 'array'
                  }
                ]}
              >
                <NSelect
                  v-model:value={forms.subjectIds}
                  options={state.subjectList}
                  multiple
                  filterable
                  clearable
                  placeholder="请选择可用声部"
                  maxTagCount={2}
                />
              </NFormItemGi>
              <NFormItemGi
                label="可用乐器"
                path="musicalInstrumentIdList"
                rule={[
                  {
                    required: true,
                    message: '请选择可用乐器',
                    trigger: 'change',
                    type: 'array'
                  }
                ]}
              >
                <NSelect
                  placeholder="请选择可用乐器"
                  options={state.instrumentList}
                  v-model:value={forms.musicalInstrumentIdList}
                  clearable
                  multiple
                  filterable
                  maxTagCount={2}
                />
              </NFormItemGi>
            </NGrid>
            <NGrid cols={2}>
              <NFormItemGi
                label="多声轨渲染"
                path="musicSheetType"
                rule={[
                  {
                    required: true,
                    message: '请选择多声轨渲染',
                    trigger: 'change'
                  }
                ]}
              >
                {/*<NSelect*/}
                {/*    placeholder="请选择曲目类型"*/}
                {/*    v-model:value={forms.musicSheetType}*/}
                {/*    options={getSelectDataFromObj(musicSheetType)}*/}
                {/*/>*/}
                <NRadioGroup v-model:value={forms.musicSheetType}>
                  <NRadio value={'SINGLE'}>是</NRadio>
                  <NRadio value={'CONCERT'}>否</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>

            {forms.musicSheetType && (
              <NGrid cols={1}>
                <NFormItemGi
                  label={`${forms.musicSheetType === 'SINGLE' ? '页面渲染声轨' : '用户可切换声轨'}`}
                  path="multiTracksSelection"
                  rule={[
                    {
                      required: true,
                      message: `请选择${
                        forms.musicSheetType === 'SINGLE' ? '页面渲染声轨' : '用户可切换声轨'
                      }`,
                      trigger: 'change',
                      type: 'array'
                    }
                  ]}
                >
                  <NGrid style="padding-top: 4px;">
                    <NGi span={24}>
                      <NRadioGroup
                        v-model:value={state.multiTracks}
                        onUpdateValue={(value) => {
                          checkMultiTracks(value)
                        }}
                      >
                        <NRadio value={'all'}>全选</NRadio>
                        <NRadio value={'allUncheck'}>重置</NRadio>
                        <NRadio value={'invert'}>反选</NRadio>
                      </NRadioGroup>
                    </NGi>
                    {state.partListNames && state.partListNames.length > 0 && (
                      <NGi span={24} style={'margin-top:5px'}>
                        <NFormItemGi
                          label=""
                          path="multiTracksSelection"
                          rule={[
                            {
                              required: false
                            }
                          ]}
                        >
                          <NCheckboxGroup
                            v-model:value={forms.multiTracksSelection}
                            onUpdateValue={(val: any) => {
                              if (state.partListNames.length != val.length) {
                                state.multiTracks = null
                              } else {
                                state.multiTracks = 'all'
                              }
                              //
                              //   let removeTracks = [] as any
                              //   for (let i = 0; i < forms.multiTracksSelection.length; i++) {
                              //     let track = forms.musicSheetSoundList[i].track
                              //     if (!val.includes(track)) {
                              //       removeTracks.push(track)
                              //     }
                              //   }
                              //   // 新增
                              //   for (let i = 0; i < val.length; i++) {
                              //     let track = val.value;
                              //     let contain = false
                              //     for (let j = 0; j < forms.musicSheetSoundList.length; j++) {
                              //       let track1 = forms.musicSheetSoundList[i].track;
                              //       if (track == track1) {
                              //         contain = true
                              //         break
                              //       }
                              //     }
                              //     if (!contain) {
                              //       forms.musicSheetSoundList.push({audioFileUrl: null, track: track, musicalInstrumentId: null})
                              //     }
                              //   }
                              //   // 删除
                              //   if (removeTracks.length > 0) {
                              //     forms.musicSheetSoundList = forms.musicSheetSoundList.filter((val: any) => {
                              //       return removeTracks.includes(val)
                              //     })
                              //   }
                              //   forms.multiTracksSelection = val
                            }}
                          >
                            <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>
            )}
            <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>
            {!!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>
              </>
            )}

            {/* 只有播放类型为mp3时才会有原音 */}
            {forms.playMode === 'MP3' && forms.musicSheetSoundList.length > 0 && (
              <>
                {forms.musicSheetSoundList.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[${index}].audioFileUrl`}
                            rule={[
                              {
                                // required: forms.multiTracksSelection.indexOf(forms.musicSheetSoundList[index].audioFileUrl) > -1,
                                required: true,
                                message: `请上传${
                                  item.track ? item.track + '的' : '第' + (index + 1) + '个'
                                }原音`
                              }
                            ]}
                          >
                            <UploadFile
                              desc={'原音文件'}
                              disabled={state.previewMode}
                              size={100}
                              v-model:fileList={item.audioFileUrl}
                              tips="仅支持上传.mp3格式文件"
                              listType="image"
                              accept=".mp3"
                              bucketName="cloud-coach"
                            />
                          </NFormItemGi>
                          {state.partListNames.length > 0 && (
                            <NFormItemGi
                              span={12}
                              label="所属轨道"
                              path={`musicSheetSoundList[${index}].track`}
                              rule={[
                                {
                                  required: validSoundNum() > 1 && item.track == null,
                                  message: '请选择所属轨道'
                                }
                              ]}
                            >
                              <NSelect
                                placeholder="请选择所属轨道"
                                value={item.track}
                                options={initPartsListStatus(item.track)}
                                onUpdateValue={(value: any) => {
                                  const track = item.track

                                  if (track) {
                                    // 声轨交换
                                    forms.musicSheetSoundList.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 = forms.musicSheetSoundList.filter(
                                      (next: any) => {
                                        return next.track != value
                                      }
                                    )
                                  }

                                  if (
                                    value != null &&
                                    !forms.multiTracksSelection.includes(value)
                                  ) {
                                    forms.multiTracksSelection.push(value)
                                  }
                                  item.track = value
                                }}
                              />
                            </NFormItemGi>
                          )}
                          <NGi class={styles.btnRemove}>
                            <NButton
                              type="primary"
                              text
                              // disabled={forms.musicSheetSoundList.length === 1}
                              onClick={() => removeSys(index)}
                            >
                              删除
                            </NButton>
                          </NGi>
                        </NGrid>
                      )}
                    </>
                  )
                })}
              </>
            )}
          </NForm>
        </NSpin>
        {props.type !== 'preview' && (
          <NSpace justify="end" style="padding-top:12px">
            <NButton type="default" onClick={() => emit('close')}>
              取消
            </NButton>
            <NButton
              type="primary"
              onClick={() => onSubmit()}
              loading={btnLoading.value}
              disabled={btnLoading.value}
            >
              确认
            </NButton>
          </NSpace>
        )}

        <NModal
          v-model:show={state.showMusicSheetOwnerDialog}
          preset="dialog"
          showIcon={false}
          maskClosable={false}
          title="所属人"
          style={{ width: '800px' }}
        >
          <MusicSheetOwnerDialog
            musicSheetExtend={forms.musicSheetExtend}
            sourceType={forms.sourceType}
            appData={state.appData}
            onClose={() => {
              state.showMusicSheetOwnerDialog = false
            }}
            onChoseMusicSheetOwnerData={(musicSheetOwnerData) => {
              forms.musicSheetExtend = {
                ...musicSheetOwnerData
              }
              setOwnerName()
            }}
          />
        </NModal>

        <NModal
          class={styles.productModal}
          title="自动生成曲谱图片"
          v-model:show={state.productOpen}
          preset="dialog"
          closeOnEsc={false}
          maskClosable={false}
          showIcon={false}
        >
          <MusicCreateImg
            xmlFileUrl={forms.xmlFileUrl || ''}
            onClose={() => (state.productOpen = false)}
            onConfirm={async (item: any) => {
              // 保存
              try {
                forms.musicImg = item.musicImg
                forms.musicFirstImg = item.musicFirstImg
                forms.musicJianImg = item.musicJianImg
                onSubmit()
              } catch (e: any) {
                //
                console.log(e, 'e')
              }
              setTimeout(() => {
                state.isAutoSave = false
              }, 50)
            }}
          />
        </NModal>
      </div>
    )
  }
})
