@@ -1120,6 +1120,9 @@ const els = {
11201120 writtenPattern : document . querySelector ( "#writtenPattern" ) ,
11211121 previousRoundBtn : document . querySelector ( "#previousRoundBtn" ) ,
11221122 nextRoundBtn : document . querySelector ( "#nextRoundBtn" ) ,
1123+ trackPartModal : document . querySelector ( "#trackPartModal" ) ,
1124+ closeTrackPartModal : document . querySelector ( "#closeTrackPartModal" ) ,
1125+ trackPartOptions : document . querySelector ( "#trackPartOptions" ) ,
11231126 previousStitchBtn : document . querySelector ( "#previousStitchBtn" ) ,
11241127 nextStitchBtn : document . querySelector ( "#nextStitchBtn" ) ,
11251128 restartRoundBtn : document . querySelector ( "#restartRoundBtn" ) ,
@@ -2371,6 +2374,15 @@ function uniquePatternName(baseName, currentId = "") {
23712374 return `${ name } ${ index } ` ;
23722375}
23732376
2377+ function uniqueProjectName ( baseName , currentId = "" ) {
2378+ const existing = new Set ( state . projects . filter ( ( project ) => project . id !== currentId ) . map ( ( project ) => project . name . trim ( ) ) ) ;
2379+ let name = baseName . trim ( ) || "未命名作品" ;
2380+ if ( ! existing . has ( name ) ) return name ;
2381+ let index = 2 ;
2382+ while ( existing . has ( `${ name } ${ index } ` ) ) index += 1 ;
2383+ return `${ name } ${ index } ` ;
2384+ }
2385+
23742386function hasSameName ( name , list , getName = ( item ) => item , currentId = "" ) {
23752387 const normalized = String ( name || "" ) . trim ( ) . toLowerCase ( ) ;
23762388 if ( ! normalized ) return false ;
@@ -3282,6 +3294,12 @@ function checkSharedStashFromUrl() {
32823294function attachPatternCopy ( project , templateId ) {
32833295 const template = state . patterns . find ( ( pattern ) => pattern . id === templateId ) || templatePatterns ( ) [ 0 ] ;
32843296 if ( ! template ) return "" ;
3297+ const currentPattern = state . patterns . find ( ( pattern ) => pattern . id === project . activePatternId ) ;
3298+ const sourcePattern = currentPattern ?. sourcePatternId
3299+ ? state . patterns . find ( ( pattern ) => pattern . id === currentPattern . sourcePatternId )
3300+ : currentPattern ;
3301+ const shouldAdoptName = ! project . name || / ^ 新 作 品 \s * \d + $ / . test ( project . name ) || ( sourcePattern ?. name && project . name === sourcePattern . name ) ;
3302+ const shouldAdoptType = ! project . type || project . type === ( state . projectTypes [ 0 ] || "作品" ) || ( sourcePattern ?. type && project . type === sourcePattern . type ) ;
32853303 if ( project . activePatternId ) {
32863304 state . patterns = state . patterns . filter ( ( pattern ) => pattern . id !== project . activePatternId || ! pattern . isProjectCopy ) ;
32873305 }
@@ -3292,6 +3310,8 @@ function attachPatternCopy(project, templateId) {
32923310 state . patterns . push ( copy ) ;
32933311 project . patternIds = [ copy . id ] ;
32943312 project . activePatternId = copy . id ;
3313+ if ( shouldAdoptName ) project . name = uniqueProjectName ( template . name , project . id ) ;
3314+ if ( shouldAdoptType ) project . type = template . type || project . type || state . projectTypes [ 0 ] || "作品" ;
32953315 project . yarnIds = Array . from ( new Set ( [ ...( project . yarnIds || [ ] ) , ...( copy . yarnIds || [ ] ) ] ) ) ;
32963316 project . supplyIds = Array . from ( new Set ( [ ...( project . supplyIds || [ ] ) , ...( copy . supplyIds || [ ] ) ] ) ) ;
32973317 project . toolIds = Array . from ( new Set ( [ ...( project . toolIds || [ ] ) , ...( copy . toolIds || [ ] ) ] ) ) ;
@@ -3514,9 +3534,6 @@ function renderTracking() {
35143534 const rows = expandedRows ( pattern ) ;
35153535 progress . completedRounds = Math . min ( rows . length , Math . max ( 0 , Number ( progress . completedRounds || 0 ) ) ) ;
35163536 progress . currentRound = clamp ( progress . currentRound , 1 , rows . length ) ;
3517- if ( progress . completedRounds < rows . length && progress . currentRound <= progress . completedRounds ) {
3518- progress . currentRound = progress . completedRounds + 1 ;
3519- }
35203537 const row = rows [ progress . currentRound - 1 ] ;
35213538 const stitches = rowStitches ( row ) ;
35223539 progress . currentStitch = clamp ( progress . currentStitch , 1 , stitches . length ) ;
@@ -4575,16 +4592,28 @@ function completeCurrentRound() {
45754592 }
45764593}
45774594
4578- function switchToNextPart ( ) {
4595+ function switchToPart ( partId ) {
45794596 const pattern = currentPattern ( ) ;
45804597 const rows = expandedRows ( pattern ) ;
4581- const progress = currentProgress ( ) ;
4582- const currentRow = rows [ progress . currentRound - 1 ] ;
4583- const partIds = rows . map ( ( row ) => row . partId ) . filter ( ( partId , index , list ) => partId && list . indexOf ( partId ) === index ) ;
4584- if ( ! partIds . length ) return ;
4585- const nextPartId = partIds [ ( partIds . indexOf ( currentRow ?. partId ) + 1 ) % partIds . length ] ;
4586- const rowIndex = rows . findIndex ( ( row ) => row . partId === nextPartId ) ;
4587- if ( rowIndex >= 0 ) updateProgress ( { currentRound : rowIndex + 1 , currentStitch : 1 } ) ;
4598+ const rowIndex = rows . findIndex ( ( row ) => row . partId === partId ) ;
4599+ if ( rowIndex < 0 ) return ;
4600+ updateProgress ( { currentRound : rowIndex + 1 , currentStitch : 1 } ) ;
4601+ }
4602+
4603+ function openTrackPartPicker ( ) {
4604+ const pattern = currentPattern ( ) ;
4605+ const project = currentProject ( ) ;
4606+ if ( ! pattern || ! els . trackPartModal || ! els . trackPartOptions ) return ;
4607+ const rows = expandedRows ( pattern ) ;
4608+ const currentRow = rows [ currentProgress ( ) . currentRound - 1 ] ;
4609+ const progressList = partProgressList ( project , pattern ) ;
4610+ els . trackPartOptions . innerHTML = progressList . map ( ( { part, done, total, percent } ) => `
4611+ <button class="part-switch-option ${ part . id === currentRow ?. partId ? "current" : "" } " data-switch-track-part="${ part . id } ">
4612+ <strong>${ escapeHtml ( part . name ) } </strong>
4613+ <span>${ done } /${ total } 段 · ${ percent } %</span>
4614+ </button>
4615+ ` ) . join ( "" ) ;
4616+ els . trackPartModal . classList . remove ( "hidden" ) ;
45884617}
45894618
45904619function clamp ( value , min , max ) {
@@ -5260,7 +5289,14 @@ els.completeRoundBtn.addEventListener("click", () => {
52605289 render ( ) ;
52615290 }
52625291} ) ;
5263- els . roundTitle . addEventListener ( "click" , switchToNextPart ) ;
5292+ els . roundTitle . addEventListener ( "click" , openTrackPartPicker ) ;
5293+ els . closeTrackPartModal ?. addEventListener ( "click" , ( ) => els . trackPartModal . classList . add ( "hidden" ) ) ;
5294+ els . trackPartOptions ?. addEventListener ( "click" , ( event ) => {
5295+ const partId = event . target . closest ( "[data-switch-track-part]" ) ?. dataset . switchTrackPart ;
5296+ if ( ! partId ) return ;
5297+ els . trackPartModal . classList . add ( "hidden" ) ;
5298+ switchToPart ( partId ) ;
5299+ } ) ;
52645300
52655301els . newPatternBtn . addEventListener ( "click" , ( ) => {
52665302 const baseName = "新織圖" ;
0 commit comments