Преглед на файлове

Merge branch 'feature-tianyong-newVersion' into ktyq-online-new

TIANYONG преди 10 месеца
родител
ревизия
f3fe88d824

+ 3 - 3
src/helpers/customMusicScore.ts

@@ -613,8 +613,8 @@ export const resetFormate = () => {
 					}
 				} catch (error) {}
 				const bbox = stave?.getBBox() || {};
-				const bgColor = state.isEvaluatReport ? '#132D4C' : '#609FCF';
-				const botColor = state.isEvaluatReport ? '#040D1E' : '#2B70A5';
+				const bgColor = state.isEvaluatReport ? '#132D4C' : state.isCbsView ? 'transparent' : '#609FCF';
+				const botColor = state.isEvaluatReport ? '#040D1E' : state.isCbsView ? 'transparent' : '#2B70A5';
 				const rect = `<rect class="vf-custom-bg" x="${bbox.x}" y="${bbox.y}" width="${bbox.width}" height="${bbox.height}" fill=${bgColor} />`
 				const rectBottom = `<rect class="vf-custom-bot" x="${bbox.x}" y="${bbox.y+bbox.height}" width="${bbox.width}" height="7.5" fill=${botColor} />`
 				// const filterDom = `<defs>
@@ -645,7 +645,7 @@ export const resetFormate = () => {
 			while (parent && !parent.classList?.contains('vf-measure') && parent.tagName !== 'body' && parent) { // 假设你想找到最外层的 DIV
 				parent = parent.parentElement;
 			}
-			const parentY = parent?.querySelector('.vf-custom-bg').getBoundingClientRect()?.y || 0;
+			const parentY = parent?.querySelector('.vf-custom-bg')?.getBoundingClientRect()?.y || 0;
 			const dotY = group?.getBoundingClientRect()?.y || 0;
 			const distanceY = parentY - dotY;
 			const translateY = 15 - distanceY;

+ 58 - 1
src/helpers/formateMusic.ts

@@ -641,7 +641,6 @@ export const xmlAddPartName = (xml: string) => {
  */
 export const formatXML = (xml: string, xmlUrl?: string): string => {
 	if (!xml) return "";
-	
 	const xmlParse = new DOMParser().parseFromString(xml, "text/xml");
 
 	// 声调
@@ -715,6 +714,9 @@ export const formatXML = (xml: string, xmlUrl?: string): string => {
 	let speed = -1
 	let beats = -1;
 	let beatType = -1;
+	// 前面小节的拍子
+	let preBeats: number = 4;
+	let preBeatType: number = 4;
 	// 小节中如果没有节点默认为休止符
 	for (const measure of measures) {
 		if (beats === -1 && measure.getElementsByTagName("beats").length) {
@@ -726,6 +728,11 @@ export const formatXML = (xml: string, xmlUrl?: string): string => {
 		if (speed === -1 && measure.getElementsByTagName('per-minute').length) {
 		  speed = Number(measure.getElementsByTagName('per-minute')[0]?.textContent)
 		}
+		// 当前小节的拍数
+		const currentBeats = measure.getElementsByTagName("beats").length ? measure.getElementsByTagName("beats")[0]?.textContent : preBeats;
+		const currentBeatType = measure.getElementsByTagName("beat-type").length ? measure.getElementsByTagName("beat-type")[0]?.textContent : preBeatType;
+		preBeats = Number(currentBeats);
+		preBeatType = Number(currentBeatType);
 		const divisions = parseInt(measure.getElementsByTagName("divisions")[0]?.textContent || "256");
 		// 如果note节点里面有space节点,并且没有duration节点,代表这是一个空白节点,需要删除
 		if (measure.getElementsByTagName("note").length && state.isEvxml) {
@@ -773,10 +780,60 @@ export const formatXML = (xml: string, xmlUrl?: string): string => {
           <type>whole</type>
         </note>`;
 		}
+		// if (state.musicRenderType !== 'staff') {
+		// 	transferJianNote(measure, divisions, preBeats, preBeatType)
+		// }
 	}
 	return new XMLSerializer().serializeToString(xmlParse);
 };
 
+/** 转换简谱的全休止符和二分休止符 */
+export const transferJianNote = (measure: any, divisions: number, preBeats: number, preBeatType: number) => {
+	const multipleXs = preBeatType / 4;
+	const notes = measure.getElementsByTagName("note")
+	for (const note of notes) {
+		const noteType = note.getElementsByTagName("type")?.[0]?.textContent || '';
+		if (noteType === 'whole' || noteType === 'half') {
+			// 4/4拍
+			if (preBeats === 4 && preBeatType === 4) {
+
+			} else if (preBeats === 3 && preBeatType === 4) {
+
+			} else if (preBeats === 3 && preBeatType === 8) {
+
+			} else if (preBeats === 3 && preBeatType === 8) {
+
+			} else if (preBeats === 5 && preBeatType === 8) {
+
+			} else if (preBeats === 6 && preBeatType === 8) {
+
+			} else if (preBeats === 9 && preBeatType === 8) {
+
+			} else if (preBeats === 12 && preBeatType === 8) {
+
+			}
+
+			const maxNumber = noteType === 'half' ? 2 : preBeats / multipleXs;
+			if (!Number.isInteger(maxNumber)) {
+				return;
+			}
+			// console.log('几个1/4音符',maxNumber)
+			let quarterNoteNumber = 1;
+			while (quarterNoteNumber <= maxNumber) {
+				const newnote = document.createElement('note');
+				newnote.innerHTML = `
+				<rest></rest>
+				<duration>${divisions}</duration>
+				<voice>1</voice>
+				<type>quarter</type>`
+				measure.insertBefore(newnote, note);
+				quarterNoteNumber += 1;
+			};
+			measure.removeChild(note);
+		} 
+	}
+}
+
 /** 获取所有音符的时值,以及格式化音符 */
 export const formateTimes = (osmd: OpenSheetMusicDisplay) => {
 	const customNoteRealValue = customData.customNoteRealValue;

+ 8 - 0
src/page-instrument/component/authorName/index.module.less

@@ -38,4 +38,12 @@
             }
         }
     }
+}
+
+.blackTitle {
+    :global{
+        .van-notice-bar{
+            color: #000 !important;
+        }
+    }
 }

+ 2 - 2
src/page-instrument/component/authorName/index.tsx

@@ -17,11 +17,11 @@ export default defineComponent({
             {
                !smoothAnimationState.isShow.value && !state.isCombineRender && 
                <div class={["authorName", styles.authorName]}>
-                  <div class={styles.title}>
+                  <div class={[styles.title, state.isCbsView && styles.blackTitle]}>
                      <NoticeBar text={state.examSongName} background="none" />
                   </div>
                   <div class={styles.authorCon}>
-                     <div class={styles.author}>
+                     <div class={[styles.author, state.isCbsView && styles.blackTitle]}>
                         {
                            state.isSingleLine ? 
                            <>

+ 2 - 1
src/page-instrument/evaluat-model/evaluat-result/index.tsx

@@ -68,7 +68,8 @@ export default defineComponent({
         playTime: evaluatingData.resultData.playTime / 1000, // 播放时长
         heardLevel: state.setting.evaluationDifficulty, // 听力等级
         recordFilePath: evaluatingData.resultData.url, // 录音文件路径
-        delFlag: evaluatingData.oneselfCancleEvaluating
+        delFlag: evaluatingData.oneselfCancleEvaluating,
+        instrumentId: state.instrumentId,
       };
       data.saveLoading = true;
       const res = await api_musicPracticeRecordSave(body);

+ 54 - 0
src/page-instrument/view-detail/index.module.less

@@ -221,6 +221,7 @@
         height: 100%;
         padding-bottom: 0 !important;
         padding-right: 0 !important;
+        padding-left: 0 !important;
     }
 
     :global {
@@ -267,6 +268,59 @@
     }
 }
 
+.cbsViewDetail {
+    background: #fff !important;
+
+    >.pageBg {
+        display: none;
+    }
+
+    .headHeight {
+        // background: #fff !important;
+    }
+
+    :global {
+        #cursorImg-0 {
+            opacity: 0 !important;
+        }
+        .noteActive {
+            path {
+                fill: #0097FF;
+                stroke: #0097FF;
+            }
+
+            rect {
+                stroke: #0097FF;
+            }
+        }
+        .lyricActive {
+            text {
+                fill: #0097FF;
+                stroke: #0097FF;
+            }
+        }
+        .voiceActive {
+            rect {
+                fill: #0097FF;
+                stroke: #0097FF;
+            }
+        }
+        .rectActive {
+            fill: #0097FF;
+            stroke: #0097FF;
+        }
+        #selectionBgBox {
+            display: none;
+        }
+        .vf-numbered_note_lines {
+            rect {
+                fill: #000;
+                stroke: #000;
+            }
+        }
+    }
+}
+
 .preJson {
     width: 1px;
     height: 1px;

+ 3 - 2
src/page-instrument/view-detail/index.tsx

@@ -162,6 +162,7 @@ export default defineComponent({
     onMounted(async () => {
       (window as any).appName = "colexiu";
       const id = query.id || "43554";
+      state.isCbsView = query.isCbs;
       // 如果是纯预览模式,0.65倍缩放谱面
       state.isPreView = query.isPreView;
       if (state.isPreView) {
@@ -514,7 +515,7 @@ export default defineComponent({
     };
     return () => (
       <div
-        class={[styles.detail, styles[state.modeType], state.setting.eyeProtection && "eyeProtection", state.platform === IPlatform.PC && state.zoom > 0.8 && styles.PC, state.isPreView && styles.preViewDetail]}
+        class={[styles.detail, styles[state.modeType], state.setting.eyeProtection && "eyeProtection", state.platform === IPlatform.PC && state.zoom > 0.8 && styles.PC, state.isPreView && styles.preViewDetail, state.isCbsView && styles.cbsViewDetail]}
         style={{
           "--detailDataPaddingLeft": detailData.paddingLeft,
           paddingLeft: detailData.paddingLeft,
@@ -568,7 +569,7 @@ export default defineComponent({
           {!detailData.isLoading && 
             <MusicScore 
               ref={musicScoreRef}
-              musicColor={state.isPreView ? '#000000' : '#FFFFFF'}
+              musicColor={state.isPreView || state.isCbsView ? '#000000' : '#FFFFFF'}
               showPartNames={state.isCombineRender}
               onRendered={handleOnRendered} 
             > 

+ 1 - 1
src/page-instrument/view-detail/loading.tsx

@@ -18,7 +18,7 @@ export default defineComponent({
    setup(props) {
       return () =>
          (
-            <div class={[styles.loadingPop, state.isPreView && styles.isPreView]} style={{display:state.isLoading? "flex" : "none"}}>
+            <div class={[styles.loadingPop, (state.isPreView || state.isCbsView) && styles.isPreView]} style={{display:state.isLoading? "flex" : "none"}}>
                <img class={styles.lottie} src={animGif} />
                {/* <Vue3Lottie class={styles.lottie} animationData={animBg}></Vue3Lottie> */}
                <div class={styles.loadingTip}>{props.tipText}</div>

+ 2 - 1
src/page-instrument/view-detail/smoothAnimation/index.ts

@@ -497,7 +497,8 @@ function initCanvasSmooth() {
    smoothDomCtx.lineCap = "round"
    smoothDomCtx.lineJoin = "round"
    // 根据坐标花线
-   drawLines(smoothDomCtx, smoothAnimationState.pointsPos, "rgba(255,255,255,0.6)")
+   const defaultColor = state.isCbsView ? "rgba(0,0,0,0.1)" : "rgba(255,255,255,0.6)";
+   drawLines(smoothDomCtx, smoothAnimationState.pointsPos, defaultColor)
    smoothAnimationState.canvasSmoothDom = smoothDom
 }
 

+ 84 - 21
src/state.ts

@@ -319,6 +319,8 @@ const state = reactive({
   extConfigJson: {} as any,
   /** 扩展样式字段 */
   extStyleConfigJson: {} as any,
+  /** 简谱扩展样式字段 */
+  extJianStyleConfigJson: {} as any,  
   /** 是否开启节拍器(mp3节拍器) */
   isOpenMetronome: false,
   /** 演唱模式是否开启节拍器(mp3节拍器) */
@@ -507,6 +509,8 @@ const state = reactive({
   beatStartTime: 0,
   /** 是否为详情预览模式 */
   isPreView: false,
+  /** 是否为内容平台预览模式 */
+  isCbsView: false,  
   /** 是否为评测报告模式 */
   isEvaluatReport: false,
   /** midi播放器是否初始化中 */
@@ -573,6 +577,8 @@ const state = reactive({
   /** 是否是C调,切换到唱名时,只有C调所有的谱面类型都可以播放唱名文件;其它调的只有首调可以播放唱名,因为唱名是按照C调制作的,没有其它调的唱名文件 */
   isCTone: false,
   evxmlAddPartName: false, // 妙极客的部分曲子没有part-name,需要自行添加的part-name
+  /** 乐器id */
+  instrumentId: null,
 });
 const browserInfo = browser();
 let offset_duration = 0;
@@ -764,6 +770,7 @@ const handlePlaying = () => {
 };
 /** 跳转到指定音符开始播放 */
 export const skipNotePlay = async (itemIndex: number, isStart = false) => {
+  if (state.isPreView) return;
   console.log('点击音符')
   const item = state.times[itemIndex];
   let itemTime = item.time;
@@ -1409,6 +1416,7 @@ function xmlToTracks(xmlString: string) {
 function initMusicSource(data: any, tracks: string[], partIndex: number, workRecordInstrumentId?: string) {
   let track:string,index:number, musicalInstrumentId: string
   const instrumentId = workRecordInstrumentId || query.instrumentId || storeData.user?.instrumentId
+  state.instrumentId = instrumentId;
   let { musicSheetType, isAllSubject, musicSheetSoundList, musicSheetAccompanimentList } = data
   musicSheetSoundList || (musicSheetSoundList = [])
   musicSheetAccompanimentList || (musicSheetAccompanimentList = [])
@@ -1666,6 +1674,7 @@ const setState = (data: any, index: number) => {
   // 开启预备小节
   state.isOpenPrepare = true;
   state.extStyleConfigJson = data.extStyleConfigJson || {}
+  state.extJianStyleConfigJson = data.extJianStyleConfigJson || {}
   // console.log("🚀 ~ state.subjectId:", state.subjectId, state.track as any , state.subjectId)
   // 是否打击乐
   /**
@@ -1704,7 +1713,9 @@ const setState = (data: any, index: number) => {
   // 如果是PC端,放大曲谱
   state.platform = query.platform?.toLocaleUpperCase() || "";
   if (state.platform === IPlatform.PC) {
-    state.zoom = query.zoom || 1.5;
+    if (query.zoom <= 1) {
+      state.zoom = query.zoom || state.zoom;
+    }
     state.enableEvaluation = false;
   }
   /**
@@ -2008,12 +2019,20 @@ watch(
         measureNum = nextMeasureNum
       }
       if (measureNum >= 0 && (measureNum === state.activeMeasureIndex || (measureNum < state.activeMeasureIndex && nextMeasureNum > state.activeMeasureIndex))) {
-        item.querySelector('.vf-custom-bg')?.setAttribute("fill", "#132D4C")
-        item.querySelector('.vf-custom-bot')?.setAttribute("fill", "#040D1E")
+        if (state.isCbsView) {
+          item.querySelector('.vf-custom-bg')?.setAttribute("fill", "#FFF6E1")
+        } else {
+          item.querySelector('.vf-custom-bg')?.setAttribute("fill", "#132D4C")
+          item.querySelector('.vf-custom-bot')?.setAttribute("fill", "#040D1E")
+        }
         // 预备小节
         if(state.sectionFirst && measureNum === state.sectionFirst.MeasureNumberXML && state.section.length === 2){
-          item?.querySelector('.vf-custom-bg')?.setAttribute("fill", "#71B8BD")
-          item?.querySelector('.vf-custom-bot')?.setAttribute("fill", "#448F9C")
+          if (state.isCbsView) {
+            item?.querySelector('.vf-custom-bg')?.setAttribute("fill", "#E3F1FF")
+          } else {
+            item?.querySelector('.vf-custom-bg')?.setAttribute("fill", "#71B8BD")
+            item?.querySelector('.vf-custom-bot')?.setAttribute("fill", "#448F9C")
+          }
         }
       } else {
         // 有选段只清除选段处的
@@ -2026,17 +2045,34 @@ watch(
             rightMeasureNumberXML = state.section[0].MeasureNumberXML
           }
           if(measureNum >= leftMeasureNumberXML && measureNum <= rightMeasureNumberXML){
-            item.querySelector('.vf-custom-bg')?.setAttribute("fill", "#609FCF")
-            item.querySelector('.vf-custom-bot')?.setAttribute("fill", "#2B70A5")
+            if (!state.isCbsView) {
+              item.querySelector('.vf-custom-bg')?.setAttribute("fill", "#609FCF")
+              item.querySelector('.vf-custom-bot')?.setAttribute("fill", "#2B70A5")
+            } else {
+              item.querySelector('.vf-custom-bg')?.setAttribute("fill", 'transparent')
+            }
+          }
+          if (measureNum >= leftMeasureNumberXML && measureNum <= rightMeasureNumberXML) {
+            if (state.isCbsView) {
+              item.querySelector('.vf-custom-bg')?.setAttribute("fill", "rgba(255,246,225,0.5)")
+            }
           }
           // 预备小节
           if(state.sectionFirst && measureNum === state.sectionFirst.MeasureNumberXML){
-            item?.querySelector('.vf-custom-bg')?.setAttribute("fill", "#71B8BD")
-            item?.querySelector('.vf-custom-bot')?.setAttribute("fill", "#448F9C")
+            if (state.isCbsView) {
+              item?.querySelector('.vf-custom-bg')?.setAttribute("fill", "#E3F1FF")
+            } else {
+              item?.querySelector('.vf-custom-bg')?.setAttribute("fill", "#71B8BD")
+              item?.querySelector('.vf-custom-bot')?.setAttribute("fill", "#448F9C")
+            }
           }
         } else {
-          item.querySelector('.vf-custom-bg')?.setAttribute("fill", "#609FCF")
-          item.querySelector('.vf-custom-bot')?.setAttribute("fill", "#2B70A5")
+          if (!state.isCbsView) {
+            item.querySelector('.vf-custom-bg')?.setAttribute("fill", "#609FCF")
+            item.querySelector('.vf-custom-bot')?.setAttribute("fill", "#2B70A5")
+          } else {
+            item.querySelector('.vf-custom-bg')?.setAttribute("fill", 'transparent')
+          }
         }
       }
     })
@@ -2071,18 +2107,35 @@ watch(
         }
         // 小于选中置灰
         if (measureNum < leftMeasureNumberXML) {
-          item.querySelector('.vf-custom-bg')?.setAttribute("fill", "rgba(96,159,207,0.5)")
-          item.querySelector('.vf-custom-bot')?.setAttribute("fill", "rgba(43,112,165,0.5)")
+          if (!state.isCbsView) {
+            item.querySelector('.vf-custom-bg')?.setAttribute("fill", "rgba(96,159,207,0.5)")
+            item.querySelector('.vf-custom-bot')?.setAttribute("fill", "rgba(43,112,165,0.5)")
+          } else {
+            item.querySelector('.vf-custom-bg')?.setAttribute("fill", 'transparent')
+          }
         }
         // 大于选中置灰
         if(measureNum > rightMeasureNumberXML){
-          item.querySelector('.vf-custom-bg')?.setAttribute("fill", "rgba(96,159,207,0.5)")
-          item.querySelector('.vf-custom-bot')?.setAttribute("fill", "rgba(43,112,165,0.5)")
+          if (!state.isCbsView) {
+            item.querySelector('.vf-custom-bg')?.setAttribute("fill", "rgba(96,159,207,0.5)")
+            item.querySelector('.vf-custom-bot')?.setAttribute("fill", "rgba(43,112,165,0.5)")
+          } else {
+            item.querySelector('.vf-custom-bg')?.setAttribute("fill", 'transparent')
+          }
+        }
+        if (measureNum >= leftMeasureNumberXML && measureNum <= rightMeasureNumberXML) {
+          if (state.isCbsView) {
+            item.querySelector('.vf-custom-bg')?.setAttribute("fill", "rgba(255,246,225,0.5)")
+          }
         }
         // 预备小节
         if(state.sectionFirst && measureNum === state.sectionFirst.MeasureNumberXML){
-          item?.querySelector('.vf-custom-bg')?.setAttribute("fill", "#71B8BD")
-          item?.querySelector('.vf-custom-bot')?.setAttribute("fill", "#448F9C")
+          if (state.isCbsView) {
+            item?.querySelector('.vf-custom-bg')?.setAttribute("fill", "#E3F1FF")
+          } else {
+            item?.querySelector('.vf-custom-bg')?.setAttribute("fill", "#71B8BD")
+            item?.querySelector('.vf-custom-bot')?.setAttribute("fill", "#448F9C")
+          }
         }        
       })
     }else{
@@ -2101,11 +2154,20 @@ watch(
           measureNum = nextMeasureNum
         }
         if (measureNum >= 0 && (measureNum === state.activeMeasureIndex || (measureNum < state.activeMeasureIndex && nextMeasureNum > state.activeMeasureIndex)) ) {
-          item.querySelector('.vf-custom-bg')?.setAttribute("fill", "#132D4C")
-          item.querySelector('.vf-custom-bot')?.setAttribute("fill", "#040D1E")
+          if (state.isCbsView) {
+            item.querySelector('.vf-custom-bg')?.setAttribute("fill", "transparent")
+          } else {
+            item.querySelector('.vf-custom-bg')?.setAttribute("fill", "#132D4C")
+            item.querySelector('.vf-custom-bot')?.setAttribute("fill", "#040D1E")
+          }
         } else {
-          item.querySelector('.vf-custom-bg')?.setAttribute("fill", "#609FCF")
-          item.querySelector('.vf-custom-bot')?.setAttribute("fill", "#2B70A5")
+          if (state.isCbsView) {
+            item.querySelector('.vf-custom-bg')?.setAttribute("fill", "transparent")
+          } else {
+            item.querySelector('.vf-custom-bg')?.setAttribute("fill", "#609FCF")
+            item.querySelector('.vf-custom-bot')?.setAttribute("fill", "#2B70A5")
+          }
+
         }
       })
     }
@@ -2143,6 +2205,7 @@ export const checkMoveNoSave = async () => {
 
 /** 刷新谱面 */
 export const refreshMusicSvg = () => {
+  moveData.noteCoords = []
   moveData.modelList = []
   clearSelection();
   resetBaseRate();

+ 2 - 2
src/view/music-score/index.tsx

@@ -249,14 +249,14 @@ export default defineComponent({
 					isInTheGradualRange.value && styles.inGradualRange,
 					state.musicRenderType == EnumMusicRenderType.staff ? "staff" : "jianpuTone",
 					state.isSingleLine && "singleLineMusicBox",
-					(!state.isCreateImg && !state.isPreView && state.musicRenderType === EnumMusicRenderType.staff) ? "blueMusicXml" : "",
+					(!state.isCreateImg && !state.isPreView && !state.isCbsView && state.musicRenderType === EnumMusicRenderType.staff) ? "blueMusicXml" : "",
 					state.isSingleLine && state.playState ==="play" && styles.notTouch,
 					!state.isSingleLine && (state.platform === "PC" || query.isCbs) &&  styles.pcCursorGrab
 
 				]}
 			>
 				{slots.default?.()}
-				{props.showSelection && musicData.showSelection && !state.isPreView && !state.isEvaluatReport &&!state.isSimplePage && state.musicRendered && <Selection />}
+				{props.showSelection && musicData.showSelection && !state.isEvaluatReport &&!state.isSimplePage && state.musicRendered && <Selection />}
 			</div>
 		);
 	},

+ 3 - 1
src/view/plugins/move-music-score/index.module.less

@@ -61,7 +61,7 @@
     left: 0;
     top: 0;
     width: 100%;
-    background: rgba(19, 36, 64, 0.5);
+    background: rgba(0, 0, 0, 0.5);
     z-index: 999999;
     display: flex;
     align-items: center;
@@ -102,6 +102,8 @@
         position: relative;
         width: 76PX;
         box-sizing: border-box;
+        cursor: pointer;
+        pointer-events: all;
         img {
             width: 18PX;
             height: 18PX;

+ 35 - 16
src/view/plugins/move-music-score/index.tsx

@@ -1,6 +1,6 @@
 import { Row, showToast, showConfirmDialog } from "vant";
 import { defineComponent, onMounted, onUnmounted, reactive, nextTick, ref } from "vue";
-import state from "/src/state";
+import state, { IPlatform } from "/src/state";
 import request from "/src/utils/request";
 import { getQuery } from "/src/utils/queryString";
 import styles from "./index.module.less";
@@ -233,18 +233,27 @@ export const filterMoveData = async () => {
 		// }
 		extStyleConfigJson[moveData.partIndex] = list;
 		console.log("🚀 ~ extStyleConfigJson", extStyleConfigJson)
+		const dataParams = state.musicRenderType === 'staff' ? {
+			id: examSongId,
+			extStyleConfigJson: JSON.stringify(extStyleConfigJson),
+		} : {
+			id: examSongId,
+			extJianStyleConfigJson: JSON.stringify(extStyleConfigJson),
+		}
 		const res = await request.post("/musicSheet/img", {
 			requestType: "json",
-			data: {
-				id: examSongId,
-				extStyleConfigJson: JSON.stringify(extStyleConfigJson),
-			}
+			data: dataParams
 		});
 		if (res && res.code == 200) {
 			showToast("保存成功");
 			undoData.undoList = [];
 			undoData.activeItem = null;
-			state.extStyleConfigJson = JSON.stringify(extStyleConfigJson)
+			if (state.musicRenderType === 'staff') {
+				state.extStyleConfigJson = JSON.stringify(extStyleConfigJson)
+			} else {
+				state.extJianStyleConfigJson = JSON.stringify(extStyleConfigJson)
+			}
+			
 		}
 		clearActiveModel();
 	}
@@ -332,10 +341,15 @@ const renderSvgItem = (item: any) => {
 /** 设置元素位置 */
 async function setModelPostion(item: any, x: number, y: number, repeatEdit?: boolean) {
 	// console.log(item)
-	//console.log('位置',x,y)
+	// console.log('位置',x,y)
 	if (item) {
 		const g = document.querySelector("#" + item.id)!; // svg元素
 		const el: HTMLElement = document.querySelector(`[data-id=${item.id}]`)!; // svg元素的背景div
+		let scaleZoom: number = item.zoom ? item.zoom : moveData.zoom;
+		// 预览页时0.65倍的谱面,需要特殊处理下
+		if (state.isPreView && state.zoom == 0.65) {
+			scaleZoom = 0.65
+		}
 		if (x === 0 && y === 0) {
 			g && g.removeAttribute("transform");
 			el && (el.style.transform = "");
@@ -350,15 +364,19 @@ async function setModelPostion(item: any, x: number, y: number, repeatEdit?: boo
 				if (!moveData.noteCoords.length) {
 					await initNoteCoord()
 				}
-				const targetX = moveData.noteCoords[item.noteIdx].x + item.noteRelativeX, targetY = moveData.noteCoords[item.noteIdx].y + item.noteRelativeY;
+				const targetX = moveData.noteCoords[item.noteIdx].x + item.noteRelativeX*(state.zoom/0.8), targetY = moveData.noteCoords[item.noteIdx].y + item.noteRelativeY*(state.zoom/0.8);
 				const original = document.getElementById(item.id)?.getBoundingClientRect() || { x: 0, y: 0 };
 				tsX = targetX - original.x;
 				tsY = targetY - original.y;
-				// console.log('距离',tsX,tsY,x,y)
-				g && g.setAttribute("transform", `translate(${tsX / moveData.zoom}, ${tsY / moveData.zoom})`);
+				// console.log('距离',tsX,tsY,x,y,moveData.zoom)
+				if (state.platform === IPlatform.PC) {
+					// tsX = tsX / 1.5
+					// tsY = tsY / 1.8
+				}
+				g && g.setAttribute("transform", `translate(${tsX / scaleZoom}, ${tsY / scaleZoom})`);
 				el && (el.style.transform = `translate(${tsX}px, ${tsY}px)`);
 			} else {
-				g && g.setAttribute("transform", `translate(${tsX / moveData.zoom}, ${tsY / moveData.zoom})`);
+				g && g.setAttribute("transform", `translate(${tsX / scaleZoom}, ${tsY / scaleZoom})`);
 				el && (el.style.transform = `translate(${tsX}px, ${tsY}px)`);
 			}
 		}
@@ -491,10 +509,11 @@ const handleUndo = () => {
 
 /** 根据移动数据渲染 */
 export const renderForMoveData = () => {
-	if (state.isSingleLine || state.musicRenderType !== 'staff') return; 
-	if (state.extStyleConfigJson) {
+	// 一行谱模式暂时不支持谱面编辑和回显
+	if (state.isSingleLine) return; 
+	if (state.extStyleConfigJson || state.extJianStyleConfigJson) {
 		try {
-			extStyleConfigJson = JSON.parse(state.extStyleConfigJson);
+			extStyleConfigJson = state.musicRenderType === 'staff' ? JSON.parse(state.extStyleConfigJson) : JSON.parse(state.extJianStyleConfigJson);
 		} catch (error) {
 			extStyleConfigJson = {};
 		}
@@ -542,7 +561,7 @@ export const renderForMoveData = () => {
 						}
 					}
 					index = targetIndex
-					item.id = moveData.modelList[targetIndex].id
+					item.id = moveData.modelList[targetIndex]?.id
 				}
 				// console.log(66666666,index)
 				if (index > -1) {
@@ -628,7 +647,7 @@ export default defineComponent({
 					}   */}	
 					<div class={[styles.editToolBox, !moveData.open && styles.itemDisabled]}>		
 						{
-							state.musicRenderType === 'staff' && !state.isSingleLine && 
+							!state.isSingleLine && 
 							<>
 								<div class={[styles.editItem, styles.canEdit]} onClick={switchMoveState}>
 									<img src={moveData.open ? editCloseIcon : editIcon} />

+ 24 - 21
src/view/selection/index.tsx

@@ -263,27 +263,30 @@ export default defineComponent({
 		});
 		return () => (
 			<>
-				<div id="selectionBgBox" class={styles.staveBgContainer}>
-						{
-							selectData.staves.map((item: any) => {
-								return (
-									<>
-										{
-											item.staveBox && item.multipleRestMeasures <= 1 && 
-												<div 
-													style={{
-														left:item.staveBox.left,
-														top:`calc(${item.staveBox.top} + ${item.staveBox.height})`,
-														width:item.staveBox.width
-													}}
-													class={[styles.staveBg]}
-												></div>
-										}
-									</>
-								)
-							})
-						}
-				</div>
+				{
+					!state.isPreView &&
+					<div id="selectionBgBox" class={styles.staveBgContainer}>
+					{
+						selectData.staves.map((item: any) => {
+							return (
+								<>
+									{
+										item.staveBox && item.multipleRestMeasures <= 1 && 
+											<div 
+												style={{
+													left:item.staveBox.left,
+													top:`calc(${item.staveBox.top} + ${item.staveBox.height})`,
+													width:item.staveBox.width
+												}}
+												class={[styles.staveBg]}
+											></div>
+									}
+								</>
+							)
+						})
+					}
+					</div>					
+				}
 				<div
 					id="selectionBox"
 					class={[

+ 2 - 2
vite.config.ts

@@ -76,8 +76,8 @@ export default defineConfig({
         // target: "https://kt.colexiu.com",
         // target: "https://test.lexiaoya.cn",
         // target: "https://kt.colexiu.com",
-        target: "https://dev.resource.colexiu.com", // 内容平台开发环境,内容平台开发,需在url链接上加上isCbs=true
-        // target: "https://test.kt.colexiu.com",
+        // target: "https://test.resource.colexiu.com", // 内容平台开发环境,内容平台开发,需在url链接上加上isCbs=true
+        target: "https://test.kt.colexiu.com",
         // target: "https://mec.colexiu.com",
         changeOrigin: true,
         rewrite: (path) => path.replace(/^\/instrument/, ""),