33< head >
44 < meta charset ="UTF-8 ">
55 < meta name ="viewport " content ="width=device-width, initial-scale=1.0 ">
6- < title > 倪珮萱的自然拼读 Pro - V17 全功能版 </ title >
6+ < title > 自然拼读 Pro - 倪珮萱 </ title >
77 < script src ="https://cdnjs.cloudflare.com/ajax/libs/mammoth/1.4.21/mammoth.browser.min.js "> </ script >
88 < style >
99 : root {
3131 .step-indicators { display : flex; gap : 40px ; }
3232 .step-ind { font-size : 20px ; color : # ddd ; font-weight : bold; transition : 0.3s ; }
3333 .step-ind .active { color : var (--primary ); transform : scale (1.1 ); }
34- .stage { flex : 1 ; display : flex; flex-direction : column; align-items : center; justify-content : center; position : relative; }
35- .instruction { font-size : 32px ; color : # 444 ; margin-bottom : 40px ; font-weight : 600 ; }
34+
35+ /* 舞台布局:字在上,释义在下 */
36+ .stage { flex : 1 ; display : flex; flex-direction : column; align-items : center; justify-content : center; position : relative; gap : 40px ; }
37+ .instruction { font-size : 28px ; color : # 888 ; font-weight : 500 ; margin-top : 20px ; }
3638
37- /* 数据管理区样式 */
39+ /* 数据管理区 */
3840 .data-management { margin-top : 60px ; padding-top : 30px ; border-top : 2px dashed # e0e0e0 ; text-align : center; color : # 666 ; }
3941 .data-btn { background : transparent; border : 1px solid # ccc ; padding : 8px 20px ; border-radius : 20px ; cursor : pointer; margin : 0 10px ; font-size : 14px ; color : # 555 ; transition : all 0.2s ; }
4042 .data-btn : hover { border-color : var (--primary ); color : var (--primary ); background : white; }
6769 .ghost-input : not (: focus ) + .visual-layer .cursor { display : none; }
6870 @keyframes blink { 0% , 100% { opacity : 1 ; } 50% { opacity : 0 ; } }
6971 .rich-input-wrapper : focus-within { border-color : var (--primary ); box-shadow : 0 0 0 6px rgba (123 , 97 , 255 , 0.2 ); }
72+
73+ /* 绿色反馈 */
7074 .rich-input-wrapper .correct {
7175 border-color : var (--success ) !important ;
7276 background-color : var (--success-bg ) !important ;
@@ -98,6 +102,7 @@ <h1 style="text-align:center; color:#333;">📚 倪珮萱的自然拼读 Pro</h1
98102 < div class ="stat-card "> < span class ="stat-num " id ="stat-mistakes " style ="color:var(--danger) "> 0</ span > < br > 错题本</ div >
99103 </ div >
100104 < div style ="text-align:center; margin-bottom:20px; ">
105+ <!-- 修改默认值为 21 -->
101106 < label > 计划:< input type ="number " id ="plan-days " value ="21 " style ="width:50px;text-align:center " onchange ="App.saveConfig() "> 天</ label >
102107
103108 < select id ="learn-order "> < option value ="random "> 随机乱序</ option > < option value ="sequence "> 列表顺序</ option > </ select >
@@ -108,7 +113,7 @@ <h1 style="text-align:center; color:#333;">📚 倪珮萱的自然拼读 Pro</h1
108113 < button class ="menu-btn " style ="border:2px solid #ddd; background:white; " onclick ="App.switchView('import') "> 📂 导入新词</ button >
109114 </ div >
110115
111- <!-- 数据管理区 -->
116+ <!-- 数据管理 -->
112117 < div class ="data-management ">
113118 < h4 > 🛠️ 数据管理与备份</ h4 >
114119 < button class ="data-btn " onclick ="DataManager.exportData() "> ⬇️ 导出进度</ button >
@@ -151,12 +156,11 @@ <h2 style="text-align:center">导入新单词</h2>
151156 </ div >
152157
153158 < script >
154- // 简易词典
155159 const DICT = { "apple" :"苹果" , "banana" :"香蕉" , "cat" :"猫" , "dog" :"狗" , "elephant" :"大象" , "fish" :"鱼" , "girl" :"女孩" , "hello" :"你好" , "ice" :"冰" , "juice" :"果汁" , "kite" :"风筝" , "lion" :"狮子" , "monkey" :"猴子" , "nose" :"鼻子" , "orange" :"橙子" , "pig" :"猪" , "queen" :"女王" , "rabbit" :"兔子" , "sun" :"太阳" , "tiger" :"老虎" , "umbrella" :"雨伞" , "van" :"货车" , "water" :"水" , "box" :"盒子" , "yellow" :"黄色" , "zoo" :"动物园" , "welcome" :"欢迎" , "student" :"学生" , "teacher" :"老师" , "school" :"学校" , "pizza" :"披萨" , "hamburger" :"汉堡" , "computer" :"电脑" , "friend" :"朋友" } ;
156160
157161 const DB = {
158- key : 'phonics_pro_v17_full ' ,
159- data : { lib : [ ] , config : { planDays : 7 } } ,
162+ key : 'phonics_pro_v17_21days ' ,
163+ data : { lib : [ ] , config : { planDays : 21 } } , // 修改默认值为 21
160164 load ( ) { const r = localStorage . getItem ( this . key ) ; if ( r ) this . data = JSON . parse ( r ) ; } ,
161165 save ( ) { localStorage . setItem ( this . key , JSON . stringify ( this . data ) ) ; App . updateUI ( ) ; } ,
162166 add ( list ) {
@@ -173,9 +177,7 @@ <h2 style="text-align:center">导入新单词</h2>
173177 split ( w ) { return w . length <= 4 ? [ w ] : ( w . toLowerCase ( ) . match ( / [ ^ a e i o u y ] * [ a e i o u y ] + (?: [ ^ a e i o u y ] * $ | [ ^ a e i o u y ] (? = [ ^ a e i o u y ] ) ) ? / gi) || [ w ] ) ; }
174178 } ;
175179
176- // ==================== 数据管理 (备份/恢复/重置) ====================
177180 const DataManager = {
178- // 导出
179181 exportData ( ) {
180182 const dataStr = JSON . stringify ( DB . data ) ;
181183 const blob = new Blob ( [ dataStr ] , { type : "application/json" } ) ;
@@ -186,7 +188,6 @@ <h2 style="text-align:center">导入新单词</h2>
186188 a . click ( ) ;
187189 URL . revokeObjectURL ( url ) ;
188190 } ,
189- // 导入
190191 importData ( file ) {
191192 if ( ! file ) return ;
192193 const reader = new FileReader ( ) ;
@@ -197,23 +198,17 @@ <h2 style="text-align:center">导入新单词</h2>
197198 DB . data = newData ;
198199 DB . save ( ) ;
199200 alert ( "✅ 进度恢复成功!" ) ;
200- } else {
201- alert ( "❌ 文件格式错误,非本程序备份文件。" ) ;
202- }
203- } catch ( err ) {
204- alert ( "❌ 读取失败,文件可能损坏。" ) ;
205- }
206- document . getElementById ( 'backup-input' ) . value = '' ; // 重置输入框
201+ } else { alert ( "❌ 文件格式错误" ) ; }
202+ } catch ( err ) { alert ( "❌ 读取失败" ) ; }
203+ document . getElementById ( 'backup-input' ) . value = '' ;
207204 } ;
208205 reader . readAsText ( file ) ;
209206 } ,
210- // 重置
211207 resetData ( ) {
212- const confirmMsg = "⚠️ 严重警告:\n\n即将清空所有学习记录和单词库!此操作不可撤销。\n\n建议先点击【⬇️ 导出进度】进行备份。\n\n确定要重置吗?" ;
213- if ( confirm ( confirmMsg ) ) {
208+ if ( confirm ( "⚠️ 警告:即清空所有数据!建议先【导出进度】。\n\n确定要重置吗?" ) ) {
214209 if ( confirm ( "再次确认:真的要清空吗?" ) ) {
215210 localStorage . removeItem ( DB . key ) ;
216- location . reload ( ) ; // 刷新页面重置
211+ location . reload ( ) ;
217212 }
218213 }
219214 }
0 commit comments