import {
  NForm,
  NFormItem,
  NInput,
  NSelect,
  NSpace,
  NButton,
  useMessage,
  NRadioGroup,
  NRadio,
  NGrid,
  NFormItemGi,
  NInputNumber,
  NGi,
  useDialog,
  NCascader,
  NAlert,
  NInputGroup,
  NInputGroupLabel
} from 'naive-ui'
import type { SelectOption } from 'naive-ui'
import { defineComponent, onMounted, PropType, reactive, ref } from 'vue'
import { musicSheetDetail, musicSheetSave, musicSheetUpdate } from '../../api'
import UploadFile from '@/components/upload-file'
import styles from './index.module.less'
import deepClone from '@/utils/deep.clone'
import axios from 'axios'

/**
 * 获取指定元素下一个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
        }
      }
      const nextNoteDuration = nextNote?.getElementsByTagName('duration')[0]
      return nextNoteDuration
    }
    Array.from(notes).forEach((note, i) => {
      const graces = note.getElementsByTagName('grace')
      if (graces && graces.length) {
        note.appendChild(getNextvNoteDuration(i)?.cloneNode(true))
      }
    })
  }
  return new XMLSerializer().serializeToString(xmlParse)
}

const speedInfo = {
  'rall.': 1.333333333,
  'poco rit.': 1.333333333,
  'rit.': 1.333333333,
  'molto rit.': 1.333333333,
  'molto rall': 1.333333333,
  molto: 1.333333333,
  lentando: 1.333333333,
  allargando: 1.333333333,
  morendo: 1.333333333,
  'accel.': 0.8,
  calando: 2,
  'poco accel.': 0.8,
  'gradually slowing': 1.333333333,
  slowing: 1.333333333,
  slow: 1.333333333,
  slowly: 1.333333333,
  faster: 1.333333333
}

/**
 * 按照xml进行减慢速度的计算
 * @param xml 始终按照第一分谱进行减慢速度的计算
 */
export function getGradualLengthByXml(xml: string) {
  const firstPartXml = onlyVisible(xml, 0)
  const xmlParse = new DOMParser().parseFromString(firstPartXml, 'text/xml')
  const measures = Array.from(xmlParse.querySelectorAll('measure'))
  const notes = Array.from(xmlParse.querySelectorAll('note'))
  const words = Array.from(xmlParse.querySelectorAll('words'))
  const metronomes = Array.from(xmlParse.querySelectorAll('metronome'))

  const eles = []

  for (const ele of [...words, ...metronomes]) {
    const note = getNextNote(ele, 'direction')
    // console.log(ele, note)
    if (note) {
      const measure = note?.closest('measure')
      const measureNotes = Array.from(measure.querySelectorAll('note'))

      const noteInMeasureIndex = Array.from(measure.childNodes)
        .filter((item: any) => item.nodeName === 'note')
        .findIndex((item) => item === note)

      let allDuration = 0
      let leftDuration = 0
      for (let i = 0; i < measureNotes.length; i++) {
        const n: any = measureNotes[i]
        const duration = +(n.querySelector('duration')?.textContent || '0')
        allDuration += duration
        if (i < noteInMeasureIndex) {
          leftDuration = allDuration
        }
      }
      eles.push({
        ele,
        index: notes.indexOf(note),
        noteInMeasureIndex,
        textContent: ele.textContent,
        measureIndex: measures.indexOf(measure), //,measure?.getAttribute('number')
        type: ele.tagName,
        allDuration,
        leftDuration
      })
    }
  }

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

  const gradualNotes: any[] = []
  eles.sort((a, b) => a.index - b.index)
  const keys = Object.keys(speedInfo).map((w) => w.toLocaleLowerCase())
  let isLastNoteAndNotClosed = false
  for (const ele of eles) {
    const textContent: any = ele.textContent?.toLocaleLowerCase().trim()
    if (ele === eles[eles.length - 1]) {
      if (gradualNotes[gradualNotes.length - 1]?.length === 1) {
        isLastNoteAndNotClosed = true
      }
    }

    const isKeyWork = keys.find((k) => {
      const ks = k.split(' ')
      return textContent && ks.includes(textContent)
    })
    if (
      ele.type === 'metronome' ||
      (ele.type === 'words' && (textContent.startsWith('a tempo') || isKeyWork)) ||
      isLastNoteAndNotClosed
    ) {
      const indexOf = gradualNotes.findIndex((item) => item.length === 1)
      if (indexOf > -1 && ele.index > gradualNotes[indexOf]?.[0].start) {
        gradualNotes[indexOf][1] = {
          start: ele.index,
          measureIndex: ele.measureIndex,
          noteInMeasureIndex: ele.noteInMeasureIndex,
          allDuration: ele.allDuration,
          leftDuration: ele.leftDuration,
          type: textContent
        }
      }
    }
    if (ele.type === 'words' && isKeyWork) {
      gradualNotes.push([
        {
          start: ele.index,
          measureIndex: ele.measureIndex,
          noteInMeasureIndex: ele.noteInMeasureIndex,
          allDuration: ele.allDuration,
          leftDuration: ele.leftDuration,
          type: textContent
        }
      ])
    }
  }
  return gradualNotes
}

export default defineComponent({
  name: 'city-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({
      graduals: {} as any, // 渐变速度
      audioType: 'MP3', // 播放类型
      mp3Type: 'MP3', // 是否含节拍器
      xmlFileUrl: null, // XML
      midiUrl: null, // mid
      metronomeUrl: null, // 伴奏 根据mp3Type 是否是为包含节拍器
      name: null, // 曲目名称
      musicTag: [] as any, // 曲目标签
      composer: null, // 音乐人
      playSpeed: null, // 曲谱速度
      showFingering: null as any, // 是否显示指法
      canEvaluate: null as any, // 是否评测
      musicSubject: null as any, // 可用声部
      notation: null as any, // 能否转和简谱
      auditVersion: null as any, // 审核版本
      accompanimentType: null, // 伴奏类型
      sortNumber: null, // 排序
      musicCover: null, // 曲谱封面
      remark: null, // 曲谱描述
      background: [] as any, // 原音
      musicSheetCategoriesId: null,
      status: false,
      musicSheetType: 'SINGLE' as 'SINGLE' | 'CONCERT'
    })
    const state = reactive({
      tagList: [...props.tagList] as any, // 标签列表
      xmlFirstSpeed: null as any, // 第一个音轨速度
      partListNames: [] as any, // 所有音轨声部列表
      musicSheetCategories: [...props.musicSheetCategories] as any
    })
    const gradualData = reactive({
      list: [] as any[],
      gradualRefs: [] as any[]
    })

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

    // 提交记录
    const onSubmit = async () => {
      formsRef.value.validate(async (error: any) => {
        console.log(error, 'error')
        if (error) {
          message.error(error[0]?.[0]?.message)
          return
        }
        try {
          const obj = {
            ...forms,
            musicTag: '-1',
            extConfigJson: JSON.stringify({ gradualTimes: forms.graduals })
          }
          if (forms.audioType == 'MIDI') {
            obj.background = []
          }
          btnLoading.value = true
          if (props.type === 'add') {
            await musicSheetSave({ ...obj })
            message.success('添加成功')
          } else if (props.type === 'edit') {
            await musicSheetUpdate({ ...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) => {
      const xmlRead = new FileReader()
      xmlRead.onload = (res) => {
        try {
          gradualData.list = getGradualLengthByXml(res?.target?.result as any).filter(
            (item: any) => item.length === 2
          )
        } catch (error) {}
        state.partListNames = getPartListNames(res?.target?.result as any) as any
        // 这里是如果没有当前音轨就重新写
        for (let j = 0; j < state.partListNames.length; j++) {
          if (!forms.background[j]) {
            forms.background.push({ audioFileUrl: null, track: null })
          }
          forms.background[j].track = state.partListNames[j].value
        }

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

        if (forms.background.length == 0) {
          forms.background.push({ audioFileUrl: '', track: '' })
        }
      }
      xmlRead.readAsText(file)
    }

    // 获取xml中所有轨道
    const getPartListNames = (xml: any) => {
      if (!xml) return []
      const xmlParse = new DOMParser().parseFromString(xml, 'text/xml')
      const partList =
        xmlParse.getElementsByTagName('part-list')?.[0]?.getElementsByTagName('score-part') || []
      const partListNames = Array.from(partList).map((item) => {
        const part = item.getElementsByTagName('part-name')?.[0].textContent || ''
        return {
          value: part,
          label: part
        }
      })

      if (partListNames.length > 0) {
        forms.background = forms.background.slice(0, partListNames.length)
      }

      state.xmlFirstSpeed = xmlParse.getElementsByTagName('per-minute')?.[0]?.textContent || ''
      if (!forms.playSpeed) {
        forms.playSpeed = state.xmlFirstSpeed
      }
      return partListNames
    }

    // 判断选择的音轨是否在选中
    const initPartsListStatus = (track: string): any => {
      const _names = state.partListNames.filter((n: any) => n.value?.toLocaleUpperCase?.() != 'COMMON')
      const partListNames = deepClone(_names) || []
      partListNames.forEach((item: any) => {
        const index = forms.background.findIndex((ground: any) => item.value == ground.track)
        if (index > -1 && track != item.value) {
          item.disabled = true
        } else {
          item.disabled = false
        }
      })
      return partListNames || []
    }

    // 添加原音
    const createSys = (initData?: any) => {
      forms.background.push({
        audioFileUrl: null, // 原音
        track: null, // 轨道
        ...initData
      })
    }
    // 删除原音
    const removeSys = (index: number) => {
      dialog.warning({
        title: '警告',
        content: `是否确认删除此原音？`,
        positiveText: '确定',
        negativeText: '取消',
        onPositiveClick: async () => {
          forms.background.splice(index, 1)
        }
      })
    }

    onMounted(async () => {
      if (props.type === 'edit') {
        const detail = props.data
        try {
          const { data } = await musicSheetDetail({ id: detail.id })
          forms.audioType = data.audioType
          forms.mp3Type = data.mp3Type
          forms.xmlFileUrl = data.xmlFileUrl
          forms.midiUrl = data.midiUrl
          forms.metronomeUrl = data.metronomeUrl
          forms.name = data.musicSheetName
          forms.musicTag = data.musicTag?.split(',')
          forms.composer = data.composer
          forms.playSpeed = data.playSpeed
          forms.showFingering = Number(data.showFingering)
          forms.canEvaluate = Number(data.canEvaluate)
          forms.musicSubject = data.musicSubject ? Number(data.musicSubject) : null
          forms.notation = Number(data.notation)
          forms.auditVersion = Number(data.auditVersion)
          forms.accompanimentType = data.accompanimentType
          forms.sortNumber = data.sortNumber
          forms.musicCover = data.titleImg
          forms.remark = data.remark
          forms.status = data.status
          forms.musicSheetCategoriesId = data.musicSheetCategoriesId
          forms.background = data.background || []
          forms.musicSheetType = data.musicSheetType || "SINGLE"
          // 获取渐变 和 是否多声部
          try {
            const extConfigJson = data.extConfigJson ? JSON.parse(data.extConfigJson) : {}
            forms.graduals = extConfigJson.gradualTimes || {}
          } catch (error) {}
          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
            }
          })
        } catch (error) {
          console.log(error)
        }
      }
    })

    return () => (
      <div style="background: #fff; padding-top: 12px">
        <NForm
          class={styles.formContainer}
          model={forms}
          ref={formsRef}
          label-placement="left"
          label-width="130"
        >
          <NGrid cols={2}>
            <NFormItemGi
              label="播放类型"
              path="audioType"
              rule={[
                {
                  required: true,
                  message: '请选择播放类型'
                }
              ]}
            >
              <NRadioGroup
                v-model:value={forms.audioType}
                onUpdateValue={(value: string | number | boolean) => {
                  console.log(value, 'value')
                  if (value === 'MP3') {
                    forms.mp3Type = 'MP3'
                  } else {
                    forms.mp3Type = ''
                  }
                }}
              >
                <NRadio value="MP3">MP3</NRadio>
                <NRadio value="MIDI">MIDI</NRadio>
              </NRadioGroup>
            </NFormItemGi>
            <NFormItemGi
                label="曲谱类型"
                path="musicSheetType"
                rule={[
                  {
                    required: true,
                    message: '请选择曲谱类型'
                  }
                ]}
              >
                <NRadioGroup v-model:value={forms.musicSheetType}>
                  <NRadio value="SINGLE">单曲</NRadio>
                  <NRadio value="CONCERT">合奏</NRadio>
                </NRadioGroup>
              </NFormItemGi>
            {/* 只有mp3 才有节拍器 */}
            {forms.audioType === 'MP3' && (
              <NFormItemGi
                label="是否含节拍器"
                path="mp3Type"
                rule={[
                  {
                    required: true,
                    message: '请选择是否含节拍器'
                  }
                ]}
              >
                <NRadioGroup v-model:value={forms.mp3Type}>
                  <NRadio value="MP3">不含节拍器</NRadio>
                  <NRadio value="MP3_METRONOME">含节拍器</NRadio>
                </NRadioGroup>
              </NFormItemGi>
            )}
          </NGrid>
          <NGrid cols={2}>
            <NFormItemGi
              label="上传XML"
              path="xmlFileUrl"
              rule={[
                {
                  required: true,
                  message: '请选择上传XML'
                }
              ]}
            >
              <UploadFile
                size={10}
                v-model:fileList={forms.xmlFileUrl}
                tips="仅支持上传.xml格式文件"
                listType="image"
                accept=".xml"
                bucketName="cloud-coach"
                text="点击上传XML"
                onReadFileInputEventAsArrayBuffer={readFileInputEventAsArrayBuffer}
              />
            </NFormItemGi>
            {forms.audioType === 'MIDI' && (
              <NFormItemGi
                label="上传mid"
                path="midiUrl"
                rule={[
                  {
                    required: true,
                    message: '请选择上传mid'
                  }
                ]}
              >
                <UploadFile
                  size={10}
                  v-model:fileList={forms.midiUrl}
                  tips="仅支持上传.mid格式文件"
                  listType="image"
                  accept=".mid"
                  bucketName="cloud-coach"
                  text="点击上传mid"
                />
              </NFormItemGi>
            )}
            {/* 只有播放类型为mp3时才会有伴奏 */}
            {forms.audioType === 'MP3' && (
              <NFormItemGi
                label={`伴奏(${forms.mp3Type === 'MP3' ? '不' : ''}含节拍器)`}
                path="metronomeUrl"
                rule={[
                  {
                    required: true,
                    message: '请选择上传伴奏'
                  }
                ]}
              >
                <UploadFile
                  size={10}
                  v-model:fileList={forms.metronomeUrl}
                  tips="仅支持上传.mp3/.aac格式文件"
                  listType="image"
                  accept=".mp3,.aac"
                  bucketName="cloud-coach"
                  text={`点击上传伴奏(${forms.mp3Type === 'MP3' ? '不' : ''}含节拍器)`}
                />
              </NFormItemGi>
            )}
            <NFormItemGi
              label="曲目名称"
              path="musicSheetName"
              rule={[
                {
                  required: true,
                  message: '请输入曲目名称'
                }
              ]}
            >
              <NInput v-model:value={forms.name} placeholder="请输入曲目名称" />
            </NFormItemGi>
            {/* <NFormItemGi
              label="曲目标签"
              path="musicTag"
              rule={[
                {
                  required: true,
                  message: '请选择曲目标签'
                }
              ]}
            >
              <NSelect
                placeholder="请选择曲目标签"
                v-model:value={forms.musicTag}
                options={state.tagList}
                multiple
                maxTagCount="responsive"
                onUpdate:value={(value: any) => {
                  // 判断条数
                  if (value.length === 3) {
                    state.tagList.forEach((item: any) => {
                      if (
                        forms.musicTag &&
                        typeof value === 'object' &&
                        value.includes(item.value)
                      ) {
                        item.disabled = false
                      } else {
                        item.disabled = true
                      }
                    })
                  } else {
                    state.tagList.forEach((item: any) => {
                      item.disabled = false
                    })
                  }
                }}
              />
            </NFormItemGi> */}
            <NFormItemGi
              label="曲目分类"
              path="musicSheetCategoriesId"
              rule={[
                {
                  required: true,
                  message: '请选择曲目分类'
                }
              ]}
            >
              <NCascader
                valueField="id"
                labelField="name"
                children-field="musicSheetCategoriesList"
                placeholder="请选择分类"
                v-model:value={forms.musicSheetCategoriesId}
                options={state.musicSheetCategories}
                clearable
              />
            </NFormItemGi>
            <NFormItemGi label="音乐人" path="composer">
              <NInput v-model:value={forms.composer} placeholder="请输入音乐人姓名" />
            </NFormItemGi>
            {forms.musicSheetType != 'CONCERT' && <NFormItemGi
              label="可用声部"
              path="musicSubject"
              rule={[
                {
                  required: true,
                  message: '请选择可用声部'
                }
              ]}
            >
              <NSelect
                v-model:value={forms.musicSubject}
                options={props.subjectList}
                filterable
                clearable
                placeholder="请选择可用声部"
              />
            </NFormItemGi>}
            <NFormItemGi
              label="指法展示"
              path="showFingering"
              rule={[
                {
                  required: true,
                  message: '请选择指法展示'
                }
              ]}
            >
              <NRadioGroup v-model:value={forms.showFingering}>
                <NRadio value={1}>展示</NRadio>
                <NRadio value={0}>不展示</NRadio>
              </NRadioGroup>
            </NFormItemGi>
            <NFormItemGi
              label="是否评测"
              path="canEvaluate"
              rule={[
                {
                  required: true,
                  message: '请选择是否评测'
                }
              ]}
            >
              <NRadioGroup v-model:value={forms.canEvaluate}>
                <NRadio value={1}>是</NRadio>
                <NRadio value={0}>否</NRadio>
              </NRadioGroup>
            </NFormItemGi>

            <NFormItemGi
              label="能否转简谱"
              path="notation"
              rule={[
                {
                  required: true,
                  message: '请选择能否转简谱'
                }
              ]}
            >
              <NRadioGroup v-model:value={forms.notation}>
                <NRadio value={1}>是</NRadio>
                <NRadio value={0}>否</NRadio>
              </NRadioGroup>
            </NFormItemGi>

            {/* <NFormItemGi
              label="伴奏类型"
              path="accompanimentType"
              rule={[
                {
                  required: true,
                  message: '请选择伴奏类型'
                }
              ]}
            >
              <NRadioGroup v-model:value={forms.accompanimentType}>
                <NRadio value="HOMEMODE">自制伴奏</NRadio>
                <NRadio value="COMMON">普通伴奏</NRadio>
              </NRadioGroup>
            </NFormItemGi> */}
            <NFormItemGi
              label="排序值"
              path="sortNumber"
              rule={[
                {
                  required: true,
                  message: '请输入排序值'
                }
              ]}
            >
              <NInputNumber
                v-model:value={forms.sortNumber}
                placeholder="请输入排序值"
                min={0}
                style={{ width: '100%' }}
              />
            </NFormItemGi>
          </NGrid>
          <NGrid cols={2}>
            <NFormItemGi label="曲谱封面" path="titleImg">
              <UploadFile
                accept=".jpg,.jpeg,.png"
                tips="请上传大小2M以内的JPG、PNG图片"
                v-model:fileList={forms.musicCover}
                cropper
                bucketName="cloud-coach"
                options={{
                  autoCrop: true, //是否默认生成截图框
                  enlarge: 2, //  图片放大倍数
                  autoCropWidth: 200, //默框高度
                  fixedBox: true, //是否固定截图框大认生成截图框宽度
                  autoCropHeight: 200, //默认生成截图小 不允许改变
                  previewsCircle: false, //预览图是否是原圆形
                  title: '曲谱封面'
                }}
              />
            </NFormItemGi>
            <NFormItemGi label="曲谱描述" path="remark">
              <NInput
                placeholder="请输入曲谱描述"
                type="textarea"
                rows={4}
                showCount
                maxlength={200}
                v-model:value={forms.remark}
              />
            </NFormItemGi>
          </NGrid>
          {!!gradualData.list.length && (
            <>
              <NAlert showIcon={false} type="info">
                识别到共1处渐变速度，请输入Dorico对应小节时间信息
              </NAlert>
              <NFormItem label="rit." required style={{ marginTop: '10px' }}>
                <NSpace vertical>
                  {gradualData.list.map((n: any, ni: number) => (
                    <NInputGroup>
                      <NFormItem
                        path={`graduals.${n[0].measureIndex}`}
                        rule={[
                          { required: true, message: '请输入合奏曲目时间' },
                          {
                            pattern: /^((\d{2}):?){2,3}$/,
                            message: '请输入正确的曲目时间',
                            trigger: 'blur'
                          }
                        ]}
                      >
                        <NInputGroup>
                          <NInputGroupLabel>{n[0].measureIndex}小节开始</NInputGroupLabel>
                          <NInput
                            placeholder="00:00:00"
                            v-model:value={forms.graduals[n[0].measureIndex]}
                          ></NInput>
                        </NInputGroup>
                      </NFormItem>
                      <div style={{ lineHeight: '30px', padding: '0 4px' }}>~</div>
                      <NFormItem
                        path={`graduals.${n[1].measureIndex}`}
                        rule={[
                          { required: true, message: '请输入合奏曲目时间' },
                          {
                            pattern: /^((\d{2}):?){2,3}$/,
                            message: '请输入正确的曲目时间',
                            trigger: 'blur'
                          }
                        ]}
                      >
                        <NInputGroup>
                          <NInput
                            placeholder="00:00:00"
                            v-model:value={forms.graduals[n[1].measureIndex]}
                          ></NInput>
                          <NInputGroupLabel>{n[1].measureIndex}小节结束</NInputGroupLabel>
                        </NInputGroup>
                      </NFormItem>
                    </NInputGroup>
                  ))}
                </NSpace>
              </NFormItem>
            </>
          )}
          <NFormItem label="曲谱速度">
            <NInputNumber v-model:value={forms.playSpeed} showButton={false} />
          </NFormItem>
          {/* 只有播放类型为mp3时才会有原音 */}
          {forms.audioType === 'MP3' && (
            <>
              {forms.background.map((item: any, index: number) => (
                <>
                  {item.track?.toLocaleUpperCase?.() != 'COMMON' && <NGrid class={styles.audioSection}>
                    <NFormItemGi
                      span={12}
                      label="原音"
                      path={`background[${index}].audioFileUrl`}
                      rule={[
                        {
                          required: true,
                          message: `请上传${
                            item.track ? item.track + '的' : '第' + (index + 1) + '个'
                          }原音`
                        }
                      ]}
                    >
                      <UploadFile
                        size={10}
                        v-model:fileList={item.audioFileUrl}
                        tips="仅支持上传.mp3/.aac格式文件"
                        listType="image"
                        accept=".mp3,.aac"
                        bucketName="cloud-coach"
                      />
                    </NFormItemGi>
                    {state.partListNames.length > 1 && (
                      <NFormItemGi
                        span={12}
                        label="所属轨道"
                        path={`background[${index}].track`}
                        rule={[
                          {
                            required: true,
                            message: '请选择所属轨道'
                          }
                        ]}
                      >
                        <NSelect
                          placeholder="请选择所属轨道"
                          v-model:value={item.track}
                          options={initPartsListStatus(item.track)}
                        />
                      </NFormItemGi>
                    )}
                    <NGi class={styles.btnRemove}>
                      <NButton
                        type="primary"
                        text
                        disabled={forms.background.length === 1}
                        onClick={() => removeSys(index)}
                      >
                        删除
                      </NButton>
                    </NGi>
                  </NGrid>}
                </>
              ))}

              <NButton
                type="primary"
                dashed
                block
                disabled={state.partListNames.length <= forms.background.length}
                style={{
                  marginBottom: '24px'
                }}
                onClick={createSys}
              >
                添加原音
              </NButton>
            </>
          )}
        </NForm>

        <NSpace justify="end">
          <NButton type="default" onClick={() => emit('close')}>
            取消
          </NButton>
          <NButton
            type="primary"
            onClick={() => onSubmit()}
            loading={btnLoading.value}
            disabled={btnLoading.value}
          >
            保存
          </NButton>
        </NSpace>
      </div>
    )
  }
})
