Bläddra i källkod

add delete plan

wup55 1 vecka sedan
förälder
incheckning
b600ef6999
4 ändrade filer med 250 tillägg och 5 borttagningar
  1. 6 0
      src/app/tab2/tab2.page.html
  2. 161 1
      src/app/tab2/tab2.page.scss
  3. 81 4
      src/app/tab2/tab2.page.ts
  4. 2 0
      src/lib/ncloud.ts

+ 6 - 0
src/app/tab2/tab2.page.html

@@ -117,6 +117,12 @@
         <ion-badge slot="end" class="days-badge" [color]="item.remaining < 5 ? 'danger' : 'success'">
           {{item.remaining}}天
         </ion-badge>
+
+        <ion-buttons slot="end">
+          <ion-button (click)="confirmDelete($event, item)" fill="clear" class="delete-btn">
+            <ion-icon name="trash-outline" slot="icon-only" class="delete-icon"></ion-icon>
+          </ion-button>
+        </ion-buttons>
       </ion-item>
     </ion-list>
 

+ 161 - 1
src/app/tab2/tab2.page.scss

@@ -525,4 +525,164 @@ ion-content.content-bg {
     --background: #e74c3c;
     --color: white;
   }
-}
+}
+
+/* 删除按钮样式 */
+.delete-btn {
+  --padding-start: 8px;
+  --padding-end: 8px;
+  
+  .delete-icon {
+    font-size: 1.25rem;
+    transition: all 0.3s ease;
+    color: #666;
+  }
+  
+  &:hover {
+    .delete-icon {
+      color: #e74c3c;
+      transform: scale(1.1);
+    }
+  }
+  
+  &:active {
+    .delete-icon {
+      transform: scale(0.9);
+    }
+  }
+}
+
+/* 确认删除弹窗样式 */
+.delete-confirm-alert {
+  --backdrop-opacity: 0.7;
+  
+  .alert-wrapper {
+    border-radius: 16px;
+    background: linear-gradient(to bottom, #fff, #f8f9fa);
+    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
+    border: 1px solid #e0e0e0;
+    overflow: hidden;
+  }
+  
+  .alert-head {
+    background: linear-gradient(to right, #e74c3c, #c0392b);
+    color: white;
+    padding: 15px 16px;
+    
+    .alert-title {
+      font-size: 1.3rem;
+      font-weight: 600;
+    }
+  }
+  
+  .alert-message {
+    padding: 20px 16px;
+    color: #444;
+    font-size: 1rem;
+    line-height: 1.5;
+  }
+  
+  .alert-button-group {
+    padding: 10px 16px 16px;
+    flex-direction: row-reverse;
+    justify-content: flex-start;
+    
+    button:last-child {
+      margin-right: 10px;
+    }
+  }
+  
+  .cancel-btn {
+    --background: #f1f2f6;
+    --background-hover: #e0e0e0;
+    --color: #444;
+    --background-activated: #e0e0e0;
+    border-radius: 50px;
+    padding: 12px 20px;
+    margin: 0;
+  }
+  
+  .delete-btn {
+    --background: linear-gradient(to right, #e74c3c, #c0392b);
+    --background-activated: rgba(231, 76, 60, 0.9);
+    --color: white;
+    border-radius: 50px;
+    padding: 12px 20px;
+    margin: 0;
+    box-shadow: 0 3px 8px rgba(192, 57, 43, 0.3);
+  }
+}
+
+/* 删除加载中提示 */
+.deleting-alert {
+  .alert-wrapper {
+    background: transparent;
+    box-shadow: none;
+  }
+  
+  .alert-message {
+    color: white;
+    text-align: center;
+    font-size: 1.1rem;
+    background: rgba(231, 76, 60, 0.8);
+    border-radius: 50px;
+    padding: 15px 20px;
+  }
+}
+
+/* 删除成功提示 */
+.delete-success-toast {
+  --backdrop-opacity: 0;
+  
+  .alert-wrapper {
+    background: linear-gradient(to right, #27ae60, #2ecc71);
+    color: white;
+    border-radius: 50px;
+    padding: 12px 24px;
+    max-width: 300px;
+    box-shadow: 0 4px 12px rgba(46, 204, 113, 0.3);
+  }
+  
+  .alert-message {
+    font-size: 1.1rem;
+    font-weight: 500;
+  }
+}
+/* 删除成功提示 */
+.delete-success-toast {
+  --background: linear-gradient(to right, #27ae60, #2ecc71);
+  --color: white;
+  --border-radius: 50px;
+  --box-shadow: 0 4px 12px rgba(46, 204, 113, 0.3);
+  --height: auto;
+  padding: 12px 24px;
+  font-weight: 500;
+}
+
+/* 删除错误提示 */
+.delete-error-alert {
+  .alert-wrapper {
+    border-radius: 16px;
+    background: white;
+    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
+    overflow: hidden;
+  }
+  
+  .alert-head {
+    background: linear-gradient(to right, #e74c3c, #c0392b);
+    color: white;
+    padding: 15px 16px;
+    
+    .alert-title {
+      font-size: 1.3rem;
+      font-weight: 600;
+    }
+  }
+  
+  .alert-message {
+    padding: 20px 16px;
+    color: #444;
+    font-size: 1rem;
+    line-height: 1.5;
+  }
+}

+ 81 - 4
src/app/tab2/tab2.page.ts

@@ -11,14 +11,13 @@ import { addIcons } from 'ionicons';
 import {
   notificationsOutline, calendarNumber, checkmarkCircle, ellipseOutline,
   timeOutline, barbell, body, walk, add, refresh, fitness,
-  flame, bicycle, trophy, ellipsisHorizontal, footsteps, footstepsOutline, chatbubbleEllipses, barChartOutline, calendarClearOutline, star, checkmarkCircleOutline } from 'ionicons/icons';
+  flame, bicycle, trophy, ellipsisHorizontal, footsteps, footstepsOutline, chatbubbleEllipses, barChartOutline, calendarClearOutline, star, checkmarkCircleOutline, trashOutline } from 'ionicons/icons';
 
 // 引用fmode-ng智能体组件
 import { ChatPanelOptions, FmodeChat, FmodeChatMessage, openChatPanelModal } from 'fmode-ng';
 import Parse from "parse";
 import { CloudObject, CloudQuery, CloudUser } from 'src/lib/ncloud';
-
-
+import { AlertController,ToastController } from '@ionic/angular';
 // 导入计划创建模态框组件
 import { PlanCreationModalComponent } from './plan-creation-modal.component';
 
@@ -26,6 +25,7 @@ import { PlanCreationModalComponent } from './plan-creation-modal.component';
   selector: 'app-tab2',
   templateUrl: 'tab2.page.html',
   styleUrls: ['tab2.page.scss'],
+  providers: [AlertController],
   standalone: true,
   imports: [
     CommonModule,
@@ -148,8 +148,10 @@ export class Tab2Page {
 
   constructor(
     private modalCtrl: ModalController,
+    private alertCtrl: AlertController,
+    private toastCtrl: ToastController
   ) {
-    addIcons({notificationsOutline,calendarNumber,refresh,barChartOutline,timeOutline,footsteps,calendarClearOutline,add,star,checkmarkCircleOutline,chatbubbleEllipses,checkmarkCircle,ellipseOutline,barbell,body,walk,fitness,flame,bicycle,trophy,ellipsisHorizontal,footstepsOutline});
+    addIcons({notificationsOutline,calendarNumber,refresh,barChartOutline,timeOutline,footsteps,trashOutline,calendarClearOutline,add,star,checkmarkCircleOutline,chatbubbleEllipses,checkmarkCircle,ellipseOutline,barbell,body,walk,fitness,flame,bicycle,trophy,ellipsisHorizontal,footstepsOutline});
     
     // 初始化周数据
     this.weekDays = this.generateWeekDays();
@@ -272,6 +274,81 @@ export class Tab2Page {
     }
   }
 
+  async confirmDelete(event: Event, plan: any) {
+    event.stopPropagation(); // 阻止事件冒泡
+    
+    const alert = await this.alertCtrl.create({
+      header: '确认删除',
+      message: `确定要删除「${plan.name}」训练计划吗?此操作不可撤销!`,
+      cssClass: 'delete-confirm-alert',
+      buttons: [
+        {
+          text: '取消',
+          role: 'cancel',
+          cssClass: 'cancel-btn'
+        },
+        {
+          text: '删除',
+          cssClass: 'delete-btn',
+          handler: () => {
+            this.deletePlan(plan);
+          }
+        }
+      ]
+    });
+    
+    await alert.present();
+  }
+
+  async deletePlan(plan: any) {
+    try {
+      // 创建CloudObject实例
+      const planObj = new CloudObject('TrainingPlan');
+      planObj.id = plan.id;
+      
+      // 显示加载状态
+      const loadingAlert = await this.alertCtrl.create({
+        message: '正在删除计划...',
+        backdropDismiss: false,
+        cssClass: 'deleting-alert'
+      });
+      await loadingAlert.present();
+      
+      // 调用destroy方法删除计划
+      const success = await planObj.destroy();
+      
+      // 关闭加载提示
+      await loadingAlert.dismiss();
+      
+      if (success) {
+        // 更新前端列表
+        this.myPlans = this.myPlans.filter(p => p.id !== plan.id);
+        
+        // 使用 Toast 显示成功消息(支持 duration)
+        const toast = await this.toastCtrl.create({
+          message: '计划已成功删除!',
+          duration: 2000,
+          cssClass: 'delete-success-toast',
+          position: 'top'
+        });
+        await toast.present();
+      } else {
+        throw new Error('删除失败');
+      }
+    } catch (error: any) {
+      console.error('删除计划时出错:', error);
+      
+      // 显示错误提示
+      const errorAlert = await this.alertCtrl.create({
+        header: '删除失败',
+        message: error.message || '计划删除失败,请稍后重试',
+        buttons: ['确定'],
+        cssClass: 'delete-error-alert'
+      });
+      await errorAlert.present();
+    }
+  }
+
   async loadPlanTasks(planId: string) {
     const query = new CloudQuery('TrainingTask');
     query.equalTo('plan', planId);

+ 2 - 0
src/lib/ncloud.ts

@@ -83,6 +83,8 @@ export class CloudObject {
         }
         return true;
     }
+
+    
 }
 
 // CloudQuery.ts