|
@@ -0,0 +1,190 @@
|
|
|
+import { defineComponent, onMounted, reactive } from "vue";
|
|
|
+import state, { EnumMusicRenderType } from "/src/state";
|
|
|
+import { setGlobalData } from "../../utils";
|
|
|
+import MusicScore from "../../view/music-score";
|
|
|
+import { sysMusicScoreAccompanimentQueryPage } from "../api";
|
|
|
+import styles from "./index.module.less";
|
|
|
+import { getQuery } from "/src/utils/queryString";
|
|
|
+import { Toast, closeToast, showLoadingToast, showToast } from "vant";
|
|
|
+import { svg2canvas } from "/src/utils/svg2canvas";
|
|
|
+
|
|
|
+export default defineComponent({
|
|
|
+ name: "music-list",
|
|
|
+ setup() {
|
|
|
+ const query: any = getQuery();
|
|
|
+
|
|
|
+ const detailData = reactive({
|
|
|
+ isLoading: true,
|
|
|
+ isProductLoading: false,
|
|
|
+ product: [
|
|
|
+ {
|
|
|
+ state: false,
|
|
|
+ name: "五线谱",
|
|
|
+ type: EnumMusicRenderType.staff,
|
|
|
+ base64: "" as any,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ state: false,
|
|
|
+ name: "首调",
|
|
|
+ type: EnumMusicRenderType.firstTone,
|
|
|
+ base64: "" as any,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ state: false,
|
|
|
+ name: "固定调",
|
|
|
+ type: EnumMusicRenderType.fixedTone,
|
|
|
+ base64: "" as any,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ });
|
|
|
+ // console.log(route.params, query)
|
|
|
+ /** 获取曲谱数据 */
|
|
|
+ const getMusicInfo = (res: any) => {
|
|
|
+ const index = query["part-index"] ? parseInt(query["part-index"] as string) : 0;
|
|
|
+ const musicData = res.data.background[index] || {};
|
|
|
+ const musicInfo = {
|
|
|
+ ...res.data,
|
|
|
+ music: musicData.audioFileUrl || res.data.audioFileUrl,
|
|
|
+ accompany: musicData.metronomeUrl || res.data.metronomeUrl,
|
|
|
+ musicSheetId: musicData.musicSheetId || res.data.id,
|
|
|
+ track: musicData.track || res.data.track,
|
|
|
+ };
|
|
|
+ console.log("🚀 ~ musicInfo:", musicInfo);
|
|
|
+ setState(musicInfo, index);
|
|
|
+ setCustom();
|
|
|
+ detailData.isLoading = false;
|
|
|
+ };
|
|
|
+
|
|
|
+ const setState = (data: any, index: number) => {
|
|
|
+ state.appName = "COLEXIU";
|
|
|
+ state.detailId = data.id;
|
|
|
+ state.xmlUrl = data.xmlFileUrl;
|
|
|
+ state.partIndex = index;
|
|
|
+ state.subjectId = data.musicSubject;
|
|
|
+ state.categoriesId = data.categoriesId;
|
|
|
+ state.categoriesName = data.musicTagNames;
|
|
|
+ state.enableEvaluation = data.canEvaluate ? true : false;
|
|
|
+ state.examSongId = data.id + "";
|
|
|
+ state.examSongName = data.musicSheetName;
|
|
|
+ // 解析扩展字段
|
|
|
+ if (data.extConfigJson) {
|
|
|
+ try {
|
|
|
+ state.extConfigJson = JSON.parse(data.extConfigJson as string);
|
|
|
+ } catch (error) {
|
|
|
+ console.error("解析扩展字段错误:", error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ state.isOpenMetronome = data.mp3Type === "MP3_METRONOME" ? true : false;
|
|
|
+ // 曲子包含节拍器,就不开启节拍器
|
|
|
+ state.needTick = data.mp3Type === "MP3_METRONOME" ? false : true;
|
|
|
+ state.isShowFingering = data.showFingering ? true : false;
|
|
|
+ state.music = data.music;
|
|
|
+ state.accompany = data.accompany;
|
|
|
+ state.midiUrl = data.midiUrl;
|
|
|
+ state.parentCategoriesId = data.musicTag;
|
|
|
+ state.musicSheetCategoriesId = data.musicSheetCategoriesId;
|
|
|
+ state.playMode = data.audioType === "MP3" ? "MP3" : "MIDI";
|
|
|
+ state.originSpeed = state.speed = data.playSpeed;
|
|
|
+ state.track = data.code || data.track;
|
|
|
+ state.enableNotation = data.notation ? true : false;
|
|
|
+
|
|
|
+ //课堂乐器,默认简谱
|
|
|
+ state.musicRenderType = EnumMusicRenderType.staff;
|
|
|
+ };
|
|
|
+
|
|
|
+ const setCustom = () => {
|
|
|
+ if (state.extConfigJson.multitrack) {
|
|
|
+ setGlobalData("multitrack", state.extConfigJson.multitrack);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ onMounted(() => {
|
|
|
+ (window as any).appName = "colexiu";
|
|
|
+ const id = query.id;
|
|
|
+ Promise.all([sysMusicScoreAccompanimentQueryPage(id)]).then((values) => {
|
|
|
+ getMusicInfo(values[0]);
|
|
|
+ });
|
|
|
+ showLoadingToast({ message: "生成中", duration: 0 });
|
|
|
+ });
|
|
|
+
|
|
|
+ /** 渲染完成 */
|
|
|
+ const handleRendered = async () => {
|
|
|
+ const item = detailData.product.find((item) => item.type === state.musicRenderType);
|
|
|
+ if (!item) return;
|
|
|
+ item.state = true;
|
|
|
+ item.base64 = await downPng();
|
|
|
+ const nextItem = detailData.product.find((item: any) => !item.state);
|
|
|
+ if (nextItem) {
|
|
|
+ state.musicRenderType = nextItem.type;
|
|
|
+ detailData.isLoading = true;
|
|
|
+ setTimeout(() => (detailData.isLoading = false), 500);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ closeToast();
|
|
|
+ console.log(detailData.product);
|
|
|
+ window.parent?.postMessage(
|
|
|
+ {
|
|
|
+ api: "webApi_renderSvg",
|
|
|
+ product: JSON.stringify(detailData.product),
|
|
|
+ },
|
|
|
+ "*"
|
|
|
+ );
|
|
|
+ };
|
|
|
+ const downPng = () => {
|
|
|
+ return new Promise((resolve) => {
|
|
|
+ setTimeout(async () => {
|
|
|
+ const svg: any = document.getElementById("osmdSvgPage1")?.cloneNode(true);
|
|
|
+ if (!svg) {
|
|
|
+ resolve("");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const cw = svg.width.animVal.value;
|
|
|
+ const ch = svg.height.animVal.value;
|
|
|
+ const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
|
|
|
+ rect.setAttribute("x", "0");
|
|
|
+ rect.setAttribute("y", "0");
|
|
|
+ rect.setAttribute("width", `${cw * 2}`);
|
|
|
+ rect.setAttribute("height", `${ch * 2}`);
|
|
|
+ rect.setAttribute("fill", "#fff");
|
|
|
+ svg.prepend(rect);
|
|
|
+ const _canvas = svg2canvas(svg.outerHTML);
|
|
|
+ const base64 = _canvas.toDataURL("image/png", 1);
|
|
|
+ resolve(base64);
|
|
|
+ // if (state.platform === IPlatform.PC) {
|
|
|
+ // let el: any = document.createElement("a");
|
|
|
+ // // 设置 href 为图片经过 base64 编码后的字符串,默认为 png 格式
|
|
|
+ // el.href = _canvas.toDataURL();
|
|
|
+ // el.download = state.examSongName;
|
|
|
+
|
|
|
+ // // 创建一个点击事件并对 a 标签进行触发
|
|
|
+ // const event = new MouseEvent("click");
|
|
|
+ // el.dispatchEvent(event);
|
|
|
+ // setTimeout(() => {
|
|
|
+ // showToast({ message: "保存成功", type: "success" });
|
|
|
+ // el = null;
|
|
|
+ // }, 300);
|
|
|
+ // } else {
|
|
|
+
|
|
|
+ // const res = await api_savePicture({
|
|
|
+ // base64,
|
|
|
+ // });
|
|
|
+ // if (res?.content?.status === "success") {
|
|
|
+ // showToast({ message: "保存成功", type: "success" });
|
|
|
+ // } else {
|
|
|
+ // showToast({ message: "保存失败", type: "fail" });
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ }, 500);
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ return () => (
|
|
|
+ <div class={styles.detail}>
|
|
|
+ <div id="scrollContainer" class={[styles.container, "hideCursor"]}>
|
|
|
+ {/* 曲谱渲染 */}
|
|
|
+ {!detailData.isLoading && <MusicScore showSelection={false} onRendered={handleRendered} />}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ },
|
|
|
+});
|