Skip to content

Commit 81cda1c

Browse files
committed
feat(PianoRoll): 重构乐谱编辑与音符转换逻辑
- 更新ScoreEditor组件,使用pianoRollStore管理乐谱转换数据 - 在PianoRoll组件中调整音符渲染逻辑,确保与pianoRollStore的数据一致性 - 增强音符编辑功能,优化用户体验 - 添加注释以提高代码可读性和可维护性
1 parent 18c0d80 commit 81cda1c

File tree

5 files changed

+61
-40
lines changed

5 files changed

+61
-40
lines changed

packages/web/src/components/editor/ScoreEditor.vue

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import { defineProps, defineEmits, ref, onMounted, onBeforeUnmount, watch } from
3131
import { EditorState } from '@codemirror/state';
3232
import { EditorView, keymap, ViewUpdate, lineNumbers } from '@codemirror/view';
3333
import { history, defaultKeymap, indentWithTab } from '@codemirror/commands';
34-
import { useEditorStore, type PianoRollNote } from '../../stores';
34+
import { useEditorStore, usePianoRollStore } from '../../stores';
3535
import { HighlightStyle, syntaxHighlighting, StreamLanguage } from '@codemirror/language';
3636
import { tags } from '@lezer/highlight';
3737
import { SNPointerLayer, SNTransition } from 'simple-notation';
@@ -46,6 +46,7 @@ const emits = defineEmits(['toggle-accordion']);
4646
4747
const scoreEditorRef = ref<HTMLDivElement | null>(null);
4848
const editorStore = useEditorStore();
49+
const pianoRollStore = usePianoRollStore();
4950
const router = useRouter();
5051
5152
/**
@@ -54,7 +55,8 @@ const router = useRouter();
5455
function editInPianoRoll() {
5556
const { score, info } = editorStore.formData;
5657
const beatsPerBar = parseInt(info.beat || '4', 10);
57-
editorStore.setConversionData(score, beatsPerBar);
58+
pianoRollStore.setConversionData(score, beatsPerBar);
59+
pianoRollStore.setIsEditingFromScoreEditor(true);
5860
router.push('/piano-roll');
5961
}
6062

packages/web/src/pages/PianoRoll.vue

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<Card>
33
<template v-slot:title>
44
<div class="flex justify-between items-center w-full">
5-
<span>{{ editorStore.isEditingFromScoreEditor ? '编辑乐谱' : '编曲文本转换工具' }}</span>
5+
<span>{{ pianoRollStore.isEditingFromScoreEditor ? '编辑乐谱' : '编曲文本转换工具' }}</span>
66
<div class="flex items-center gap-4">
77
<div class="flex items-center gap-2">
88
<label for="beatsPerBarInput" class="text-sm font-medium text-gray-300">拍/节:</label>
@@ -39,14 +39,14 @@
3939
/>
4040
</div>
4141
<Button @click="togglePlayback">{{ isPlaying ? '停止' : '播放' }}</Button>
42-
<Button v-if="editorStore.isEditingFromScoreEditor" @click="completeEditing"
42+
<Button v-if="pianoRollStore.isEditingFromScoreEditor" @click="completeEditing"
4343
>完成编辑</Button
4444
>
45-
<Button v-if="!editorStore.isEditingFromScoreEditor" @click="onGenerateClick"
45+
<Button v-if="!pianoRollStore.isEditingFromScoreEditor" @click="onGenerateClick"
4646
>生成模板文本</Button
4747
>
4848
<Button
49-
v-if="!editorStore.isEditingFromScoreEditor"
49+
v-if="!pianoRollStore.isEditingFromScoreEditor"
5050
@click="createNewScoreFromArrangement"
5151
>以此新建乐谱</Button
5252
>
@@ -113,10 +113,11 @@ import { useRouter } from 'vue-router';
113113
import { SNTransition, type SNTemplate } from 'simple-notation';
114114
import * as Tone from 'tone';
115115
import { useTone } from '@/use';
116-
import { useEditorStore, type PianoRollNote } from '@/stores';
116+
import { useEditorStore, usePianoRollStore, type PianoRollNote } from '@/stores';
117117
118118
const { playNote, midiToNoteName, setInstrument } = useTone();
119119
const editorStore = useEditorStore();
120+
const pianoRollStore = usePianoRollStore();
120121
const router = useRouter();
121122
const pianoGridRef = ref<InstanceType<typeof PianoGrid> | null>(null);
122123
const isModalOpen = ref(false);
@@ -256,34 +257,38 @@ function loadAndRenderNotes(notesToRender: PianoRollNote[], beatsInfo: number) {
256257
tempo.value = parseInt(editorStore.formData.info.tempo || '120', 10);
257258
258259
// 3. 将转换后的音符存入 store(如果它们还不在那里)
259-
if (editorStore.pianoRollNotes !== notesToRender) {
260-
editorStore.pianoRollNotes = notesToRender;
260+
if (pianoRollStore.pianoRollNotes !== notesToRender) {
261+
pianoRollStore.setPianoRollNotes(notesToRender);
261262
}
262263
}
263264
264265
onMounted(() => {
265266
// Case 1: 从乐谱编辑器带数据过来,需要异步转换
266-
if (editorStore.scoreToConvert && editorStore.beatsPerBarToConvert && pianoGridRef.value) {
267-
editorStore.isEditingFromScoreEditor = true;
267+
if (
268+
pianoRollStore.isEditingFromScoreEditor &&
269+
pianoRollStore.scoreToConvert &&
270+
pianoRollStore.beatsPerBarToConvert &&
271+
pianoGridRef.value
272+
) {
268273
(async () => {
269274
isLoading.value = true;
270275
loadingProgress.value = 0;
271276
const notes = await convertTextToNotesWithProgress(
272-
editorStore.scoreToConvert!,
273-
editorStore.beatsPerBarToConvert!,
277+
pianoRollStore.scoreToConvert!,
278+
pianoRollStore.beatsPerBarToConvert!,
274279
(progress) => {
275280
loadingProgress.value = progress;
276281
},
277282
);
278-
loadAndRenderNotes(notes, editorStore.beatsPerBarToConvert!);
283+
loadAndRenderNotes(notes, pianoRollStore.beatsPerBarToConvert!);
279284
isLoading.value = false;
280-
editorStore.clearConversionData(); // 清理临时数据
285+
pianoRollStore.clearConversionData(); // 清理临时数据
281286
})();
282287
}
283288
// Case 2: 刷新页面或从其他页面返回,直接加载store中已有的数据
284-
else if (editorStore.isEditingFromScoreEditor && pianoGridRef.value) {
289+
else if (pianoRollStore.isEditingFromScoreEditor && pianoGridRef.value) {
285290
const beatsInfo = parseInt(editorStore.formData.info.beat || '4', 10);
286-
loadAndRenderNotes(editorStore.pianoRollNotes, beatsInfo);
291+
loadAndRenderNotes(pianoRollStore.pianoRollNotes, beatsInfo);
287292
}
288293
});
289294
@@ -498,7 +503,7 @@ function completeEditing() {
498503
const notesList = pianoGridRef.value.generateNotesList();
499504
const scoreText = convertNotesToText(notesList, beatsPerBar.value);
500505
editorStore.updateScore(scoreText); // 只更新乐谱文本
501-
editorStore.isEditingFromScoreEditor = false; // 重置标志位
506+
pianoRollStore.setIsEditingFromScoreEditor(false); // 重置标志位
502507
router.push('/');
503508
}
504509
}

packages/web/src/stores/editor.ts

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,6 @@ import {
88
SNChordType,
99
SNScoreType,
1010
} from 'simple-notation';
11-
import { ref } from 'vue';
12-
13-
// 编曲工具音符数据接口
14-
export interface PianoRollNote {
15-
index: number;
16-
pitch: number;
17-
pitchName: string;
18-
start: number;
19-
duration: number;
20-
}
2111

2212
export const useEditorStore = defineStore('editor', {
2313
state: () => ({
@@ -48,10 +38,6 @@ export const useEditorStore = defineStore('editor', {
4838
},
4939
} as Partial<SNOptions>,
5040
selectionRange: { start: null as number | null, end: null as number | null },
51-
isEditingFromScoreEditor: false,
52-
pianoRollNotes: [] as PianoRollNote[],
53-
scoreToConvert: null as string | null,
54-
beatsPerBarToConvert: null as number | null,
5541
}),
5642

5743
actions: {
@@ -112,13 +98,5 @@ export const useEditorStore = defineStore('editor', {
11298
},
11399
};
114100
},
115-
setConversionData(score: string, beatsPerBar: number) {
116-
this.scoreToConvert = score;
117-
this.beatsPerBarToConvert = beatsPerBar;
118-
},
119-
clearConversionData() {
120-
this.scoreToConvert = null;
121-
this.beatsPerBarToConvert = null;
122-
},
123101
},
124102
});

packages/web/src/stores/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ export * from './instrument/piano';
22
export * from './instrument/guitar';
33
export * from './instrument/harmonica';
44
export * from './editor';
5+
export * from './pianoRoll';
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { defineStore } from 'pinia';
2+
3+
// 编曲工具音符数据接口
4+
export interface PianoRollNote {
5+
index: number;
6+
pitch: number;
7+
pitchName: string;
8+
start: number;
9+
duration: number;
10+
}
11+
12+
export const usePianoRollStore = defineStore('pianoRoll', {
13+
state: () => ({
14+
isEditingFromScoreEditor: false,
15+
pianoRollNotes: [] as PianoRollNote[],
16+
scoreToConvert: null as string | null,
17+
beatsPerBarToConvert: null as number | null,
18+
}),
19+
actions: {
20+
setConversionData(score: string, beatsPerBar: number) {
21+
this.scoreToConvert = score;
22+
this.beatsPerBarToConvert = beatsPerBar;
23+
},
24+
clearConversionData() {
25+
this.scoreToConvert = null;
26+
this.beatsPerBarToConvert = null;
27+
},
28+
setPianoRollNotes(notes: PianoRollNote[]) {
29+
this.pianoRollNotes = notes;
30+
},
31+
setIsEditingFromScoreEditor(isEditing: boolean) {
32+
this.isEditingFromScoreEditor = isEditing;
33+
},
34+
},
35+
});

0 commit comments

Comments
 (0)