12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996 |
- import type { SelectOption } from 'naive-ui'
- import {
- NAlert,
- NButton,
- NCascader,
- NCheckbox,
- NCheckboxGroup,
- NDivider,
- NForm,
- NFormItem,
- NFormItemGi,
- NGi,
- NGrid,
- NInput,
- NInputGroup,
- NInputGroupLabel,
- NInputNumber,
- NModal,
- NRadio,
- NRadioGroup,
- NSelect,
- NSpace,
- NSpin,
- useDialog,
- useMessage
- } from 'naive-ui'
- import { defineComponent, onMounted, PropType, reactive, ref, watch, h } from 'vue'
- import { musicSheetCategoriesQueryTree, musicSheetDetail, musicSheetSave } from '../../api'
- import UploadFile from '@/components/upload-file'
- import styles from './index.module.less'
- import deepClone from '@/utils/deep.clone'
- import axios from 'axios'
- import { appKey, clientType, musicSheetSourceType } from '@/utils/constant'
- import { getMapValueByKey, getSelectDataFromObj } from '@/utils/objectUtil'
- import { musicalInstrumentPage } from '@views/system-manage/subject-manage/api'
- import { subjectPage } from '@views/system-manage/api'
- import MusicSheetOwnerDialog from '@views/music-library/music-sheet/modal/musicSheetOwnerDialog'
- import { sysApplicationPage } from '@views/menu-manage/api'
- import { filterPointCategory } from '@views/teaching-manage/unit-test'
- import MusicCreateImg from './music-create-img'
- import MusiceBeatTime from './musiceBeatTime'
- import MusicPlatform from './music-platform'
- import { formatBeatUnit } from "./config"
- /**
- * 获取指定元素下一个Note元素
- * @param ele 指定元素
- * @param selectors 选择器
- */
- const getNextNote = (ele: any, selectors: any) => {
- let index = 0
- const parentEle = ele.closest(selectors)
- let pointer = parentEle
- const measure = parentEle?.closest('measure')
- let siblingNote = null
- // 查找到相邻的第一个note元素
- while (!siblingNote && index < (measure?.childNodes.length || 50)) {
- index++
- if (pointer?.nextElementSibling?.tagName === 'note') {
- siblingNote = pointer?.nextElementSibling
- }
- pointer = pointer?.nextElementSibling
- }
- return siblingNote
- }
- export const onlyVisible = (xml: any, partIndex: any) => {
- if (!xml) return ''
- const xmlParse = new DOMParser().parseFromString(xml, 'text/xml')
- const partList =
- xmlParse.getElementsByTagName('part-list')?.[0]?.getElementsByTagName('score-part') || []
- const parts = xmlParse.getElementsByTagName('part')
- const visiblePartInfo = partList[partIndex]
- if (visiblePartInfo) {
- const id = visiblePartInfo.getAttribute('id')
- Array.from(parts).forEach((part) => {
- if (part && part.getAttribute('id') !== id) {
- part.parentNode?.removeChild(part)
- // 不等于第一行才添加避免重复添加
- }
- // 最后一个小节的结束线元素不在最后 调整
- if (part && part.getAttribute('id') === id) {
- const barlines = part.getElementsByTagName('barline')
- const lastParent = barlines[barlines.length - 1]?.parentElement
- if (lastParent?.lastElementChild?.tagName !== 'barline') {
- const children: any[] = (lastParent?.children as any) || []
- for (let el of children) {
- if (el.tagName === 'barline') {
- // 将结束线元素放到最后
- lastParent?.appendChild(el)
- break
- }
- }
- }
- }
- })
- Array.from(partList).forEach((part) => {
- if (part && part.getAttribute('id') !== id) {
- part.parentNode?.removeChild(part)
- }
- })
- // 处理装饰音问题
- const notes = xmlParse.getElementsByTagName('note')
- const getNextvNoteDuration = (i: any) => {
- let nextNote = notes[i + 1]
- // 可能存在多个装饰音问题,取下一个非装饰音时值
- for (let index = i; index < notes.length; index++) {
- const note = notes[index]
- if (!note.getElementsByTagName('grace')?.length) {
- nextNote = note
- break
- }
- }
- return nextNote?.getElementsByTagName('duration')[0]
- }
- Array.from(notes).forEach((note, i) => {
- const graces = note.getElementsByTagName('grace')
- if (graces && graces.length && getNextvNoteDuration(i)) {
- note?.appendChild(getNextvNoteDuration(i)?.cloneNode(true))
- }
- })
- }
- return new XMLSerializer().serializeToString(xmlParse)
- }
- const speedInfo = {
- 'rall.': 1.333333333,
- 'poco rit.': 1.333333333,
- 'rit.': 1.333333333,
- 'molto rit.': 1.333333333,
- 'molto rall': 1.333333333,
- molto: 1.333333333,
- lentando: 1.333333333,
- allargando: 1.333333333,
- morendo: 1.333333333,
- 'accel.': 0.8,
- calando: 2,
- 'poco accel.': 0.8,
- 'gradually slowing': 1.333333333,
- slowing: 1.333333333,
- slow: 1.333333333,
- slowly: 1.333333333,
- faster: 1.333333333,
- "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)
- })
- if (
- ele.type === 'metronome' ||
- (ele.type === 'words' && (textContent.startsWith('a tempo') || isKeyWork)) ||
- isLastNoteAndNotClosed
- ) {
- const indexOf = gradualNotes.findIndex((item) => item.length === 1)
- if (indexOf > -1 && ele.index > gradualNotes[indexOf]?.[0].start) {
- gradualNotes[indexOf][1] = {
- start: ele.index,
- measureIndex: ele.measureIndex,
- noteInMeasureIndex: ele.noteInMeasureIndex,
- allDuration: ele.allDuration,
- leftDuration: ele.leftDuration,
- type: textContent
- }
- }
- }
- if (ele.type === 'words' && isKeyWork) {
- gradualNotes.push([
- {
- start: ele.index,
- measureIndex: ele.measureIndex,
- noteInMeasureIndex: ele.noteInMeasureIndex,
- allDuration: ele.allDuration,
- leftDuration: ele.leftDuration,
- type: textContent
- }
- ])
- }
- }
- return gradualNotes
- }
- export type FormatXMLInfo = {
- speed: number
- title: string
- composer: string
- partNames: string[]
- }
- /** 获取xml基本信息,标题,速度等信息 */
- export const getXmlInfo = (xml: string): FormatXMLInfo => {
- const data: FormatXMLInfo = {
- /** 速度 */
- speed: 0,
- /** 标题 */
- title: '',
- /** 作曲人 */
- composer: '',
- /** 声部列表 */
- partNames: []
- }
- const xmlParse = new DOMParser().parseFromString(xml, 'text/xml')
- data.title = xmlParse.getElementsByTagName('work-title')[0]?.textContent || ''
- data.composer = xmlParse.getElementsByTagName('creator')[0]?.textContent || ''
- const measures = xmlParse.getElementsByTagName('measure')
- for (const item of Array.from(xmlParse.getElementsByTagName('part-name'))) {
- if (item.textContent?.trim()) {
- data.partNames.push(item.textContent)
- }
- }
- for (const measure of Array.from(measures)) {
- const perMinute = measure.getElementsByTagName('per-minute')
- if (perMinute.length && perMinute[perMinute.length - 1]) {
- data.speed = parseFloat(perMinute[perMinute.length - 1].textContent || '0')
- break
- }
- }
- return data
- }
- export default defineComponent({
- name: 'music-operation',
- props: {
- type: {
- type: String,
- default: 'add'
- },
- data: {
- type: Object as PropType<any>,
- default: () => {}
- },
- tagList: {
- type: Array as PropType<Array<SelectOption>>,
- default: () => []
- },
- subjectList: {
- type: Array as PropType<Array<SelectOption>>,
- default: () => []
- }
- // musicSheetCategories: {
- // type: Array as PropType<Array<SelectOption>>,
- // default: () => []
- // }
- },
- emits: ['close', 'getList'],
- setup(props, { slots, attrs, emit }) {
- const forms = reactive({
- details: {} as any, // 曲目详情
- graduals: {} as any, // 渐变速度
- playMode: 'MP3', // 播放类型
- xmlFileUrl: null, // XML
- midiUrl: null, // mid
- name: null, // 曲目名称
- // musicTag: [] as any, // 曲目标签
- composer: null as any, // 音乐人
- playSpeed: null as any, // 曲谱速度
- speedBeatUnit: null as any, // 曲谱速度节拍
- // showFingering: null as any, // 是否显示指法
- // canEvaluate: null as any, // 是否评测
- // notation: null as any, // 能否转和简谱
- // auditVersion: null as any, // 审核版本
- // sortNumber: null, // 排序
- musicCover: null, // 曲谱封面
- remark: null, // 曲谱描述
- // musicSheetSoundList: [] as any, // 原音
- musicSheetSoundList_YY: [] as any, // 演唱原音
- musicSheetSoundList_YZ: [] as any, // 演奏演奏
- musicSheetSoundList_all_subject: null, // 全部声部原音
- // musicSheetCategoriesId: null,
- status: true,
- musicSheetType: 'CONCERT', // 曲目类型
- sourceType: 'PLATFORM' as any, //来源类型/作者属性(PLATFORM: 平台; ORG: 机构; PERSON: 个人)
- // userId: null, // 所属人
- appAuditFlag: 0, // 是否审核版本
- midiFileUrl: null, // 伴奏文件 MIDI文件(保留字段)
- subjectIds: [] as any, // 可用声部
- musicalInstrumentIdList: [] as any, //可用乐器
- musicCategoryId: null, //曲目分类
- musicSheetAccompanimentList: [] as any, //曲目伴奏
- audioType: 'HOMEMODE', // 伴奏类型
- isPlayBeat: true, // 是否播放节拍器
- isUseSystemBeat: true, // 是否使用系统节拍器(0:否;1:是)
- isUseSingSystemBeat: true, //演唱是否使用系统节拍器(0:否;1:是)
- repeatedBeats: false, // 是否重复节拍时长
- repeatedBeatsToSing: false, //演唱是否重复节拍时长
- isPlaySingBeat: true, //是否播入演唱节拍器(0: 否 1:是)
- evaluationStandard: 'FREQUENCY', // 评分标准 节奏 AMPLITUDE 音准 FREQUENCY 分贝 DECIBELS
- multiTracksSelection: [] as any, // 声轨
- musicSheetExtend: {} as any, //所属人信息
- musicImg: '', // 五线谱图片
- musicFirstImg: '', //首调图片
- musicJianImg: '', // 简谱固定调
- isEvxml: false, // 是否是evxml
- isShowFingering: true, // 是否显示指法
- solmizationFileUrl: null, // 唱名文件
- isAllSubject: false, // 适用声部
- isMixBeat: true, // 是否生成节拍器
- musicPdfUrl: '', // 总谱五线谱PDF
- firstPdfUrl: '', // 总谱首调PDF
- jianPdfUrl: '', // 总谱固定PDF
- fSongList: [] as any, // 范唱列表
- isScoreRender: true, // 总谱渲染
- defaultScoreRender: false, // 演奏是否默认展示总谱渲染
- scoreAudioFileUrl: null as any // 总谱文件
- })
- const state = reactive({
- loading: false,
- musicUpdateLoading: false, // 是否在加载 中
- previewMode: false, //是否是预览模式
- tagList: [...props.tagList] as any, // 标签列表
- xmlFirstSpeed: null as any, // 第一个音轨速度
- partListNames: [] as any, // 所有音轨声部列表
- musicSheetCategories: [] as any,
- musicSheetAccompanimentUrl: null as any,
- instrumentData: [],
- instrumentList: [] as any,
- instrumentIdNameMap: new Map() as any,
- subjectList: [] as any,
- showMusicSheetOwnerDialog: false, //所属人弹框
- // musicSheetOwnerData: {}, //所属人信息
- multiTracks: null as any,
- multiInstruments: null,
- appData: [], // 应用列表
- ownerName: null as any, // 所属人名称描述
- productOpen: false, // 是否打开自动生成图片
- productItem: {} as any,
- productIfameSrc: '',
- isAutoSave: false, // 是否自动保存
- bSongFile: null as any, // 伴唱
- musicSheetSoundList: [] as any,
- subjectDisabled: false, // 声部不可用
- instrumentDisabled: false, // 乐器不可用
- initFSongMap: new Map() as any, //初始化的范唱
- showUseProject: false,
- showUseProjectId: null as any,
- useProjectData: [] as any,
- // 修改:修改内容XML(生成图片)、MP3(生成节拍器);其他情况无需生成图片、节拍器
- isCreateImg: false, // 是否生成图片
- isBeatTime: false // 是否生成节拍器
- })
- const gradualData = reactive({
- list: [] as any[],
- gradualRefs: [] as any[]
- })
- const beatTimeData = reactive({
- beatTimeOpen: false,
- musicId: ''
- })
- watch(
- () => forms.multiTracksSelection,
- (value) => {
- // 在修改的时候不用自动更新
- if (state.musicUpdateLoading) {
- state.musicUpdateLoading = false
- return
- }
- initInstrumentAndSubjectByTrack(value)
- initFSongList()
- }
- )
- const btnLoading = ref(false)
- const formsRef = ref()
- const message = useMessage()
- const dialog = useDialog()
- // 提交记录
- const onSubmit = async () => {
- formsRef.value.validate(async (error: any) => {
- if (error) {
- return
- }
- // 校验合奏时声轨与乐器是否存在不匹配情况
- if (forms.musicSheetType == 'CONCERT') {
- let set = [] as any
- const { data } = await musicalInstrumentPage({ page: 1, rows: 9999 })
- data.rows.map((row: any) => {
- if (row.code) {
- row.code.split(',').forEach((code: string) => {
- set.push(code.replaceAll(' ', '').toLocaleLowerCase())
- })
- }
- })
- let unDefinedTrack = [] as any
- forms.multiTracksSelection.forEach((item: any) => {
- if (item && !isPtrack(item)) {
- let contain = false
- let code = item.replace(' ', '').toLocaleLowerCase()
- for (let i = 0; i < set.length; i++) {
- if (code.startsWith(set[i])) {
- contain = true
- break
- }
- }
- if (!contain) {
- unDefinedTrack.push(item)
- }
- }
- })
- if (unDefinedTrack.length > 0) {
- dialog.warning({
- title: '提示',
- content: `声轨未配置:${unDefinedTrack.join(',')}`,
- positiveText: '确定',
- onPositiveClick: () => {}
- })
- return
- }
- }
- try {
- //extConfigJson: {"repeatedBeats":0,"gradualTimes":{"75":"02:38:60","77":"02:43:39"}}
- let audioPlayTypes = new Set() as any
- let musicSheetSoundList = []
- let musicSheetType = forms.musicSheetType
- let existYzFile = false
- // console.log({
- // musicSheetType,
- // fSongList: forms.fSongList,
- // isAllSubject: forms.isAllSubject,
- // musicSheetSoundList_all_subject: forms.musicSheetSoundList_all_subject,
- // musicSheetSoundList_YZ: forms.musicSheetSoundList_YZ,
- // playMode: forms.playMode,
- // musicalInstrumentIdList: forms.musicalInstrumentIdList
- // })
- // 判断 伴唱 范唱 唱名只有上传一个都可以上传
- let existFSFile = false
- for (let i = 0; i < forms.fSongList.length; i++) {
- let fSong = forms.fSongList[i]
- if (fSong.audioFileUrl || fSong.solmizationFileUrl || fSong.femaleSolmizationFileUrl) {
- musicSheetSoundList.push(fSong)
- audioPlayTypes.add('SING')
- existFSFile = true
- }
- }
- if (musicSheetType == 'SINGLE') {
- if (forms.isAllSubject) {
- if (forms.musicSheetSoundList_all_subject) {
- audioPlayTypes.add('PLAY')
- musicSheetSoundList.push({
- audioFileUrl: forms.musicSheetSoundList_all_subject,
- musicSheetId: props.data.id,
- audioPlayType: 'PLAY'
- })
- existYzFile = true
- }
- } else {
- if (forms.musicSheetSoundList_YZ.length > 0) {
- forms.musicSheetSoundList_YZ.forEach((musicSheetSound: any) => {
- if (
- forms.musicalInstrumentIdList.includes(musicSheetSound.musicalInstrumentId) &&
- musicSheetSound.audioFileUrl
- ) {
- existYzFile = true
- musicSheetSoundList.push({
- ...musicSheetSound,
- musicSheetId: props.data.id
- })
- // 判断是否显示
- if (!audioPlayTypes.has('PLAY')) {
- audioPlayTypes.add('PLAY')
- }
- }
- })
- }
- }
- } else if (musicSheetType == 'CONCERT') {
- forms.musicSheetSoundList_YY.forEach((musicSheetSound: any) => {
- if (
- musicSheetSound.audioFileUrl &&
- forms.multiTracksSelection.includes(musicSheetSound.track)
- ) {
- musicSheetSoundList.push({
- ...musicSheetSound,
- musicalInstrumentId:
- musicSheetSound.musicalInstrumentId ||
- instrumentCodeToInstrumentId(musicSheetSound.track),
- musicSheetId: props.data.id,
- audioPlayType: 'PLAY'
- })
- existYzFile = true
- if (!audioPlayTypes.has('PLAY')) {
- audioPlayTypes.add('PLAY')
- }
- }
- })
- }
-
- // 总谱 伴唱判断
- if (forms.scoreAudioFileUrl || state.bSongFile) {
- existFSFile = true
- }
- // 演唱 演奏只要有一个上传都可以
- if (!existFSFile && !existYzFile) {
- message.warning('请上传音频文件')
- return
- }
- // 生成图片
- if (!state.isAutoSave && state.isCreateImg) {
- state.isAutoSave = true
- state.productOpen = true
- return
- }
- // 判断是否有总谱
- // console.log(forms.scoreAudioFileUrl, 'forms.scoreAudioFileUrl')
- if (forms.scoreAudioFileUrl) {
- forms.musicSheetAccompanimentList.push({
- musicSheetId: props.data.id,
- audioFileUrl: state.bSongFile,
- scoreAudioFileUrl:
- forms.multiTracksSelection.length > 1 &&
- forms.isScoreRender &&
- forms.scoreAudioFileUrl
- ? forms.scoreAudioFileUrl
- : null,
- audioPlayType: 'SING'
- })
- } else {
- if(state.bSongFile) {
- forms.musicSheetAccompanimentList.push({
- musicSheetId: props.data.id,
- audioFileUrl: state.bSongFile,
- audioPlayType: 'SING'
- })
- }
-
- }
- if (state.musicSheetAccompanimentUrl) {
- forms.musicSheetAccompanimentList.push({
- musicSheetId: props.data.id,
- audioFileUrl: state.musicSheetAccompanimentUrl,
- audioPlayType: 'PLAY'
- })
- }
- let isScoreRender
- let defaultScoreRender
- if (forms.multiTracksSelection.length > 1) {
- isScoreRender = forms.isScoreRender
- if (forms.isScoreRender) {
- defaultScoreRender = forms.defaultScoreRender
- }
- }
- const obj = {
- musicCategoryId: forms.musicCategoryId,
- musicCover: forms.musicCover,
- name: forms.name,
- appAuditFlag: forms.appAuditFlag,
- subjectIds: forms.isAllSubject ? '' : forms.subjectIds.join(','),
- remark: forms.remark,
- audioPlayTypes: Array.from(audioPlayTypes).join(','),
- musicalInstrumentIds: forms.isAllSubject ? '' : forms.musicalInstrumentIdList.join(','),
- composer: forms.composer,
- musicSheetType: forms.musicSheetType,
- isUseSystemBeat: forms.isUseSystemBeat,
- isShowFingering: forms.isShowFingering,
- isPlayBeat: forms.isPlayBeat,
- multiTracksSelection: forms.multiTracksSelection.join(','),
- playSpeed: forms.playSpeed,
- speedBeatUnit: forms.speedBeatUnit || "1/4",
- playMode: forms.playMode,
- xmlFileUrl: forms.xmlFileUrl,
- isMixBeat: forms.isMixBeat,
- musicImg: forms.musicImg,
- musicFirstImg: forms.musicFirstImg,
- musicJianImg: forms.musicJianImg,
- musicPdfUrl: forms.musicPdfUrl,
- firstPdfUrl: forms.firstPdfUrl,
- jianPdfUrl: forms.jianPdfUrl,
- extConfigJson: JSON.stringify({
- repeatedBeats: forms.repeatedBeats ? 1 : 0,
- gradualTimes: forms.graduals,
- isEvxml: forms.isEvxml ? 1 : 0,
- repeatedBeatsToSing: forms.repeatedBeatsToSing ? 1 : 0
- }),
- // availableType: forms.availableType,
- sourceType: forms.sourceType,
- audioType: forms.audioType,
- status: forms.status,
- evaluationStandard: forms.evaluationStandard,
- musicSheetAccompanimentList: forms.musicSheetAccompanimentList,
- musicSheetSoundList: musicSheetSoundList,
- musicTag: '-1',
- isUseSingSystemBeat: forms.isUseSingSystemBeat,
- isPlaySingBeat: forms.isPlaySingBeat,
- isAllSubject: forms.isAllSubject,
- musicSheetExtend: forms.sourceType == 'PLATFORM' ? null : forms.musicSheetExtend,
- isScoreRender: isScoreRender,
- defaultScoreRender: defaultScoreRender
- }
- if (forms.audioType == 'MIDI') {
- obj.musicSheetSoundList = []
- }
- console.log(obj, 'obj')
- // return
- btnLoading.value = true
- let resData: any
- if (props.type === 'add') {
- resData = await musicSheetSave(obj)
- } else if (props.type === 'edit') {
- resData = await musicSheetSave({ ...obj, id: props.data.id })
- }
- //if (state.isBeatTime && forms.isMixBeat) {
- if (forms.isMixBeat) {
- beatTimeData.beatTimeOpen = true
- beatTimeData.musicId = resData.data
- state.showUseProjectId = resData.data
- } else {
- state.showUseProjectId = resData.data
- state.showUseProject = true
- setTimeout(() => {
- btnLoading.value = false
- state.isAutoSave = false
- }, 100)
- }
- } catch (e) {
- console.log(e)
- setTimeout(() => {
- btnLoading.value = false
- state.isAutoSave = false
- }, 100)
- }
- })
- }
- // 合成节拍器的回调
- function handlerMusiceBeatTimeClose(val: any) {
- if (!val) {
- if (props.type === 'add') {
- message.success('添加成功')
- } else if (props.type === 'edit') {
- message.success('修改成功')
- }
- }
- emit('getList')
- emit('close')
- setTimeout(() => {
- btnLoading.value = false
- state.isAutoSave = false
- }, 100)
- }
- const isPtrack = async (track: string) => {
- if (track && (track == 'P1' || track == 'P2' || track == 'P3' || track == 'P4')) {
- return true
- }
- return false
- }
- const initFSongList = async () => {
- forms.fSongList.forEach((fSong: any) => {
- state.initFSongMap.set(fSong.track, fSong)
- })
- let fSongList = [] as any
- forms.multiTracksSelection.forEach((item: any) => {
- if (state.initFSongMap.has(item)) {
- fSongList.push(state.initFSongMap.get(item))
- } else {
- fSongList.push({
- musicSheetId: props.data.id,
- audioFileUrl: null,
- audioPlayType: 'SING',
- musicalInstrumentId: null,
- track: item,
- // musicalInstrumentName: state.instrumentIdNameMap.get(item),
- musicalInstrumentName: null,
- solmizationFileUrl: null, // 唱名男
- femaleSolmizationFileUrl: null // 唱名女
- })
- }
- })
- forms.fSongList = fSongList
- }
- // 上传XML,初始化音轨 音轨速度 乐器、声部
- const readFileInputEventAsArrayBuffer = (file: any) => {
- state.isCreateImg = true // 更换XML
- // 是否是evxml
- const xmlRead = new FileReader()
- xmlRead.onload = (res) => {
- try {
- gradualData.list = getGradualLengthByXml(res?.target?.result as any).filter(
- (item: any) => item.length === 2
- )
- // 音乐人中有值,则不做更新
- const result = getXmlInfo(res?.target?.result as any)
- if (!forms.composer) {
- forms.composer = result.composer
- }
- } catch (error) {}
- forms.musicSheetSoundList_YY = forms.musicSheetSoundList_YY.filter((item: any) => {
- return (
- !item.track ||
- !containOther(item.track) ||
- (item.track?.toLocaleUpperCase?.() != 'COMMON' &&
- forms.multiTracksSelection.includes(item.track))
- )
- })
- state.partListNames = getPartListNames(res?.target?.result as any) as any
- // parseInstrumentAndSubject(res?.target?.result as any)
- // 这里是如果没有当前音轨就重新写
- let map = new Map<String, String>()
- for (let i = 0; i < forms.musicSheetSoundList_YY.length; i++) {
- let track = forms.musicSheetSoundList_YY[i].track
- if (track) {
- map.set(track, forms.musicSheetSoundList_YY[i])
- }
- }
- let newMusicSheetSoundList = []
- let tracks = [] as any
- for (let j = 0; j < state.partListNames.length; j++) {
- let track = state.partListNames[j].value
- if (map.has(track)) {
- newMusicSheetSoundList.push(map.get(track))
- } else {
- newMusicSheetSoundList.push({
- audioFileUrl: null,
- track: track,
- musicalInstrumentId: null
- })
- }
- tracks.push(track)
- if (!forms.multiTracksSelection.includes(track)) {
- forms.multiTracksSelection.push(track)
- }
- }
- for (let i = 0; i < forms.musicSheetSoundList_YY.length; i++) {
- let track = forms.musicSheetSoundList_YY[i].track
- if (!track || !tracks.includes(track)) {
- forms.musicSheetSoundList_YY[i].track = null
- newMusicSheetSoundList.push(forms.musicSheetSoundList_YY[i])
- }
- }
- forms.musicSheetSoundList_YY = newMusicSheetSoundList
- forms.multiTracksSelection = forms.multiTracksSelection.filter((track: any) => {
- return tracks.includes(track)
- })
- // 全选选中
- state.multiTracks = 'all'
- // 循环添加所在音轨的原音
- // for (let index = forms.musicSheetSoundList.length; index < state.partListNames.length; index++) {
- // const part = state.partListNames[index].value
- // const sysData = {
- // ...forms.musicSheetSoundList[0],
- // track: part
- // }
- // if (!sysData.speed) {
- // sysData.speed = state.xmlFirstSpeed
- // }
- // createSys(sysData)
- // }
- if (forms.musicSheetSoundList_YY.length == 0) {
- forms.musicSheetSoundList_YY.push({ audioFileUrl: '', track: '', musicPdfUrl: '', firstPdfUrl: '', jianPdfUrl: '' })
- }
- }
- xmlRead.readAsText(file)
- }
- const containOther = (track: any) => {
- for (let i = 0; i < state.partListNames.length; i++) {
- if (state.partListNames[i].value == track) {
- return true
- }
- }
- return false
- }
- const validSoundNum = () => {
- return forms.musicSheetSoundList_YY.filter((item: any) => {
- return (
- !item.track ||
- !containOther(item.track) ||
- (item.track?.toLocaleUpperCase?.() != 'COMMON' &&
- forms.multiTracksSelection.includes(item.track))
- )
- }).length
- }
- const parseInstrumentAndSubject = (xml: any) => {
- if (!xml) return
- const xmlParse = new DOMParser().parseFromString(xml, 'text/xml')
- // 乐器
- const instrumentCodeList: any = []
- const instrumentEle = xmlParse.getElementsByTagName('virtual-instrument')
- for (let index = 0; index < instrumentEle.length; index++) {
- const note = instrumentEle[index]
- let instrumentCode = note.getElementsByTagName('virtual-name')?.[0]?.textContent || ''
- instrumentCode = instrumentCode.toLocaleLowerCase().trim()
- if (instrumentCode && !instrumentCodeList.includes(instrumentCode)) {
- instrumentCodeList.push(instrumentCode)
- }
- }
- // 乐器支持多编码,暂不开放
- initInstrumentAndSubjectByTrack(instrumentCodeList)
- }
- /** 通过声轨反显乐器和声部 */
- const initInstrumentAndSubjectByTrack = async (tracks: string[]) => {
- // 选择一个声轨,独奏
- // 选择了多个声轨,合奏,乐器和声部自动反显,不可修改
- // if (!tracks || tracks.length <= 1) {
- // forms.musicSheetType = 'SINGLE'
- // state.subjectDisabled = false
- // state.instrumentDisabled = false
- // return
- // }
- forms.musicSheetType = !tracks || tracks.length <= 1 ? 'SINGLE' : 'CONCERT'
- state.subjectDisabled = true
- state.instrumentDisabled = true
- await initInstrumentAndSubjectByCode(tracks)
- }
- /** 获取分轨名称 */
- const getInstrumentName = (instruments: any, name = '') => {
- name = name.toLocaleLowerCase().replace(/ /g, '').replace(/\d*/gi, '')
- if (!name) return ''
- for (let key of instruments) {
- const _key = key.toLocaleLowerCase().replace(/ /g, '')
- // if (_key.includes(name)) {
- // return key
- // }
- if (_key === name) {
- return _key
- }
- }
- // for (let key of instruments) {
- // const _key = key.toLocaleLowerCase().replace(/ /g, '')
- // if (name.includes(_key)) {
- // return key
- // }
- // }
- return ''
- }
- // 通过乐器编码反显乐器和声部
- const initInstrumentAndSubjectByCode = async (codes: string[]) => {
- // forms.musicalInstrumentIdList = []
- console.log('1111')
- forms.subjectIds = []
- const codeIdMap = new Map<string, []>() as any
- const codeMapKeys: string[] = []
- state.instrumentData.forEach((data: any) => {
- if (!data.disabled) {
- const codes = data.code.split(/[,,]/)
- codes.forEach((code: string) => {
- let codeTemp = code.replaceAll(' ', '').toLowerCase()
- codeMapKeys.push(codeTemp)
- if (codeIdMap.has(codeTemp)) {
- codeIdMap.get(codeTemp).push(data.id + '')
- } else {
- const arr = [] as any
- arr.push(data.id + '')
- codeIdMap.set(codeTemp, arr)
- }
- })
- }
- })
- for (let i = 0; i < codes.length; i++) {
- let code = codes[i].replaceAll(' ', '').toLowerCase()
- const tempCode = getInstrumentName(codeMapKeys, code)
- if (codeIdMap.has(tempCode)) {
- codeIdMap.get(tempCode).forEach((c: any) => {
- const index = state.instrumentList.findIndex((item: any) => item.id.toString() === c)
- if (!forms.musicalInstrumentIdList.includes(c) && index !== -1) {
- forms.musicalInstrumentIdList.push(c)
- }
- })
- }
- }
- // 声部
- if (forms.musicalInstrumentIdList.length > 0) {
- await showBackSubject(forms.musicalInstrumentIdList)
- // changeSubject(forms.subjectIds)
- }
- }
- // 通过乐器编码返回乐器编号
- const instrumentCodeToInstrumentId = (code: string) => {
- const codeIdMap = new Map<string, []>() as any
- const codeMapKeys: string[] = []
- state.instrumentData.forEach((data: any) => {
- if (!data.disabled) {
- const codes = data.code.split(/[,,]/)
- codes.forEach((code: string) => {
- let codeTemp = code.replaceAll(' ', '').toLowerCase()
- codeMapKeys.push(codeTemp)
- if (codeIdMap.has(codeTemp)) {
- codeIdMap.get(codeTemp).push(data.id + '')
- } else {
- const arr = [] as any
- arr.push(data.id + '')
- codeIdMap.set(codeTemp, arr)
- }
- })
- }
- })
- if (!code) {
- return ''
- }
- code = code.replaceAll(' ', '').toLowerCase()
- const tempCode = getInstrumentName(codeMapKeys, code)
- if (codeIdMap.has(tempCode)) {
- const result = codeIdMap.get(tempCode)
- console.log('result:', result)
- return result[0] || ''
- }
- return ''
- }
- // 获取xml中所有轨道 乐器
- const getPartListNames = (xml: any) => {
- if (!xml) return []
- const xmlParse = new DOMParser().parseFromString(xml, 'text/xml')
- const partList: any =
- xmlParse.getElementsByTagName('part-list')?.[0]?.getElementsByTagName('score-part') || []
- let partListNames = Array.from(partList).map((item: any) => {
- let part = item.getElementsByTagName('part-name')?.[0]
- // evxml没有分轨,需要手动设置一个默认的名称,用于上传原音
- let track = ''
- // if (forms.isEvxml) {
- // // 秒极客曲目,取ID
- // let id = item.getAttribute('id')
- // if (id) {
- // track = id
- // }
- // } else {
- // 优先解析声轨,没有就取id值
- if (part && part.textContent?.trim()) {
- track = part.textContent || ''
- } else {
- let id = item.getAttribute('id')
- if (id) {
- track = id
- }
- }
- // }
- return {
- value: track.trim(),
- label: track.trim()
- }
- })
- // 处理空数据
- // if (partListNames.length === 1 && forms.details.id && !partListNames[0].value) {
- // partListNames[0] = {
- // value: forms.details.multiTracksSelection,
- // label: forms.details.multiTracksSelection
- // }
- // }
- partListNames = partListNames.filter((n: any) => n.value?.toLocaleUpperCase?.() != 'COMMON')
- // if (partListNames.length > 0) {
- // forms.musicSheetSoundList = forms.musicSheetSoundList.slice(0, partListNames.length)
- // }
- const metronomeXml = xmlParse.getElementsByTagName('metronome')?.[0]
- state.xmlFirstSpeed = metronomeXml?.getElementsByTagName('per-minute')?.[0]?.textContent || ''
- if (!forms.playSpeed) {
- if (state.xmlFirstSpeed) {
- forms.playSpeed = Number.parseFloat(state.xmlFirstSpeed)
- } else {
- // 速度默认给100
- forms.playSpeed = 100
- }
- }
- if(!forms.speedBeatUnit){
- const beatUnit = metronomeXml?.getElementsByTagName('beat-unit')?.[0]?.textContent || ''
- const beatUnitDot = metronomeXml?.getElementsByTagName('beat-unit-dot')?.[0]
- forms.speedBeatUnit = formatBeatUnit(beatUnit, !!beatUnitDot)
- }
- // console.log('xml声轨',partListNames,state.xmlFirstSpeed)
- return partListNames
- }
- // 判断选择的音轨是否在选中
- const initPartsListStatus = (track: string): any => {
- // const _names = state.partListNames.filter(
- // (n: any) => n.value?.toLocaleUpperCase?.() != 'COMMON'
- // )
- const partListNames = deepClone(state.partListNames) || []
- const multiTracksSelection = forms.multiTracksSelection
- partListNames.forEach((item: any) => {
- if (multiTracksSelection.includes(item.value)) {
- item.disabled = true
- } else {
- item.disabled = false
- }
- // const index = forms.musicSheetSoundList.findIndex(
- // (ground: any) => item.value == ground.track
- // )
- // if (index > -1 && track == item.value) {
- // item.disabled = false
- // } else {
- // item.disabled = true
- // }
- })
- return partListNames || []
- }
- // 反显声部
- const showBackSubject = async (musicalInstrumentIdList: []) => {
- if (!musicalInstrumentIdList || musicalInstrumentIdList.length == 0) {
- forms.subjectIds = []
- return
- }
- try {
- const { data } = await subjectPage({
- page: 1,
- rows: 999,
- musicalInstrumentIdList: musicalInstrumentIdList
- })
- const tempList = data.rows || []
- const tempSubject: any[] = []
- tempList.forEach((item: any) => {
- if (item.enableFlag) {
- tempSubject.push(item.id + '')
- }
- })
- forms.subjectIds = tempSubject
- } catch {}
- }
- // 添加原音
- const createSys = (initData?: any) => {
- forms.musicSheetSoundList_YY.push({
- audioFileUrl: null, // 原音
- track: null, // 轨道
- ...initData
- })
- }
- // 删除原音
- const removeSys = (index: number) => {
- dialog.warning({
- title: '提示',
- content: `是否确认删除此原音?`,
- positiveText: '确定',
- negativeText: '取消',
- onPositiveClick: async () => {
- const sound = forms.musicSheetSoundList_YY[index]
- let track = sound.track
- // if (!track) {
- // track = ''
- // }
- // if (track) {
- const selectIndex = forms.multiTracksSelection.indexOf(track)
- if (selectIndex > -1) {
- forms.multiTracksSelection.splice(selectIndex, 1)
- } else {
- forms.musicSheetSoundList_YY.splice(index, 1)
- }
- if (
- state.multiTracks == 'all' &&
- state.partListNames.length != forms.multiTracksSelection.length
- ) {
- state.multiTracks = null
- }
- }
- })
- }
- const checkMultiTracks = (value: string) => {
- if (!value) {
- return
- }
- let tempMultiTracksSelection = [] as any
- if (value === 'all') {
- state.partListNames.forEach((next: any) => {
- tempMultiTracksSelection.push(next.value)
- })
- } else if (value === 'invert') {
- state.partListNames.forEach((next: any) => {
- if (!forms.multiTracksSelection.includes(next.value)) {
- tempMultiTracksSelection.push(next.value)
- }
- })
- }
- forms.multiTracksSelection = tempMultiTracksSelection
- }
- const setOwnerName = () => {
- if (forms.sourceType == 'PLATFORM') {
- state.ownerName = ''
- return
- }
- if (!forms.sourceType || !forms.musicSheetExtend?.userId) {
- return
- }
- const appId = forms.musicSheetExtend.applicationId
- const app = state.appData.filter((next: any) => {
- return next.id == appId
- }) as any
- if (app.length > 0) {
- state.ownerName = app[0].appName
- }
- if (forms.sourceType == 'ORG') {
- state.ownerName = state.ownerName
- ? state.ownerName + '-' + forms.musicSheetExtend.organizationRole
- : forms.musicSheetExtend.organizationRole
- } else if (forms.sourceType == 'PERSON') {
- state.ownerName = state.ownerName
- ? state.ownerName +
- '-' +
- getMapValueByKey(forms.musicSheetExtend.clientType, new Map(Object.entries(clientType)))
- : getMapValueByKey(forms.musicSheetExtend.clientType, new Map(Object.entries(clientType)))
- if (forms.musicSheetExtend.userName) {
- state.ownerName = state.ownerName
- ? state.ownerName + '-' + forms.musicSheetExtend.userName
- : forms.musicSheetExtend.userName
- }
- if (forms.musicSheetExtend.phone) {
- state.ownerName += '(' + forms.musicSheetExtend.phone + ')'
- }
- }
- }
- // 声轨数据兼容
- const formatTrack = (track: string) => {
- if (!track) {
- return ''
- }
- const trim = track.trim().toUpperCase()
- // 导入后的脏数据兼容
- if (trim == 'P1' || trim == 'NULL') {
- return ''
- }
- return track.trim()
- }
- const changeSubject = async (subjectIdList: []) => {
- state.instrumentList = []
- if (!subjectIdList || subjectIdList.length == 0) {
- forms.musicalInstrumentIdList = []
- return
- }
- let enableFlag = null
- if (props.type === 'add') {
- enableFlag = true
- }
- let tempMusicalInstrumentIdList = [] as any
- const { data } = await musicalInstrumentPage({
- page: 1,
- rows: 999,
- subjectIds: subjectIdList,
- enableFlag: enableFlag
- })
- data.rows.map((item: any) => {
- tempMusicalInstrumentIdList.push(item.id + '')
- state.instrumentList.push({
- label: item.name,
- value: item.id + '',
- disabled: !item.enableFlag
- })
- })
- forms.musicalInstrumentIdList = forms.musicalInstrumentIdList.filter((item: any) => {
- return tempMusicalInstrumentIdList.includes(item)
- })
- }
- onMounted(async () => {
- state.loading = true
- if (props.type === 'preview') {
- state.previewMode = true
- }
- // 获取乐器信息
- {
- if (state.instrumentList && state.instrumentList.length > 0) {
- return
- }
- try {
- const { data } = await musicalInstrumentPage({ page: 1, rows: 999 })
- const tempList = data.rows || []
- tempList.forEach((item: any) => {
- item.label = item.name
- item.value = item.id + ''
- // item.disabled = !item.enableFlag
- state.instrumentIdNameMap.set(item.id + '', item.name)
- forms.musicSheetSoundList_YZ.push({
- musicSheetId: props.data.id,
- musicalInstrumentId: item.id + '',
- musicalInstrumentName: item.name,
- audioFileUrl: null,
- audioPlayType: 'PLAY'
- })
- })
- state.instrumentData = tempList
- state.instrumentList = deepClone(tempList)
- } catch {}
- }
- state.subjectList = deepClone(props.subjectList)
- state.subjectList.forEach((subject: any) => {
- subject.disabled = !subject.enableFlag
- })
- // 初始化应用
- {
- const appKeys = Object.keys(appKey)
- const { data } = await sysApplicationPage({
- page: 1,
- rows: 999,
- parentId: 0,
- hiddenFlag: true
- })
- const tempList = data.rows || []
- const filter = tempList.filter((next: any) => {
- return appKeys.includes(next.appKey)
- })
- filter.forEach((item: any) => {
- item.label = item.appName
- item.value = item.id
- })
- state.useProjectData = filter
- const tempFilter = tempList.filter((next: any) => {
- return appKeys.includes(next.appKey) && next.appKey !== 'KLX_JG'
- })
- tempFilter.forEach((item: any) => {
- item.label = item.appName
- item.value = item.id
- })
- state.appData = tempFilter
- }
- // 获取分类信息
- {
- try {
- const { data } = await musicSheetCategoriesQueryTree({ enable: true })
- state.musicSheetCategories = filterPointCategory(data, 'musicSheetCategoriesList')
- } catch (e) {}
- }
- if (props.type === 'edit' || props.type === 'preview') {
- const detail = props.data
- try {
- const { data } = await musicSheetDetail({ id: detail.id })
- forms.details = data
- forms.playMode = data.playMode
- forms.xmlFileUrl = data.xmlFileUrl
- forms.midiUrl = data.midiUrl
- forms.name = data.name
- // forms.musicTag = data.musicTag?.split(',')
- forms.composer = data.composer
- forms.playSpeed = data.playSpeed ? Number.parseFloat(data.playSpeed) : 100
- forms.speedBeatUnit = data.speedBeatUnit
- // forms.showFingering = Number(data.showFingering)
- // forms.canEvaluate = Number(data.canEvaluate)
- // forms.notation = Number(data.notation)
- // forms.auditVersion = Number(data.auditVersion)
- // forms.sortNumber = data.sortNumber
- forms.defaultScoreRender = data.defaultScoreRender
- forms.isScoreRender = data.isScoreRender
- forms.musicCover = data.musicCover
- forms.remark = data.remark
- forms.status = data.status
- // forms.musicSheetType = data.musicSheetType || 'SINGLE'
- forms.sourceType = data.sourceType
- forms.appAuditFlag = data.appAuditFlag ? 1 : 0
- forms.midiFileUrl = data.midiFileUrl
- forms.isShowFingering = data.isShowFingering
- forms.isMixBeat = data.isMixBeat
- forms.musicFirstImg = data.musicFirstImg
- forms.musicJianImg = data.musicJianImg
- forms.musicImg = data.musicImg
- forms.musicPdfUrl = data.musicPdfUrl
- forms.firstPdfUrl = data.firstPdfUrl
- forms.jianPdfUrl = data.jianPdfUrl
- forms.isAllSubject = data.isAllSubject
- forms.isUseSingSystemBeat = data.isUseSingSystemBeat
- forms.isPlaySingBeat = data.isPlaySingBeat
- forms.subjectIds = []
- if (data.subjectIds) {
- const subjectIds = data.subjectIds.split(',') || []
- console.log(subjectIds, 'subjectIds', forms.subjectIds)
- subjectIds.forEach((subjectId: any) => {
- if (!forms.subjectIds.includes(subjectId)) {
- forms.subjectIds.push(subjectId)
- }
- })
- state.subjectList = state.subjectList.filter((subject: any) => {
- return !subject.disabled || subjectIds.includes(subject.value)
- })
- }
- forms.musicCategoryId = data.musicCategoryId
- forms.audioType = data.audioType
- forms.isPlayBeat = data.isPlayBeat
- forms.isUseSystemBeat = data.isUseSystemBeat
- // 获取渐变 和 是否多声部
- try {
- const extConfigJson = data.extConfigJson ? JSON.parse(data.extConfigJson) : {}
- forms.graduals = extConfigJson.gradualTimes || {}
- forms.repeatedBeats = !!extConfigJson.repeatedBeats
- forms.isEvxml = !!extConfigJson.isEvxml
- forms.repeatedBeatsToSing = !!extConfigJson.repeatedBeatsToSing
- } catch (error) {}
- forms.evaluationStandard = data.evaluationStandard
- forms.musicSheetExtend = data.musicSheetExtend
- state.musicSheetSoundList = data.musicSheetSoundList ? data.musicSheetSoundList : []
- let musicSheetAccompanimentList = data.musicSheetAccompanimentList
- ? data.musicSheetAccompanimentList
- : []
- musicSheetAccompanimentList.forEach((next: any) => {
- let audioPlayType = next.audioPlayType
- if (audioPlayType && audioPlayType == 'SING') {
- state.bSongFile = next.audioFileUrl
- forms.scoreAudioFileUrl = next.scoreAudioFileUrl
- } else {
- state.musicSheetAccompanimentUrl = next.audioFileUrl
- }
- })
- // 初始化演奏
- for (let i = 0; i < state.musicSheetSoundList.length; i++) {
- if (
- state.musicSheetSoundList[i].audioPlayType == 'SING' &&
- state.musicSheetSoundList[i].track != null
- ) {
- // 范唱 唱名
- state.initFSongMap.set(state.musicSheetSoundList[i].track, {
- ...state.musicSheetSoundList[i]
- // musicalInstrumentName: state.instrumentIdNameMap.get(state.musicSheetSoundList[i].musicalInstrumentId),
- })
- } else {
- if (forms.isAllSubject) {
- forms.musicSheetSoundList_all_subject = state.musicSheetSoundList[i].audioFileUrl
- } else {
- // 乐器演奏原音
- for (let j = 0; j < forms.musicSheetSoundList_YZ.length; j++) {
- let musicalInstrumentId = state.musicSheetSoundList[i].musicalInstrumentId
- if (
- musicalInstrumentId &&
- musicalInstrumentId == forms.musicSheetSoundList_YZ[j].musicalInstrumentId
- ) {
- forms.musicSheetSoundList_YZ[j].audioFileUrl =
- state.musicSheetSoundList[i].audioFileUrl
- }
- }
- }
- }
- }
- forms.musicalInstrumentIdList = data.musicalInstrumentIds
- ? data.musicalInstrumentIds.split(',')
- : []
- // 乐器下拉格式化,停用的过滤
- state.instrumentList = state.instrumentList.filter((next: any) => {
- return next.enableFlag || forms.musicalInstrumentIdList.includes(next.id + '')
- })
- setOwnerName()
- axios.get(data.xmlFileUrl).then((res: any) => {
- if (res?.data) {
- state.musicUpdateLoading = true
- gradualData.list = getGradualLengthByXml(res?.data as any).filter(
- (item: any) => item.length === 2
- )
- state.partListNames = getPartListNames(res?.data as any) as any
- // 初始化音轨和原音
- let multiTracksSelection = [] as any
- if (data.multiTracksSelection) {
- data.multiTracksSelection = data.multiTracksSelection.toLocaleUpperCase()
- }
- if (
- !data.multiTracksSelection ||
- data.multiTracksSelection.trim() == '' ||
- data.multiTracksSelection.trim() == 'NULL'
- ) {
- multiTracksSelection.push('')
- } else {
- data.multiTracksSelection.split(',').forEach((next: any) => {
- multiTracksSelection.push(next.trim())
- })
- }
- let names = state.partListNames.map((next: any) => next.label)
- multiTracksSelection = names.filter((next: any) =>
- multiTracksSelection.includes(next.toLocaleUpperCase())
- )
- forms.multiTracksSelection = multiTracksSelection
- // 根据声轨数量判断独奏合奏
- forms.musicSheetType = forms.multiTracksSelection.length > 1 ? 'CONCERT' : 'SINGLE'
- const existSoundList = data.musicSheetSoundList ? data.musicSheetSoundList : []
- // 如果只有一个原音文件,并且原音没有对应声轨,取xml解析中的第一个声轨绑定当当前原音
- // if (existSoundList.length === 1 && !formatTrack(existSoundList[0].track)) {
- // let track = state.partListNames.length > 0 ? state.partListNames[0].value : null;
- // forms.musicSheetSoundList_YY.push({
- // audioFileUrl: existSoundList[0].audioFileUrl, // 原音
- // musicalInstrumentId: existSoundList[0].musicalInstrumentId,
- // track: track, // 轨道
- // audioPlayType: 'PLAY'
- // })
- // if (track && !forms.multiTracksSelection.includes(track)) {
- // forms.multiTracksSelection.push(track)
- // }
- // } else {
- const tracks = [] as any
- state.partListNames.forEach((item: any) => {
- let audioFileUrl = null
- let musicalInstrumentId = null
- let musicPdfUrl = null
- let firstPdfUrl = null
- let jianPdfUrl = null
- if (forms.musicSheetType == 'CONCERT') {
- existSoundList.forEach((next: any) => {
- if (next.audioPlayType == 'PLAY') {
- let track = ''
- if (next.track) {
- track = next.track.trim()
- }
- if (track == item.value) {
- audioFileUrl = next.audioFileUrl
- musicalInstrumentId = next.musicalInstrumentId
- musicPdfUrl = next.musicPdfUrl
- firstPdfUrl = next.firstPdfUrl
- jianPdfUrl = next.jianPdfUrl
- }
- }
- })
- }
- forms.musicSheetSoundList_YY.push({
- audioFileUrl: audioFileUrl, // 原音
- musicPdfUrl, // 五线谱pdf
- firstPdfUrl,// 首调pdf
- jianPdfUrl,// 固定调pdf
- musicalInstrumentId: musicalInstrumentId, // 乐器
- track: item.value, // 轨道
- audioPlayType: 'PLAY'
- })
- tracks.push(item.value)
- })
- if (tracks.length == forms.multiTracksSelection.length) {
- state.multiTracks = 'all'
- }
- // 处理没有声轨,但有原音
- if (forms.musicSheetType == 'CONCERT') {
- state.musicSheetSoundList.forEach((next: any) => {
- if (next.audioPlayType == 'PLAY') {
- if (
- next.track &&
- !tracks.includes(next.track.trim()) &&
- next.audioPlayType == 'PLAY'
- ) {
- forms.musicSheetSoundList_YY.push({
- audioFileUrl: next.audioFileUrl, // 原音
- musicalInstrumentId: next.musicalInstrumentId,
- track: next.track ? next.track.trim() : '', // 轨道
- audioPlayType: 'PLAY'
- })
- }
- }
- })
- // }
- }
- initFSongList()
- // state.musicUpdateLoading = false
- }
- })
- } catch (error) {}
- } else {
- // 新增只能使用启用状态的数据
- state.subjectList = state.subjectList.filter((next: any) => {
- return next.enableFlag == true
- })
- state.instrumentList = state.instrumentList.filter((next: any) => {
- return next.enableFlag == true
- })
- }
- state.loading = false
- })
- const beatSymbolOpt = [
- {
- label: '',
- labelHide: '1',
- value: '1/1',
- class: 'beatSymbolOptItem'
- },
- {
- label: '',
- labelHide: '2',
- value: '1/2',
- class: 'beatSymbolOptItem'
- },
- {
- label: '',
- labelHide: '3',
- value: '1/4',
- class: 'beatSymbolOptItem'
- },
- {
- label: '',
- labelHide: '4',
- value: '1/8',
- class: 'beatSymbolOptItem'
- },
- {
- label: '',
- labelHide: '5',
- value: '1/16',
- class: 'beatSymbolOptItem'
- },
- {
- label: '',
- labelHide: '6',
- value: '1/2.',
- class: 'beatSymbolOptItem'
- },
- {
- label: '',
- labelHide: '7',
- value: '1/4.',
- class: 'beatSymbolOptItem'
- },
- {
- label: '',
- labelHide: '8',
- value: '1/8.',
- class: 'beatSymbolOptItem'
- }
- ];
- return () => (
- <div style="background: #fff; padding-top: 12px">
- <NSpin show={state.loading}>
- <NForm
- class={styles.formContainer}
- model={forms}
- ref={formsRef}
- label-placement="left"
- label-width="150"
- disabled={state.previewMode}
- >
- <NAlert showIcon={false} style={{ marginBottom: '12px' }}>
- 基本信息
- </NAlert>
- <NGrid cols={2}>
- <NFormItemGi
- label="曲目名称"
- path="name"
- rule={[
- {
- required: true,
- message: '请输入曲目名称',
- trigger: ['input', 'blur']
- }
- ]}
- >
- <NInput
- v-model:value={forms.name}
- placeholder="请输入曲目名称"
- maxlength={50}
- showCount
- />
- </NFormItemGi>
- <NFormItemGi
- label="音乐人"
- path="composer"
- rule={[
- {
- required: false,
- message: '请输入音乐人',
- trigger: ['input', 'blur']
- }
- ]}
- >
- <NInput
- v-model:value={forms.composer}
- placeholder="请输入音乐人名称"
- showCount
- maxlength={14}
- />
- </NFormItemGi>
- </NGrid>
- <NGrid cols={2}>
- <NFormItemGi
- label="曲目封面"
- path="musicCover"
- rule={[
- {
- required: false,
- message: '请上传曲目封面',
- trigger: ['input', 'blur']
- }
- ]}
- >
- <UploadFile
- desc={'封面图'}
- disabled={state.previewMode}
- accept=".jpg,.jpeg,.png"
- tips="请上传大小1M以内的JPG、PNG图片"
- size={1}
- v-model:fileList={forms.musicCover}
- cropper
- bucketName="cbs"
- options={{
- autoCrop: true, //是否默认生成截图框
- enlarge: 2, // 图片放大倍数
- autoCropWidth: 200, //默框高度
- fixedBox: true, //是否固定截图框大认生成截图框宽度
- autoCropHeight: 200, //默认生成截图小 不允许改变
- previewsCircle: false, //预览图是否是原圆形
- title: '曲目封面'
- }}
- />
- </NFormItemGi>
- <NFormItemGi
- label="曲目分类"
- path="musicCategoryId"
- rule={[
- {
- required: true,
- message: '请选择曲目分类',
- trigger: ['change']
- }
- ]}
- >
- <NCascader
- valueField="id"
- labelField="name"
- children-field="musicSheetCategoriesList"
- placeholder="请选择分类"
- v-model:value={forms.musicCategoryId}
- options={state.musicSheetCategories}
- clearable
- />
- </NFormItemGi>
- </NGrid>
- <NGrid cols={2}>
- <NFormItemGi
- label="作者属性"
- path="sourceType"
- rule={[
- {
- required: true,
- message: '请选择作者属性',
- trigger: 'change'
- }
- ]}
- >
- <NSelect
- v-model:value={forms.sourceType}
- options={getSelectDataFromObj(musicSheetSourceType)}
- placeholder="请选择作者属性"
- onUpdateValue={() => {
- // 发送变化,清理选择的所属人信息
- forms.musicSheetExtend = {}
- state.ownerName = null
- // forms.musicSheetExtend.userId = null
- // forms.musicSheetExtend.userName = null
- // forms.musicSheetExtend.applicationId = null
- // forms.musicSheetExtend.organizationRoleId = null
- }}
- />
- </NFormItemGi>
- {forms.sourceType === 'PERSON' && (
- <NFormItemGi
- label="所属人"
- path="musicSheetExtend.userId"
- rule={[
- {
- required: true,
- message: '请选择曲目所属人',
- trigger: ['input', 'change']
- }
- ]}
- >
- <NButton
- disabled={state.previewMode || !forms.sourceType}
- type="primary"
- size="small"
- text
- //v-auth="orchestraSubsidyStandard/update1597887579789053953"
- onClick={() => {
- state.showMusicSheetOwnerDialog = true
- }}
- >
- {state.ownerName ? state.ownerName : '请选择所属人'}
- </NButton>
- </NFormItemGi>
- )}
- {forms.sourceType === 'ORG' && (
- <NFormItemGi
- label="所属人"
- path="musicSheetExtend.organizationRoleId"
- rule={[
- {
- required: true,
- message: '请选择曲目所属机构',
- trigger: ['input', 'change']
- }
- ]}
- >
- <NButton
- disabled={state.previewMode || !forms.sourceType}
- type="primary"
- size="small"
- text
- //v-auth="orchestraSubsidyStandard/update1597887579789053953"
- onClick={() => {
- state.showMusicSheetOwnerDialog = true
- }}
- >
- {state.ownerName ? state.ownerName : '请选择所属机构'}
- </NButton>
- </NFormItemGi>
- )}
- </NGrid>
- <NGrid cols={2}>
- <NFormItemGi
- label="审核版本"
- path="appAuditFlag"
- rule={[
- {
- required: true,
- message: '请选择审核版本',
- trigger: 'change',
- type: 'number'
- }
- ]}
- >
- <NSelect
- options={
- [
- {
- label: '是',
- value: 1
- },
- {
- label: '否',
- value: 0
- }
- ] as any
- }
- v-model:value={forms.appAuditFlag}
- />
- </NFormItemGi>
- </NGrid>
- <NAlert showIcon={false} style={{ marginBottom: '12px' }}>
- 曲目设置
- </NAlert>
- <NGrid cols={2}>
- <NFormItemGi
- label="播放模式"
- path="playMode"
- rule={[
- {
- required: true,
- message: '请选择播放模式'
- }
- ]}
- >
- <NRadioGroup
- v-model:value={forms.playMode}
- onUpdateValue={(value: string | number | boolean) => {
- if (value === 'MP3') {
- forms.playMode = 'MP3'
- } else {
- forms.playMode = 'MIDI'
- }
- }}
- >
- <NRadio value="MP3">MP3</NRadio>
- {forms.playMode == 'MIDI' && props.type === 'preview' && (
- <NRadio value="MIDI">MID</NRadio>
- )}
- </NRadioGroup>
- </NFormItemGi>
- {forms.playMode === 'MP3' && (
- <NFormItemGi
- label="伴奏类型"
- path="audioType"
- rule={[
- {
- required: true,
- message: '请选择伴奏类型'
- }
- ]}
- >
- <NRadioGroup v-model:value={forms.audioType}>
- <NRadio value={'HOMEMODE'}>自制伴奏</NRadio>
- <NRadio value={'COMMON'}>普通伴奏</NRadio>
- </NRadioGroup>
- </NFormItemGi>
- )}
- </NGrid>
- <NGrid cols={2}>
- <NFormItemGi
- label="上传XML"
- path="xmlFileUrl"
- rule={[
- {
- required: true,
- message: '请选择上传XML',
- trigger: ['change', 'input']
- }
- ]}
- >
- <UploadFile
- desc={'XML文件'}
- disabled={state.previewMode}
- size={30}
- key={'xmlFileUrl'}
- v-model:fileList={forms.xmlFileUrl}
- tips="仅支持上传.xml/.mxml格式文件"
- listType="image"
- accept=".xml,.mxml,.evxml"
- bucketName="cloud-coach"
- text="点击上传XML文件"
- onReadFileInputEventAsArrayBuffer={readFileInputEventAsArrayBuffer}
- onRemove={() => {
- // forms.multiTracksSelection = []
- // state.partListNames = []
- // forms.musicSheetSoundList_YY = []
- // forms.musicalInstrumentIdList = []
- // forms.subjectIds = []
- }}
- />
- </NFormItemGi>
- <NFormItemGi
- label="总谱五线谱PDF"
- path="musicPdfUrl"
- rule={[
- {
- required: false,
- message: '请选择总谱五线谱PDF',
- trigger: ['change', 'input']
- }
- ]}
- >
- <UploadFile
- desc={'总谱五线谱PDF'}
- disabled={state.previewMode}
- size={30}
- max={1}
- v-model:fileList={forms.musicPdfUrl}
- tips="仅支持上传.pdf格式文件"
- listType="image"
- accept=".pdf"
- bucketName="cloud-coach"
- text="点击上传PDF"
- />
- </NFormItemGi>
- <NFormItemGi
- label="总谱首调PDF"
- path="firstPdfUrl"
- rule={[
- {
- required: false,
- message: '请选择总谱首调PDF',
- trigger: ['change', 'input']
- }
- ]}
- >
- <UploadFile
- desc={'总谱首调PDF'}
- disabled={state.previewMode}
- size={30}
- max={1}
- v-model:fileList={forms.firstPdfUrl}
- tips="仅支持上传.pdf格式文件"
- listType="image"
- accept=".pdf"
- bucketName="cloud-coach"
- text="点击上传PDF"
- />
- </NFormItemGi>
- <NFormItemGi
- label="总谱固定PDF"
- path="jianPdfUrl"
- rule={[
- {
- required: false,
- message: '请选择总谱固定PDF',
- trigger: ['change', 'input']
- }
- ]}
- >
- <UploadFile
- desc={'总谱固定PDF'}
- disabled={state.previewMode}
- size={30}
- max={1}
- v-model:fileList={forms.jianPdfUrl}
- tips="仅支持上传.pdf格式文件"
- listType="image"
- accept=".pdf"
- bucketName="cloud-coach"
- text="点击上传PDF"
- />
- </NFormItemGi>
- <NFormItemGi
- label="评分标准"
- path="evaluationStandard"
- rule={[
- {
- required: true
- }
- ]}
- >
- <NRadioGroup v-model:value={forms.evaluationStandard}>
- <NRadio value={'FREQUENCY'}>标准评测</NRadio>
- <NRadio value={'AMPLITUDE'}>打击乐(振幅)</NRadio>
- <NRadio value={'DECIBELS'}>节奏(分贝)</NRadio>
- </NRadioGroup>
- </NFormItemGi>
- </NGrid>
- <NGrid cols={2}>
- {/*<NFormItemGi*/}
- {/* label="谱面渲染"*/}
- {/* path="musicSheetType"*/}
- {/* rule={[*/}
- {/* {*/}
- {/* required: true,*/}
- {/* message: '请选择谱面渲染',*/}
- {/* trigger: 'change'*/}
- {/* }*/}
- {/* ]}*/}
- {/*>*/}
- {/* <NRadioGroup v-model:value={forms.musicSheetType}>*/}
- {/* <NRadio value={'SINGLE'}>多声轨</NRadio>*/}
- {/* <NRadio value={'CONCERT'}>单声轨</NRadio>*/}
- {/* </NRadioGroup>*/}
- {/*</NFormItemGi>*/}
- <NFormItemGi
- label="是否全声部"
- path="isAllSubject"
- rule={[
- {
- required: true,
- message: '是否全声部'
- }
- ]}
- >
- <NRadioGroup v-model:value={forms.isAllSubject}>
- <NRadio value={false}>否</NRadio>
- <NRadio value={true}>是</NRadio>
- </NRadioGroup>
- </NFormItemGi>
- <NFormItemGi
- label="速度"
- path="playSpeed"
- rule={[
- {
- required: false,
- message: '请输入速度'
- }
- ]}
- >
- <NSelect
- class={styles.beatSymbolSel}
- v-model:value={forms.speedBeatUnit}
- options={beatSymbolOpt}
- show-checkmark={false}
- show-arrow={false}
- placement={'top'}
- render-tag={
- ({ option }:any) => {
- return h('div', { class: `beatSymbolImg${option.labelHide} beatSymbolImg` });
- }
- }
- render-label={
- (option:any) => {
- return h('div', { class: `beatSymbolImg${option.labelHide} beatSymbolImg` });
- }
- }
- ></NSelect>
- <NInputNumber
- placeholder="请输入速度"
- v-model:value={forms.playSpeed}
- min={0}
- style="width:100%"
- />
- </NFormItemGi>
- </NGrid>
- {!forms.isAllSubject && (
- <NGrid cols={2}>
- <NFormItemGi
- label="可用乐器"
- path="musicalInstrumentIdList"
- rule={[
- {
- required: true,
- message: '请选择可用乐器',
- trigger: 'change',
- type: 'array'
- }
- ]}
- >
- <NSelect
- placeholder="请选择可用乐器"
- options={state.instrumentList}
- v-model:value={forms.musicalInstrumentIdList}
- // disabled = {state.instrumentDisabled}
- clearable
- multiple
- filterable
- maxTagCount={10}
- onUpdateValue={async (value: any) => {
- await showBackSubject(value)
- }}
- />
- </NFormItemGi>
- <NFormItemGi
- label="可用声部"
- path="subjectIds"
- rule={[
- {
- required: true,
- message: '请选择可用声部',
- trigger: 'change',
- type: 'array'
- }
- ]}
- >
- <NSelect
- v-model:value={forms.subjectIds}
- options={state.subjectList}
- // disabled={true}
- multiple
- filterable
- clearable
- placeholder="请选择可用声部"
- maxTagCount={10}
- onUpdateValue={async (val: any) => {
- // await changeSubject(val)
- }}
- />
- </NFormItemGi>
- </NGrid>
- )}
- <NGrid cols={1}>
- <NFormItemGi
- label="是否生成节拍器"
- path="isMixBeat"
- rule={[
- {
- required: true,
- message: '请选择是否生成节拍器'
- }
- ]}
- >
- <NRadioGroup v-model:value={forms.isMixBeat} onUpdate:value={()=>{ state.isBeatTime = true }}>
- <NRadio value={true}>是</NRadio>
- <NRadio value={false}>否</NRadio>
- </NRadioGroup>
- </NFormItemGi>
- </NGrid>
-
- <NGrid cols={1}>
- <NFormItemGi
- label={'切换声轨'}
- path="multiTracksSelection"
- rule={[
- {
- required: true,
- message: `请选择切换声轨`,
- trigger: 'change',
- type: 'array'
- }
- ]}
- >
- <NGrid style="padding-top: 4px;">
- <NGi span={24}>
- <NRadioGroup
- v-model:value={state.multiTracks}
- onUpdateValue={(value) => {
- checkMultiTracks(value)
- }}
- >
- <NRadio value={'all'}>全选</NRadio>
- <NRadio value={'allUncheck'}>重置</NRadio>
- <NRadio value={'invert'}>反选</NRadio>
- </NRadioGroup>
- </NGi>
- {state.partListNames && state.partListNames.length > 0 && (
- <NGi span={24} style={'margin-top:5px'}>
- <NFormItemGi
- label=""
- path="multiTracksSelection"
- rule={[
- {
- required: false
- }
- ]}
- >
- <NCheckboxGroup
- v-model:value={forms.multiTracksSelection}
- onUpdateValue={(val: any) => {
- if (state.partListNames.length != val.length) {
- state.multiTracks = null
- } else {
- state.multiTracks = 'all'
- }
- }}
- >
- <NGrid yGap={2} cols={4}>
- {state.partListNames.map((item: any) => (
- <NGi>
- <NCheckbox value={item.value} label={item.label} />
- </NGi>
- ))}
- </NGrid>
- </NCheckboxGroup>
- </NFormItemGi>
- </NGi>
- )}
- </NGrid>
- </NFormItemGi>
- </NGrid>
- {forms.multiTracksSelection.length > 1 && (
- <NGrid cols={2}>
- <NFormItemGi
- label="总谱渲染"
- path="isScoreRender"
- rule={[
- {
- required: true,
- message: '请选择总谱渲染'
- }
- ]}
- >
- <NRadioGroup v-model:value={forms.isScoreRender}>
- <NRadio value={true}>支持</NRadio>
- <NRadio value={false}>不支持</NRadio>
- </NRadioGroup>
- </NFormItemGi>
- {/* 支持总谱渲染的时候才显示 */}
- {forms.isScoreRender && (
- <NFormItemGi
- label="默认显示"
- path="defaultScoreRender"
- rule={[
- {
- required: false
- }
- ]}
- >
- <NRadioGroup v-model:value={forms.defaultScoreRender}>
- <NRadio value={true}>总谱</NRadio>
- <NRadio value={false}>分轨</NRadio>
- </NRadioGroup>
- </NFormItemGi>
- )}
- </NGrid>
- )}
- <NAlert showIcon={false} style={{ marginBottom: '12px' }}>
- 演奏文件
- </NAlert>
- <NGrid cols={2}>
- <NFormItemGi
- label="是否播放预备拍"
- path="isPlayBeat"
- rule={[
- {
- required: true,
- message: '请选择是否播放预备拍'
- }
- ]}
- >
- <NRadioGroup v-model:value={forms.isPlayBeat}>
- <NRadio value={true}>是</NRadio>
- <NRadio value={false}>否</NRadio>
- </NRadioGroup>
- </NFormItemGi>
- {forms.isPlayBeat && (
- <NFormItemGi
- label="播放方式"
- path="isUseSystemBeat"
- rule={[
- {
- required: true,
- message: '请选择播放方式'
- }
- ]}
- >
- <NRadioGroup v-model:value={forms.isUseSystemBeat}>
- <NRadio value={true}>系统预备拍</NRadio>
- <NRadio value={false}>MP3预备拍</NRadio>
- </NRadioGroup>
- </NFormItemGi>
- )}
- </NGrid>
- <NGrid cols={2}>
- <NFormItemGi
- label="重复节拍时长"
- path="repeatedBeats"
- rule={[
- {
- required: false,
- message: '请选择是否重复节拍时长'
- }
- ]}
- >
- <NRadioGroup v-model:value={forms.repeatedBeats}>
- <NRadio value={true}>是</NRadio>
- <NRadio value={false}>否</NRadio>
- </NRadioGroup>
- </NFormItemGi>
- <NFormItemGi
- label="是否显示指法"
- path="isShowFingering"
- rule={[
- {
- required: true,
- message: '请选择是否显示指法'
- }
- ]}
- >
- <NRadioGroup v-model:value={forms.isShowFingering}>
- <NRadio value={true}>是</NRadio>
- <NRadio value={false}>否</NRadio>
- </NRadioGroup>
- </NFormItemGi>
- </NGrid>
- <NGrid cols={2}>
- {forms.playMode === 'MP3' && (
- <NFormItemGi
- label="上传伴奏"
- path="musicSheetAccompanimentList"
- rule={[
- {
- required: false,
- message: '请选择上传.mp3'
- }
- ]}
- >
- <UploadFile
- disabled={state.previewMode}
- size={30}
- v-model:fileList={state.musicSheetAccompanimentUrl}
- onUpdate:fileList={() => {
- state.isBeatTime = true
- }}
- tips="仅支持上传.mp3格式文件"
- listType="image"
- accept=".mp3"
- bucketName="cloud-coach"
- text="点击上传伴奏文件"
- max={1}
- desc={'上传伴奏文件'}
- // onReadFileInputEventAsArrayBuffer={readFileInputEventAsArrayBuffer}
- />
- </NFormItemGi>
- )}
- {forms.isAllSubject && forms.musicSheetType == 'SINGLE' && (
- <NFormItemGi
- label="上传原音"
- path="musicSheetSoundList_all_subject"
- rule={[
- {
- required: false,
- message: '请选择上传原音',
- trigger: ['change', 'input']
- }
- ]}
- >
- <UploadFile
- desc={'上传原音'}
- disabled={state.previewMode}
- size={30}
- max={1}
- v-model:fileList={forms.musicSheetSoundList_all_subject}
- onUpdate:fileList={() => {
- state.isBeatTime = true
- }}
- tips="仅支持上传.mp3格式文件"
- listType="image"
- accept=".mp3"
- bucketName="cloud-coach"
- text="点击上传原音"
- onRemove={() => {}}
- />
- </NFormItemGi>
- )}
- </NGrid>
- {/*渐变速*/}
- {!!gradualData.list.length && (
- <>
- <NAlert showIcon={false} type="info">
- 识别到共1处渐变速度,请输入Dorico对应小节时间信息
- </NAlert>
- <NFormItem label="rit." required style={{ marginTop: '10px' }}>
- <NSpace vertical>
- {gradualData.list.map((n: any, ni: number) => (
- <NInputGroup>
- <NFormItem
- path={`graduals.${n[0].measureIndex}`}
- rule={[
- { required: true, message: '请输入合奏曲目时间' },
- {
- pattern: /^((\d{2}):?){2,3}$/,
- message: '请输入正确的曲目时间',
- trigger: 'blur'
- }
- ]}
- >
- <NInputGroup>
- <NInputGroupLabel>{n[0].measureIndex + 1}小节开始</NInputGroupLabel>
- <NInput
- placeholder="00:00:00"
- v-model:value={forms.graduals[n[0].measureIndex]}
- ></NInput>
- </NInputGroup>
- </NFormItem>
- <div style={{ lineHeight: '30px', padding: '0 4px' }}>~</div>
- <NFormItem
- path={`graduals.${n[1].measureIndex}`}
- rule={[
- { required: true, message: '请输入合奏曲目时间' },
- {
- pattern: /^((\d{2}):?){2,3}$/,
- message: '请输入正确的曲目时间',
- trigger: 'blur'
- }
- ]}
- >
- <NInputGroup>
- <NInput
- placeholder="00:00:00"
- v-model:value={forms.graduals[n[1].measureIndex]}
- ></NInput>
- <NInputGroupLabel>{n[1].measureIndex}小节结束</NInputGroupLabel>
- </NInputGroup>
- </NFormItem>
- </NInputGroup>
- ))}
- </NSpace>
- </NFormItem>
- </>
- )}
- {/*独奏*/}
- {forms.musicSheetType == 'SINGLE' &&
- forms.playMode === 'MP3' &&
- !forms.isAllSubject &&
- forms.musicSheetSoundList_YZ.map((item: any, index: any) => {
- return (
- <>
- {forms.musicalInstrumentIdList.includes(item.musicalInstrumentId) && (
- <NGrid class={styles.audioSection}>
- <NFormItemGi
- span={12}
- label={item.musicalInstrumentName}
- path={`musicSheetSoundList_YZ[${index}].audioFileUrl`}
- rule={[
- {
- required: false,
- message: `请上传乐器演奏文件`
- }
- ]}
- >
- <UploadFile
- desc={'乐器演奏文件'}
- disabled={state.previewMode}
- size={100}
- v-model:fileList={item.audioFileUrl}
- onUpdate:fileList={() => {
- state.isBeatTime = true
- }}
- tips="仅支持上传.mp3格式文件"
- listType="image"
- accept=".mp3"
- text={'点击上传MP3文件'}
- bucketName="cloud-coach"
- />
- </NFormItemGi>
- </NGrid>
- )}
- </>
- )
- })}
- {/*合奏*/}
- {forms.musicSheetType == 'CONCERT' &&
- forms.playMode === 'MP3' &&
- forms.musicSheetSoundList_YY.length > 0 && (
- <>
- {forms.musicSheetSoundList_YY.map((item: any, index: number) => {
- return (
- <>
- {(!containOther(item.track) ||
- (item.track?.toLocaleUpperCase?.() != 'COMMON' &&
- forms.multiTracksSelection.includes(item.track))) && (
- <NGrid
- class={styles.audioSection}
- // v-show={forms.multiTracksSelection.indexOf(item.track) > -1}
- >
- <NFormItemGi
- span={12}
- label="原音"
- path={`musicSheetSoundList_YY[${index}].audioFileUrl`}
- rule={[
- {
- // required: forms.multiTracksSelection.indexOf(forms.musicSheetSoundList_YY[index].audioFileUrl) > -1,
- required: false,
- message: `请上传${
- item.track ? item.track + '的' : '第' + (index + 1) + '个'
- }原音`
- }
- ]}
- >
- <UploadFile
- desc={'原音文件'}
- disabled={state.previewMode}
- size={100}
- v-model:fileList={item.audioFileUrl}
- onUpdate:fileList={() => {
- state.isBeatTime = true
- }}
- tips="仅支持上传.mp3格式文件"
- listType="image"
- accept=".mp3"
- bucketName="cloud-coach"
- />
- </NFormItemGi>
- {state.partListNames.length > 0 && (
- <NFormItemGi
- span={12}
- label="所属轨道"
- path={`musicSheetSoundList_YY[${index}].track`}
- rule={[
- {
- required: false,
- message: '请选择所属轨道'
- }
- ]}
- >
- <NSelect
- placeholder="请选择所属轨道"
- value={item.track}
- options={initPartsListStatus(item.track)}
- onUpdateValue={(value: any) => {
- const track = item.track
- if (track) {
- // 声轨交换
- forms.musicSheetSoundList_YY.forEach((next: any) => {
- if (next.track == value) {
- next.track = track
- }
- })
- const index = forms.multiTracksSelection.indexOf(item.track)
- forms.multiTracksSelection.splice(index, 1)
- } else {
- forms.musicSheetSoundList_YY =
- forms.musicSheetSoundList_YY.filter((next: any) => {
- return next.track != value
- })
- }
- if (
- value != null &&
- !forms.multiTracksSelection.includes(value)
- ) {
- forms.multiTracksSelection.push(value)
- }
- item.track = value
- if (
- state.partListNames.length ==
- forms.multiTracksSelection.length
- ) {
- state.multiTracks = 'all'
- }
- }}
- />
- </NFormItemGi>
- )}
- <NFormItemGi
- span={12}
- label="五线谱PDF"
- path={`musicSheetSoundList_YY[${index}].musicPdfUrl`}
- rule={[
- {
- required: false,
- message: '请选择五线谱PDF',
- trigger: ['change', 'input']
- }
- ]}
- >
- <UploadFile
- desc={'五线谱PDF'}
- disabled={state.previewMode}
- size={30}
- max={1}
- v-model:fileList={item.musicPdfUrl}
- tips="仅支持上传.pdf格式文件"
- listType="image"
- accept=".pdf"
- bucketName="cloud-coach"
- text="点击上传PDF"
- />
- </NFormItemGi>
- <NFormItemGi
- span={12}
- label="首调PDF"
- path={`musicSheetSoundList_YY[${index}].firstPdfUrl`}
- rule={[
- {
- required: false,
- message: '请选择首调PDF',
- trigger: ['change', 'input']
- }
- ]}
- >
- <UploadFile
- desc={'首调PDF'}
- disabled={state.previewMode}
- size={30}
- max={1}
- v-model:fileList={item.firstPdfUrl}
- tips="仅支持上传.pdf格式文件"
- listType="image"
- accept=".pdf"
- bucketName="cloud-coach"
- text="点击上传PDF"
- />
- </NFormItemGi>
- <NFormItemGi
- span={12}
- label="固定PDF"
- path={`musicSheetSoundList_YY[${index}].jianPdfUrl`}
- rule={[
- {
- required: false,
- message: '请选择固定PDF',
- trigger: ['change', 'input']
- }
- ]}
- >
- <UploadFile
- desc={'固定PDF'}
- disabled={state.previewMode}
- size={30}
- max={1}
- v-model:fileList={item.jianPdfUrl}
- tips="仅支持上传.pdf格式文件"
- listType="image"
- accept=".pdf"
- bucketName="cloud-coach"
- text="点击上传PDF"
- />
- </NFormItemGi>
- <NGi class={styles.btnRemove}>
- <NButton
- type="primary"
- text
- // disabled={forms.musicSheetSoundList_YY.length === 1}
- onClick={() => removeSys(index)}
- >
- 删除
- </NButton>
- </NGi>
- </NGrid>
- )}
- </>
- )
- })}
- </>
- )}
- <NAlert showIcon={false} style={{ marginBottom: '12px' }}>
- 演唱文件
- </NAlert>
- <NGrid cols={2}>
- <NFormItemGi
- label="是否播放预备拍"
- path="isPlaySingBeat"
- rule={[
- {
- required: true,
- message: '请选择是否播放预备拍'
- }
- ]}
- >
- <NRadioGroup v-model:value={forms.isPlaySingBeat}>
- <NRadio value={true}>是</NRadio>
- <NRadio value={false}>否</NRadio>
- </NRadioGroup>
- </NFormItemGi>
- {forms.isPlaySingBeat && (
- <NFormItemGi
- label="播放方式"
- path="isUseSingSystemBeat"
- rule={[
- {
- required: true,
- message: '请选择播放方式'
- }
- ]}
- >
- <NRadioGroup v-model:value={forms.isUseSingSystemBeat}>
- <NRadio value={true}>系统预备拍</NRadio>
- <NRadio value={false}>MP3预备拍</NRadio>
- </NRadioGroup>
- </NFormItemGi>
- )}
- </NGrid>
- <NGrid cols={2}>
- <NFormItemGi
- label="重复节拍时长"
- path="repeatedBeatsToSing"
- rule={[
- {
- required: false,
- message: '请选择是否重复节拍时长'
- }
- ]}
- >
- <NRadioGroup v-model:value={forms.repeatedBeatsToSing}>
- <NRadio value={true}>是</NRadio>
- <NRadio value={false}>否</NRadio>
- </NRadioGroup>
- </NFormItemGi>
- </NGrid>
- <NGrid cols={2}>
- <NFormItemGi
- label="上传伴唱"
- path="bSongFile"
- rule={[
- {
- required: false
- }
- ]}
- >
- <UploadFile
- desc={'上传伴唱'}
- disabled={state.previewMode}
- size={30}
- v-model:fileList={state.bSongFile}
- onUpdate:fileList={() => {
- state.isBeatTime = true
- }}
- tips="仅支持上传.mp3格式文件"
- listType="image"
- accept=".mp3"
- bucketName="cloud-coach"
- text="点击上传伴唱文件"
- />
- </NFormItemGi>
- </NGrid>
- {forms.fSongList.length > 0 &&
- forms.fSongList.map((item: any) => {
- return (
- <NGrid class={styles.audioSection}>
- <NFormItemGi
- span={12}
- label={item.track + '范唱'}
- path={item.audioFileUrl}
- rule={[
- {
- required: false
- }
- ]}
- >
- <UploadFile
- desc={'上传范唱'}
- disabled={state.previewMode}
- size={100}
- v-model:fileList={item.audioFileUrl}
- onUpdate:fileList={() => {
- state.isBeatTime = true
- }}
- tips="仅支持上传.mp3格式文件"
- listType="image"
- accept=".mp3"
- bucketName="cloud-coach"
- text={'点击上传范唱文件'}
- />
- </NFormItemGi>
- </NGrid>
- )
- })}
- {forms.multiTracksSelection.length > 1 && forms.isScoreRender && (
- <NGrid cols={2} class={styles.audioSection}>
- <NFormItemGi
- label="总谱范唱"
- path="scoreRenderFile"
- rule={[
- {
- required: false
- }
- ]}
- >
- <UploadFile
- desc={'上传总谱范唱'}
- disabled={state.previewMode}
- size={30}
- v-model:fileList={forms.scoreAudioFileUrl}
- onUpdate:fileList={() => {
- state.isBeatTime = true
- }}
- tips="仅支持上传.mp3格式文件"
- listType="image"
- accept=".mp3"
- bucketName="cloud-coach"
- text="点击上传总谱范唱"
- />
- </NFormItemGi>
- </NGrid>
- )}
- {forms.fSongList.length > 0 &&
- forms.fSongList.map((item: any) => {
- return (
- <NGrid cols={2}>
- <NFormItemGi
- label={item.track + '唱名(男)'}
- path={item.solmizationFileUrl}
- rule={[
- {
- required: false
- }
- ]}
- >
- <UploadFile
- desc={'上传范唱'}
- disabled={state.previewMode}
- size={100}
- v-model:fileList={item.solmizationFileUrl}
- onUpdate:fileList={() => {
- state.isBeatTime = true
- }}
- tips="仅支持上传.mp3格式文件"
- listType="image"
- accept=".mp3"
- bucketName="cloud-coach"
- text={'点击上传唱名文件'}
- />
- </NFormItemGi>
- <NFormItemGi
- label={item.track + '唱名(女)'}
- path={item.femaleSolmizationFileUrl}
- rule={[
- {
- required: false
- }
- ]}
- >
- <UploadFile
- desc={'上传范唱'}
- disabled={state.previewMode}
- size={100}
- v-model:fileList={item.femaleSolmizationFileUrl}
- onUpdate:fileList={() => {
- state.isBeatTime = true
- }}
- tips="仅支持上传.mp3格式文件"
- listType="image"
- accept=".mp3"
- bucketName="cloud-coach"
- text={'点击上传唱名文件'}
- />
- </NFormItemGi>
- </NGrid>
- )
- })}
- </NForm>
- </NSpin>
- {props.type !== 'preview' && (
- <NSpace justify="end" style="padding-top:12px">
- <NButton type="default" onClick={() => emit('close')}>
- 取消
- </NButton>
- <NButton
- type="primary"
- onClick={() => onSubmit()}
- loading={btnLoading.value}
- disabled={btnLoading.value}
- >
- 确认
- </NButton>
- </NSpace>
- )}
- <NModal
- v-model:show={state.showMusicSheetOwnerDialog}
- preset="dialog"
- showIcon={false}
- maskClosable={false}
- title="所属人"
- style={{ width: '800px' }}
- >
- <MusicSheetOwnerDialog
- musicSheetExtend={forms.musicSheetExtend}
- sourceType={forms.sourceType}
- appData={state.appData}
- onClose={() => {
- state.showMusicSheetOwnerDialog = false
- }}
- onChoseMusicSheetOwnerData={(musicSheetOwnerData) => {
- forms.musicSheetExtend = {
- ...musicSheetOwnerData
- }
- setOwnerName()
- }}
- />
- </NModal>
- <NModal
- class={styles.productModal}
- title="自动生成曲谱图片"
- v-model:show={state.productOpen}
- preset="dialog"
- closeOnEsc={false}
- maskClosable={false}
- onClose={() => {
- state.isAutoSave = false
- }}
- showIcon={false}
- >
- <MusicCreateImg
- xmlFileUrl={forms.xmlFileUrl || ''}
- onClose={() => (state.productOpen = false)}
- onConfirm={async (item: any) => {
- // 保存
- try {
- forms.musicImg = item.musicImg
- forms.musicFirstImg = item.musicFirstImg
- forms.musicJianImg = item.musicJianImg
- await onSubmit()
- } catch (e: any) {
- //
- console.log(e, 'e')
- }
- // setTimeout(() => {
- // state.isAutoSave = false
- // }, 50)
- }}
- />
- </NModal>
- {beatTimeData.beatTimeOpen && (
- <MusiceBeatTime
- asyncFlag={true}
- id={beatTimeData.musicId}
- // onClose={handlerMusiceBeatTimeClose}
- onClose={(val: any) => {
- beatTimeData.beatTimeOpen = false
- if (val) return
- state.showUseProject = true
- }}
- ></MusiceBeatTime>
- )}
- <NModal
- blockScroll={true}
- v-model:show={state.showUseProject}
- preset="dialog"
- showIcon={false}
- title={'适用项目'}
- style={{ width: '1200px' }}
- onMaskClick={() => {
- emit('getList')
- emit('close')
- setTimeout(() => {
- btnLoading.value = false
- state.isAutoSave = false
- }, 100)
- }}
- onClose={() => {
- emit('getList')
- emit('close')
- setTimeout(() => {
- btnLoading.value = false
- state.isAutoSave = false
- }, 100)
- }}
- >
- <MusicPlatform
- type={props.type}
- id={state.showUseProjectId}
- useProject={state.useProjectData}
- onClose={handlerMusiceBeatTimeClose}
- />
- </NModal>
- </div>
- )
- }
- })
|