import { defineComponent, nextTick, onMounted, onUnmounted, reactive, ref, watch } from "vue"; import ABCJS, { AbcElem, AbcVisualParams, ClickListenerAnalysis, ClickListenerDrag, NoteTimingEvent, SynthObjectController } from "abcjs"; import { api_musicSheetCreationWav2mp3, api_musicSheetCreationSaveMusic, api_subjectList, api_musicSheetCreationUpdate } from "../../api"; import { NButton, NForm, NFormItem, NIcon, NModal, NProgress, NSelect, NSpace, useMessage } from "naive-ui"; import styles from "./index.module.less"; import { Close } from "@vicons/ionicons5"; import { SelectMixedOption } from "naive-ui/es/select/src/interface"; import { api_uploadFile } from "/src/utils/uploadFile"; import { bufferToWave } from "/src/helpers/parseABC"; import { decodeUrl, downloadFile } from "/src/utils"; import { renderMeasures } from "../../home/runtime"; import cleanDeep from "clean-deep"; export default defineComponent({ name: "UploadToResources", props: { show: { type: Boolean, default: false, }, item: { type: Object, default: () => ({}), }, }, emits: ["update:show", "success"], setup(props, { emit }) { const message = useMessage(); const model = reactive({ subjects: [] as SelectMixedOption[], saveLoading: false, saveProgress: 0, productOpen: false, productIfameSrc: "", }); const froms = reactive({ subjectId: null, isPublic: 0, mp3: "", musicImg: "", musicSvg: "", musicJianSvg: "", }); const getSubjects = async () => { const { data } = await api_subjectList(); model.subjects = data.map((item: any) => { return { label: item.name, value: item.id, }; }); }; const handleProductResult = (res: MessageEvent) => { const data = res.data; if (data?.api === "webApi_renderSvg") { let imgs: any = []; try { imgs = JSON.parse(data.product); } catch (error) { console.log("🚀 ~ error:", error); } imgs = imgs.filter((item: any) => item.base64); if (imgs.length === 3) { handleUploadImg(imgs); } console.log("🚀 ~ 上传之前", [...imgs]); } }; const handleUploadImg = async (imgs: any[]) => { if (!props.show) return; for (let i = 0; i < imgs.length; i++) { const fileName = `${Date.now()}p${i}.png`; const file = dataURLtoFile(imgs[i].base64, fileName); imgs[i].url = await api_uploadFile(file, fileName, () => {}); model.saveProgress = (i + 1) * 20; } froms.musicImg = imgs[0]?.url || ""; froms.musicSvg = imgs[1]?.url || ""; froms.musicJianSvg = imgs[2]?.url || ""; model.productOpen = false; imgs = []; if (!props.show) return; handleSubmit(); }; /** base64转file */ const dataURLtoFile = (dataurl: string, filename: string) => { let arr = dataurl.split(",") || [], mime = arr[0].match(/:(.*?);/)?.[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } return new File([u8arr], filename, { type: mime }); }; onMounted(() => { getSubjects(); window.addEventListener("message", handleProductResult); }); onUnmounted(() => { window.removeEventListener("message", handleProductResult); }); watch( () => props.item, () => { // console.log(props.item, model.subjects); const subjectId = model.subjects.length > 0 ? model.subjects[0].value : null; froms.subjectId = props.item.subjectId ?? subjectId; } ); const createMusic = async () => { await api_musicSheetCreationSaveMusic({ musicSheetCreationId: props.item.id, musicSheetName: props.item.name || "曲谱名称", musicSheetCategoriesId: "", audioType: "MP3", mp3Type: "MP3", xmlFileUrl: props.item.xml, musicSubject: froms.subjectId, showFingering: 1, canEvaluate: 1, notation: 1, playSpeed: props.item?.visualObj?.metaText?.tempo?.bpm || "", background: [ { audioFileUrl: froms.mp3, track: "P1", }, ], musicImg: froms.musicImg, musicSvg: froms.musicSvg, musicJianSvg: froms.musicJianSvg, extConfigJson: "", }); }; const wav2mp3 = async () => { try { const { data } = await api_musicSheetCreationWav2mp3(props.item.filePath); froms.mp3 = data; } catch (error) { message.error("wav转mp3失败"); handleClose(); } }; const handleClose = () => { model.saveLoading = false; model.saveProgress = 0; }; /** 自动生成图片 */ const handleAutoProduct = async () => { model.saveProgress = 0; const xml = props.item.xml; const res = await fetch(xml); if (res.status > 299 || res.status < 200) { message.error("xml文件不存在"); handleClose(); return; } const origin = /(localhost|192)/.test(location.host) ? "https://test.lexiaoya.cn" : location.origin; model.productIfameSrc = `${origin}/instrument/#/product-img?xmlUrl=${xml}&productXmlImg=1`; model.productOpen = true; setTimeout(() => { model.saveProgress = 10; }, 800); }; // 生成wav const productWav = async (isUrl = true) => { return new Promise((resolve) => { const subjectCode = props.item.subjectCode || "acoustic_grand_piano"; const _instruments = ABCJS.synth.instrumentIndexToName.indexOf(subjectCode); const program = _instruments > -1 ? _instruments : 0; const midiBuffer = new ABCJS.synth.CreateSynth(); midiBuffer .init({ visualObj: props.item.visualObj, options: { program, soundFontUrl: "https://oss.dayaedu.com/musicSheet/", // soundFontUrl: "https://paulrosen.github.io/midi-js-soundfonts/FluidR3_GM/", // 默认 FluidR3_GM // soundFontUrl: "https://paulrosen.github.io/midi-js-soundfonts/MusyngKite/", // Musyng Kite }, }) .then(() => { midiBuffer.prime().then(async () => { if (isUrl) { downloadFile(midiBuffer.download(), (props.item.name || "曲谱") + ".wav"); } else { const blob = bufferToWave((midiBuffer as any).getAudioBuffer()); const fileName = +new Date() + Math.ceil(Math.random() * 1000); const wavurl = await api_uploadFile(blob, fileName + ".wav"); resolve(wavurl); } }); }); }); }; const fromRef = ref(); const handleUpload = () => { fromRef.value.validate(async (err: any) => { if (err) { return; } if (!props.item.xml) { message.error("没有生成xml文件"); handleClose(); return; } // if (!props.item.filePath) { // message.error("没有生成wav文件"); // handleClose(); // return; // } model.saveLoading = true; handleAutoProduct(); }); }; const handleSubmit = async () => { // 判断是否有wav文件,如果没有则生成保存 // if (!props.item.filePath) { const url = await productWav(false); props.item.filePath = url; // } await api_musicSheetCreationUpdate({ id: props.item.id, subjectId: froms.subjectId, // filePath: props.item.filePath, }); await wav2mp3(); model.saveProgress = 70; if (!props.show) return; await createMusic(); model.saveProgress = 100; emit("success"); if (!props.show) return; message.success("上传成功"); setTimeout(() => { model.saveLoading = false; emit("update:show", false); }, 300); }; return () => ( <> { model.productOpen = false; emit("update:show", val); }} >
上传到我的资源
{ model.productOpen = false; emit("update:show", false); }} >
{/* (froms.isPublic = 1)} > 公开 (froms.isPublic = 0)} > 不公开 */}
{ model.productOpen = false; handleClose(); emit("update:show", false); }} > 取消 handleUpload()}> 确定
{model.productOpen && } ); }, });