1515
1616 </div >
1717 </div >
18+ <v-slide-y-transition >
19+ <div v-if =" fetched && hasUnsavedChanges" class =" unsaved-changes-banner-wrap" >
20+ <v-banner
21+ icon =" $warning"
22+ lines =" one"
23+ class =" unsaved-changes-banner my-4"
24+ >
25+ {{ tm('messages.unsavedChangesNotice') }}
26+ </v-banner >
27+ </div >
28+ </v-slide-y-transition >
1829 <!-- <v-progress-linear v-if="!fetched" indeterminate color="primary"></v-progress-linear> -->
1930
2031 <v-slide-y-transition mode =" out-in" >
@@ -235,6 +246,12 @@ export default {
235246 });
236247 return items;
237248 },
249+ hasUnsavedChanges () {
250+ if (! this .fetched ) {
251+ return false ;
252+ }
253+ return this .getConfigSnapshot (this .config_data ) !== this .lastSavedConfigSnapshot ;
254+ }
238255 },
239256 watch: {
240257 config_data_str (val ) {
@@ -269,6 +286,7 @@ export default {
269286 save_message: " " ,
270287 save_message_success: " " ,
271288 configContentKey: 0 ,
289+ lastSavedConfigSnapshot: ' ' ,
272290
273291 // 配置类型切换
274292 configType: ' normal' , // 'normal' 或 'system'
@@ -383,6 +401,7 @@ export default {
383401 params: params
384402 }).then ((res ) => {
385403 this .config_data = res .data .data .config ;
404+ this .lastSavedConfigSnapshot = this .getConfigSnapshot (this .config_data );
386405 this .fetched = true
387406 this .metadata = res .data .data .metadata ;
388407 this .configContentKey += 1 ;
@@ -407,6 +426,7 @@ export default {
407426
408427 axios .post (' /api/config/astrbot/update' , postData).then ((res ) => {
409428 if (res .data .status === " ok" ) {
429+ this .lastSavedConfigSnapshot = this .getConfigSnapshot (this .config_data );
410430 this .save_message = res .data .message || this .messages .saveSuccess ;
411431 this .save_message_snack = true ;
412432 this .save_message_success = " success" ;
@@ -601,6 +621,9 @@ export default {
601621 closeTestChat () {
602622 this .testChatDrawer = false ;
603623 this .testConfigId = null ;
624+ },
625+ getConfigSnapshot (config ) {
626+ return JSON .stringify (config ?? {});
604627 }
605628 },
606629}
@@ -612,6 +635,26 @@ export default {
612635 text- transform: none ! important;
613636}
614637
638+ .unsaved - changes- banner {
639+ border- radius: 8px ;
640+ }
641+
642+ .v - theme-- light .unsaved - changes- banner {
643+ background- color: #f1f4f9 ! important;
644+ }
645+
646+ .v - theme-- dark .unsaved - changes- banner {
647+ background- color: #2d2d2d ! important;
648+ }
649+
650+ .unsaved - changes- banner- wrap {
651+ position: sticky;
652+ top: calc (var (-- v- layout- top, 64px ));
653+ z- index: 20 ;
654+ width: 100 % ;
655+ margin- bottom: 6px ;
656+ }
657+
615658/* 按钮切换样式优化 */
616659.v - btn- toggle .v - btn {
617660 transition: all 0 .3s ease ! important;
0 commit comments