@@ -4,7 +4,7 @@ import SelectFileTypeTip from "./SelectFileTypeTip";
44import { LicenseStatus , MessageLevel } from "@/client/apiGen" ;
55import CheckingModal from "./CheckingModal" ;
66import api , { getUrl } from "@/client/api" ;
7- import { globalCapture , selectedADir , selectMusicId , updateMusicList , version as appVersion } from "@/store/refs" ;
7+ import { globalCapture , isReadOnlyDir , selectedADir , selectMusicId , updateMusicList , version as appVersion } from "@/store/refs" ;
88import { appSettings } from "@/store/settings" ;
99import ErrorDisplayIdInput from "./ErrorDisplayIdInput" ;
1010import ImportStepDisplay from "./ImportStepDisplay" ;
@@ -97,14 +97,18 @@ export default defineComponent({
9797 return ! reject ;
9898 }
9999
100+ // 导入一旦开始就把目标目录固定下来:中途切目录(尤其是切到只读的 A000)
101+ // 也不能把写操作带偏,所有写入都用这个快照
102+ let importDir = selectedADir . value ;
103+
100104 const uploadMovie = ( id : number , movie : File , offset : number ) => new Promise < void > ( ( resolve , reject ) => {
101105 currentMovieProgress . value = 0 ;
102106 const body = new FormData ( ) ;
103107 body . append ( 'padding' , offset . toString ( ) ) ;
104108 body . append ( 'file' , movie ) ;
105109 body . append ( 'file' , movie ) ;
106110 const controller = new AbortController ( ) ;
107- fetchEventSource ( getUrl ( `SetMovieApi/${ selectedADir . value } /${ id } ` ) , {
111+ fetchEventSource ( getUrl ( `SetMovieApi/${ importDir } /${ id } ` ) , {
108112 signal : controller . signal ,
109113 method : 'PUT' ,
110114 body,
@@ -144,7 +148,7 @@ export default defineComponent({
144148 try {
145149 music . importStep = IMPORT_STEP . create ;
146150
147- const createRet = ( await api . AddMusic ( music . id , selectedADir . value ) ) . data ;
151+ const createRet = ( await api . AddMusic ( music . id , importDir ) ) . data ;
148152 if ( createRet ) throw new Error ( createRet ) ;
149153
150154 music . importStep = IMPORT_STEP . chart ;
@@ -163,13 +167,13 @@ export default defineComponent({
163167 utageRightLevel : music . utageMapping . rightLevel ,
164168 } : { } ) ,
165169 debug : import . meta. env . DEV ,
166- assetDir : selectedADir . value ,
170+ assetDir : importDir ,
167171 } ) ) . data ;
168172
169173 errors . value . push ( ...res . errors ! . map ( it => ( { ...it , name : music . name } ) ) ) ;
170174 if ( res . fatal ) {
171175 try {
172- await api . DeleteMusic ( music . id , selectedADir . value ) ;
176+ await api . DeleteMusic ( music . id , importDir ) ;
173177 } catch {
174178 }
175179 return ;
@@ -181,14 +185,14 @@ export default defineComponent({
181185 // 音频上应该应用的延迟audioPadding = 谱面上应用的延迟chartPadding - &first
182186 let audioPadding = chartPadding - music . first ;
183187
184- await api . SetAudio ( music . id , selectedADir . value , { file : music . track , padding : audioPadding , ignoreGapless : ! ! tempOptions . value . ignoreGapless } ) ;
188+ await api . SetAudio ( music . id , importDir , { file : music . track , padding : audioPadding , ignoreGapless : ! ! tempOptions . value . ignoreGapless } ) ;
185189 if ( music . previewTime ) {
186190 // 因为&demo_seek和&demo_len都是相对于原始音源的,所以这里的时间必须要扣掉上面SetAudio时应用的padding。
187191 // 根据SetAudioApi的定义,padding为正表示歌曲前面被加了空白,因此原本的预览段在新的裁剪后的音频中的位置也要相应后移;padding为负反之。
188192 // 因此,直接给startTime和endTime都加上audioPadding即可。
189193 music . previewTime . startTime ! += audioPadding ;
190194 music . previewTime . endTime ! += audioPadding
191- await api . SetAudioPreview ( music . id , selectedADir . value , music . previewTime ) ;
195+ await api . SetAudioPreview ( music . id , importDir , music . previewTime ) ;
192196 }
193197
194198 if ( music . movie && ! tempOptions . value . disableBga ) {
@@ -202,7 +206,7 @@ export default defineComponent({
202206 }
203207
204208 music . importStep = IMPORT_STEP . jacket ;
205- if ( music . bg ) await api . SetMusicJacket ( music . id , selectedADir . value , { file : music . bg } ) ;
209+ if ( music . bg ) await api . SetMusicJacket ( music . id , importDir , { file : music . bg } ) ;
206210
207211 music . importStep = IMPORT_STEP . finish ;
208212 } catch ( e ) {
@@ -218,14 +222,17 @@ export default defineComponent({
218222 // 如果是在创建乐曲这步就挂了,说明乐曲XML没有创建成功,则不需要删除乐曲。
219223 // 否则,在ID冲突的情况下,会把原本的乐曲给删除掉,见 https://github.com/MuNET-OSS/MaiChartManager/issues/34
220224 try {
221- await api . DeleteMusic ( music . id , selectedADir . value ) ;
225+ await api . DeleteMusic ( music . id , importDir ) ;
222226 } catch {
223227 }
224228 }
225229 }
226230 }
227231
228232 startProcess = async ( dir ?: ImportDirectory | ImportDirectory [ ] ) => {
233+ // A000 只读:拖拽进来的导入也要挡住,不只是点按钮
234+ if ( isReadOnlyDir . value ) return ;
235+ importDir = selectedADir . value ;
229236 let id = getNextUnusedMusicId ( ) ;
230237 const usedIds = [ ] as number [ ] ;
231238 errors . value = [ ] ;
@@ -305,7 +312,7 @@ export default defineComponent({
305312 }
306313 }
307314
308- return ( ) => < Button onClick = { ( ) => startProcess ( ) } variant = "secondary" >
315+ return ( ) => < Button onClick = { ( ) => startProcess ( ) } disabled = { isReadOnlyDir . value } variant = "secondary" >
309316 { t ( 'chart.import.title' ) }
310317 < SelectFileTypeTip show = { step . value === STEP . selectFile } closeModal = { closeModal } />
311318 < CheckingModal title = { t ( 'chart.import.checkingTitle' ) } show = { step . value === STEP . checking } closeModal = { closeModal } />
0 commit comments