فهرست منبع

- 修改 app.routes.ts 和其他页面路由配置
- 更新 daily-content、poem-detail、tab1、tab2、tab3 页面的内容和样式
- 删除不再使用的 login 组件
- 新增和重命名了一些图片资源
- 修改 ncloud.ts 文件

危齐晟 3 ماه پیش
والد
کامیت
9bff821c01

+ 2 - 6
poem-life-app/src/app/app.routes.ts

@@ -19,15 +19,11 @@ export const routes: Routes = [
   },
 
   {
-    path: 'book-management/:id',  // 添加动态参数 :id
+    path: 'book-management',
     loadComponent: () => import('./book-management/book-management.page').then(m => m.BookManagementPage)
   },
   {
-    path: 'poem-detail/:id',  // 添加动态参数 :id
+    path: 'poem-detail',
     loadComponent: () => import('./poem-detail/poem-detail.page').then(m => m.PoemDetailPage)
   },
-  // {
-  //   path: 'login',  // 添加 login 页面路径
-  //   loadComponent: () => import('./login/login.component').then(m => m.LoginComponent)
-  // },
 ];

+ 9 - 6
poem-life-app/src/app/daily-content/daily-content.page.html

@@ -18,15 +18,18 @@
   </ion-toolbar>
 </ion-header>
 
-
 <ion-content>
   <div class="daily-content-wrapper">
-    <div class="daily-item" *ngFor="let item of dailyItems">
-      <img [src]="item.image" alt="{{ item.title }}" class="daily-image" *ngIf="item.image">
-      <h3>{{ item.date }}</h3>
-      <h4>{{ item.title }}</h4>
-      <p>{{ item.snippet }}</p>
+    <div class="daily-item" *ngFor="let content of PLContentsList">
+        <p>{{ content.get('type') }}</p>
+        <h1 style="text-align: center;">{{ content.get('title') }}</h1>
+        <img [src]="content.get('image')" alt="{{ content.get('title') }}" class="card-image">
+        <h4 style="text-align: center;">{{ content.get('snippet') }}</h4>
+        <p style="text-align: center;">{{ content.get('time') }} ---- {{ content.get('editor') }}</p>
     </div>
   </div>
 </ion-content>
 
+<!-- <ng-container *ngIf="content.get('type') === '图文'"> -->
+<!-- </ng-container> -->
+

+ 14 - 39
poem-life-app/src/app/daily-content/daily-content.page.ts

@@ -5,6 +5,7 @@ import { IonHeader, IonToolbar, IonTitle, IonContent,IonButtons, IonButton, IonI
 import { Router } from '@angular/router';
 import { addIcons } from 'ionicons';
 import { calendar } from 'ionicons/icons';
+import { CloudObject, CloudQuery } from 'src/lib/ncloud';
 @Component({
   selector: 'app-daily-content',
   templateUrl: './daily-content.page.html',
@@ -12,47 +13,21 @@ import { calendar } from 'ionicons/icons';
   standalone: true,
   imports: [FormsModule,CommonModule,IonHeader, IonToolbar, IonTitle, IonContent,IonButtons, IonButton,IonDatetime, IonIcon],
 })
+
 export class DailyContentPage implements OnInit {
-  dailyItems = [
-    {
-      date: '2024-11-30',
-      title: '清平调',
-      snippet: '云想衣裳花想容,春风拂槛露华浓。若非群玉山头见,会向瑶台月下逢。.',
-      image: '../assets/image/01/Vx_03.jpg'
-    },
-    {
-      date: '2024-11-29',
-      title: '纯诗歌内容(内带详细注解)',
-      snippet: '床前明月光,疑是地上霜...',
-      image: ''
-    },
-    {
-      date: '2024-11-28',
-      title: '纯诗歌内容(内带详细注解)',
-      snippet: '床前明月光,疑是地上霜...',
-      image: ''
-    },
-    {
-      date: '2024-11-27',
-      title: '纯诗歌内容(内带详细注解)',
-      snippet: '床前明月光,疑是地上霜...',
-      image: ''
-    },
-    {
-      date: '2024-11-26',
-      title: '纯诗歌内容(内带详细注解)',
-      snippet: '床前明月光,疑是地上霜...',
-      image: ''
-    },
-    {
-      date: '2024-11-25',
-      title: '纯诗歌内容(内带详细注解)',
-      snippet: '床前明月光,疑是地上霜...',
-      image: ''
-    },
-    // 更多内容...
-  ];
+
   ngOnInit() {
+    // 生命周期:页面加载后,运行医生列表加载函数
+    this.loadPLContentsList();
+  }
+
+  // 创建用于数据列表存储的属性
+  PLContentsList:Array<CloudObject> = []
+
+  async loadPLContentsList(){
+    let query = new CloudQuery("PL_Contents");
+    query.equalTo('type', '图文'); // 添加查询条件来限制 type="图文"
+    this.PLContentsList = await query.find() //限制查询条件为type="图文"
   }
   constructor(private router:Router) {
     addIcons({calendar});

+ 0 - 80
poem-life-app/src/app/login/login.component.ts

@@ -1,80 +0,0 @@
-// src/app/login/login.component.ts
-import { Component } from '@angular/core';
-import { Router } from '@angular/router'; // 导入 Router 模块
-import { IonicModule, IonContent, IonHeader, IonToolbar, IonButtons, IonMenuButton, IonButton, IonIcon, IonLabel, IonInput, IonItem,  } from '@ionic/angular';
-import { FormsModule } from '@angular/forms'; // 导入 FormsModule
-import { CloudUser } from 'src/lib/ncloud';
-import { openUserLoginModal } from 'src/lib/user/modal-user-login/modal-user-login.component';
-import { openUserEditModal } from 'src/lib/user/modal-user-edit/modal-user-edit.component';
-import { addIcons } from 'ionicons';
-import { folderOutline, timeOutline, starOutline, heartOutline, chevronForwardOutline, personOutline, shieldOutline, callOutline, lockClosedOutline } from 'ionicons/icons';
-import { ModalController } from '@ionic/angular/standalone';
-import { AlertController } from '@ionic/angular/standalone'; // 导入所需的模块
-
-@Component({
-  selector: 'app-login',
-  templateUrl: './login.component.html',
-  styleUrls: ['./login.component.scss'],
-  standalone: true,
-  imports: [IonicModule, FormsModule], // 确保导入 FormsModule
-})
-export class LoginComponent {
-  username: string = '';
-  password: string = '';
-  currentUser: CloudUser | undefined;
-  isRegistered: boolean = false;
-  showLoginForm: boolean = false;
-
-  constructor(
-    private router: Router,
-    private alertController: AlertController,
-    private modalCtrl: ModalController
-  ) {
-    addIcons({ folderOutline, timeOutline, starOutline, heartOutline, chevronForwardOutline, personOutline, shieldOutline, callOutline, lockClosedOutline });
-    this.currentUser = new CloudUser();
-  }
-
-  async onSubmit() {
-    // 处理登录逻辑
-    console.log('Username:', this.username);
-    console.log('Password:', this.password);
-
-    // 示例:成功登录后导航到主页或其他页面
-    if (this.username && this.password) {
-      // 这里可以添加实际的登录验证逻辑
-      this.currentUser = new CloudUser(); // 假设登录成功
-      this.router.navigate(['/tab3']); // 假设主页面是 tabs/tab3
-    }
-  }
-
-  async login() {
-    // 弹出登录窗口
-    let user = await openUserLoginModal(this.modalCtrl);
-    if (user?.id) {
-      this.currentUser = user;
-      this.showLoginForm = false; // 关闭登录表单
-      this.router.navigate(['/tabs/tab3']);
-    }
-  }
-
-  async signup() {
-    // 弹出注册窗口
-    let user = await openUserLoginModal(this.modalCtrl, "signup");
-    if (user?.id) {
-      this.isRegistered = true; // 设置注册状态为已注册
-      this.currentUser = user;
-      this.showLoginForm = false; // 关闭登录表单
-    }
-  }
-
-  logout() {
-    this.currentUser?.logout();
-    this.isRegistered = false; // 设置注册状态为未注册
-    this.showLoginForm = false; // 关闭登录表单
-  }
-
-
-  toggleLoginForm(show: boolean) {
-    this.showLoginForm = show;
-  }
-}

+ 23 - 8
poem-life-app/src/app/poem-detail/poem-detail.page.html

@@ -3,7 +3,7 @@
     <ion-buttons slot="start">
       <ion-back-button (click)="goBack()"></ion-back-button>
     </ion-buttons>
-    <ion-title>{{ poemTitle || '诗词详情' }}</ion-title>
+    <ion-title>{{ poem?.get('title') || '诗词详情' }}</ion-title>
   </ion-toolbar>
 </ion-header>
 
@@ -11,14 +11,29 @@
 <div class="background"></div>
 
 <!-- 内容层 -->
-<ion-content>
-  <div class="content-wrapper">
-    <div *ngIf="poemTitle !== null && poemContent !== null" class="poem-content">
-      <!-- <h1>{{ poemTitle }}</h1> -->
-      <pre>{{ poemContent }}</pre>
+<ion-content class="content-container">
+  <div *ngIf="loading" class="loading">
+    <p>加载中...</p>
+  </div>
+  <div *ngIf="error" class="error">
+    <p>{{ error }}</p>
+  </div>
+  <div *ngIf="poem" class="content-detail">
+    <div class="issue-time">
+      <span class="issue">{{ poem.get('title') }}</span>
+      <span class="time">{{ poem.get('theme') }}</span>
     </div>
-    <div *ngIf="poemTitle === null || poemContent === null" class="loading-message">
-      <p>加载中...</p>
+    <h2 class="title">{{ poem.get('creation_time') }}</h2>
+    <h3 class="editor">{{ poem.get('autor') }}</h3>
+    <div class="content-text">
+      {{ poem.get('content') }}
     </div>
+    <p>{{poem.get('emotion')}}</p>
+    <p>{{poem.get('background')}}</p>
+    <p>{{poem.get('sumary')}}</p>
+    <p>{{poem.get('tags')}}</p>
+    <p>{{poem.get('translation')}}</p>
+    <p>{{poem.get('language')}}</p>
+    <p>{{poem.get('emotion')}}</p>
   </div>
 </ion-content>

+ 42 - 95
poem-life-app/src/app/poem-detail/poem-detail.page.ts

@@ -3,8 +3,7 @@ import { ActivatedRoute, Router } from '@angular/router';
 import { HttpClient } from '@angular/common/http';
 import { CommonModule } from '@angular/common';
 import { IonicModule } from '@ionic/angular';
-import { forkJoin } from 'rxjs';
-
+import { CloudObject, CloudQuery } from 'src/lib/ncloud';
 
 
 @Component({
@@ -15,108 +14,56 @@ import { forkJoin } from 'rxjs';
   imports: [CommonModule, IonicModule]
 })
 export class PoemDetailPage implements OnInit {
-  bookId: number | null = null; // 初始化为 null
-  poemId: number | null = null; // 初始化为 null
-  poemContent: string | null = null; // 初始化为 null
-  poemTitle: string | null = null;
-  title: string | null = null;
-  private baseUrl = 'http://localhost:3000/api'; // 后端 API 基础 URL
 
-  constructor(private route: ActivatedRoute, private http: HttpClient, private router: Router) {
-  }
+poem: CloudObject | null = null; // 用于存储当前内容的数据
+error: string | null = null; // 添加错误状态
+loading: boolean = true; // 添加加载状态
+poemsList: CloudObject[] = [];
+constructor(private activatedRoute: ActivatedRoute, private router: Router) { }
 
 
   ngOnInit() {
-   // 订阅路由参数,以获取传递的诗词ID和书籍ID
-   this.route.params.subscribe(params => {
-    this.poemId = +params['id']; // 获取传递的诗词ID
-    if (this.poemId) {
-      // this.getPoemContent(this.poemId); // 获取诗词内容
-      // this.getPoemTitle(this.poemId);
-      this.loadPoemDetails(this.poemId);
+    const id = this.activatedRoute.snapshot.queryParamMap.get('id');
+    if (id) {
+      this.loadPoemById(id);
+    } else {
+      this.error = '内容ID未找到';
+      this.loading = false;
     }
-
-    // 获取传递的书籍ID(假设书籍ID通过其他方式传递)
-    const bookIdParam = this.route.snapshot.queryParamMap.get('bookId');
-    // const bookIdParam = params['bookId'];
-    if (bookIdParam) {
-      this.bookId = +bookIdParam;
-    }
-  });
-  }
-
-
-  loadPoemDetails(poemId: number) {
-    // 合并诗词标题和内容的请求
-    forkJoin([
-      this.http.get<{ id: number; book_id: number; author_id: number; genre_id: number; title: string }>(`${this.baseUrl}/poems/${poemId}`),
-      this.http.get<{ content: string }>(`${this.baseUrl}/poem-contents/${poemId}`)
-    ]).subscribe(
-      ([poemData, content]) => {
-        console.log('Received poem data:', poemData); // 添加日志
-        console.log('Received content:', content); // 添加日志
-        this.poemTitle = poemData.title ;
-        this.title = this.poemTitle; // 设置页面标题
-        this.poemContent = content.content || '加载失败或无内容';
-      },
-      error => {
-        console.error('Error fetching poem details', error);
-      }
-    );
   }
-
-    // 返回逻辑
-    goBack() {
-      if (this.bookId !== null) {
-        this.router.navigate(['book-management', this.bookId]); // 导航到对应类型的书籍管理页面
+  async loadPoemById(id: string) {
+    try {
+      let query = new CloudQuery("PL_Poems");
+      query.equalTo('objectId', id); // 根据 ID 查询内容
+      const results = await query.find();
+      console.log('Loaded poem:', results);
+      if (results.length > 0) {
+        this.poem = results[0];
+        if (this.poem) {
+          await this.loadPoemsList(this.poem.get('title')); // 加载内容列表
+        }
       } else {
-        console.error('Book ID is not set');
+        this.error = '内容未找到';
       }
+    } catch (err) {
+      this.error = '加载内容时出错';
+      console.error(err);
+    } finally {
+      this.loading = false;
     }
   }
 
-  
-  // loadPoemDetails(poemId: number) {
-  //   // 获取诗词标题
-  //   const id = poemId;
-  //   this.http.get<{ title: string }>(`${this.baseUrl}/poems/${id}`).subscribe(
-  //     data => {
-  //       this.poemTitle = data.title || '未知标题'; // 设置默认值以防为空
-  //       this.title = this.poemTitle; // 设置页面标题
-  //     },
-  //     error => {
-  //       console.error('Error fetching poem title', error);
-  //     }
-  //   );
-
-  //   // 获取诗词内容
-  //   this.http.get<{ content: string }>(`${this.baseUrl}/poem-contents/${poemId}`).subscribe(
-  //     data => {
-  //       this.poemContent = data.content || '加载失败或无内容'; // 设置默认值以防为空
-  //     },
-  //     error => {
-  //       console.error('Error fetching poem content', error);
-  //     }
-  //   );
-  // }
-
-
-  // getPoemTitle(poemId: number) {
-  //   // const id = poemId;
-  //   this.http.get<{ title: string }>(`${this.baseUrl}/poems/${poemId}`).subscribe(data => {
-  //     this.poemTitle = data.title; // 保存诗词标题
-  //   }, error => {
-  //     console.error('Error fetching poem title', error);
-  //   });
-  // }
-  // // 获取诗词内容
-  // getPoemContent(poemId: number) {
-  //   this.http.get<{ content: string }>(`${this.baseUrl}/poem-contents/${poemId}`).subscribe(data => {
-  //     this.poemContent = data.content; // 保存诗词内容
-  //   }, error => {
-  //     console.error('Error fetching poem content', error);
-  //   });
-  // }
-
-
+  async loadPoemsList(type: string) {
+    try {
+      let query = new CloudQuery("PL_Poems");
+      this.poemsList = await query.find();
+      console.log('Loaded contents list:', this.poemsList);
+    } catch (err) {
+      console.error('加载内容列表时出错:', err);
+    }
+  }
 
+    goBack() {
+      this.router.navigate(['/tabs/tab2']);
+    }
+}

+ 24 - 27
poem-life-app/src/app/tab1/card-detail/card-detail.page.html

@@ -3,41 +3,38 @@
     <ion-buttons slot="start">
       <ion-back-button defaultHref="/tabs/tab1"></ion-back-button>
     </ion-buttons>
-    <ion-title>{{ content.title }}</ion-title>
+    <ion-title style="text-align: center;">{{ content?.get('type') }}</ion-title>
   </ion-toolbar>
 </ion-header>
 
-<ion-content>
-  <h2>{{ content.title }}</h2>
-  <h3>编者: {{ content.editor }}</h3>
-  <p>{{ content.detail }}</p>
-  <p>日期: {{ content.date }} - {{ content.issue }}</p>
-
-  <ion-list>
-    <ion-item *ngFor="let image of content.images">
-      <ion-thumbnail slot="start">
-        <img [src]="image" />
-      </ion-thumbnail>
-    </ion-item>
-
-    <ion-item *ngIf="content.video">
-      <video controls [src]="content.video"></video>
-    </ion-item>
-
-    <ion-item *ngIf="content.audio">
-      <audio controls [src]="content.audio"></audio>
-    </ion-item>
-  </ion-list>
+<ion-content class="content-container">
+  <div *ngIf="loading" class="loading">
+    <p>加载中...</p>
+  </div>
+  <div *ngIf="error" class="error">
+    <p>{{ error }}</p>
+  </div>
+  <div *ngIf="content" class="content-detail">
+    <div class="issue-time">
+      <span class="issue">{{ content.get('issue') }}</span>
+      <span class="time">{{ content.get('time') }}</span>
+    </div>
+    <h2 class="title">{{ content.get('title') }}</h2>
+    <h3 class="editor">{{ content.get('editor') }}</h3>
+    <img [src]="content.get('image')" class="content-image" />
+    <div class="content-text">
+      {{ content.get('detail') }}
+    </div>
+  </div>
 </ion-content>
 
 <ion-footer>
   <ion-toolbar>
-    <ion-buttons slot="start" (click)="prevContent()">
-      <ion-button>前一期</ion-button>
+    <ion-buttons slot="start">
+      <ion-button  (click)="prevContent()">前一期</ion-button>
     </ion-buttons>
-    <ion-buttons slot="end" (click)="nextContent()">
-      <ion-button>后一期</ion-button>
+    <ion-buttons slot="end">
+      <ion-button  (click)="nextContent()">后一期</ion-button>
     </ion-buttons>
   </ion-toolbar>
 </ion-footer>
-

+ 49 - 0
poem-life-app/src/app/tab1/card-detail/card-detail.page.scss

@@ -0,0 +1,49 @@
+.content-container {
+  padding: 16px;
+}
+
+.loading, .error {
+  text-align: center;
+  margin-top: 20px;
+}
+
+.content-detail {
+  background-color: #f9f9f9;
+  padding: 16px;
+  border-radius: 8px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.issue-time {
+  display: flex;
+  justify-content: space-between;
+  margin-bottom: 16px;
+}
+
+.issue, .time {
+  font-size: 14px;
+  color: #666;
+}
+
+.title {
+  font-size: 24px;
+  margin-bottom: 16px;
+}
+
+.editor {
+  font-size: 18px;
+  color: #333;
+  margin-bottom: 16px;
+}
+
+.content-image {
+  width: 100%;
+  height: auto;
+  border-radius: 8px;
+  margin-bottom: 16px;
+}
+
+.content-text {
+  font-size: 16px;
+  line-height: 1.5;
+}

+ 82 - 48
poem-life-app/src/app/tab1/card-detail/card-detail.page.ts

@@ -3,10 +3,7 @@ import { ActivatedRoute, Router } from '@angular/router';
 import { CommonModule } from '@angular/common';
 import { FormsModule } from '@angular/forms';
 import { IonContent, IonHeader,IonItem,IonList, IonThumbnail,IonTitle, IonToolbar,IonFooter, IonButtons,IonButton, IonBackButton} from '@ionic/angular/standalone';
-
-
-
-
+import { CloudObject, CloudQuery } from 'src/lib/ncloud';
 
 @Component({
   selector: 'app-card-detail',
@@ -17,63 +14,100 @@ import { IonContent, IonHeader,IonItem,IonList, IonThumbnail,IonTitle, IonToolba
 })
 export class CardDetailPage implements OnInit {
 
-  content: {
-    title: string;
-    editor: string;
-    date: string;
-    issue: string;
-    detail: string;
-    images: string[]; // 明确指定为字符串数组
-    video: string;
-    audio: string;
-  } = {
-    title: '',
-    editor: '',
-    date: '',
-    issue: '',
-    detail: '',
-    images: [], // 初始化为空数组
-    video: '',
-    audio: ''
-  };
+  content: CloudObject | null = null; // 用于存储当前内容的数据
+  loading: boolean = true; // 添加加载状态
+  error: string | null = null; // 添加错误状态
+  prevContentData: CloudObject | null = null; // 前一篇文章
+  nextContentData: CloudObject | null = null; // 后一篇文章
+  contentsList: CloudObject[] = []; // 存储相同类型的文章列表
 
   constructor(private activatedRoute: ActivatedRoute, private router: Router) { }
 
   ngOnInit() {
-    const id = this.activatedRoute.snapshot.paramMap.get('id'); // 获取内容ID
-    this.loadContent(id);
+    // 获取传递的 ID
+    const id = this.activatedRoute.snapshot.queryParamMap.get('id');
+    if (id) {
+      this.loadContentById(id);
+    } else {
+      this.error = '内容ID未找到';
+      this.loading = false;
+    }
   }
 
-  loadContent(id: string | null) {
-    // 模拟加载内容,实际中应从服务获取数据
-    this.content = {
-      // title: `内容标题 ${id}`,
-      title: `清平调`,
-      editor: `文|编辑部`,
-      // editor: `编者姓名 ${id}`,
-      date: '2024-11-30',
-      issue: `第1期`,
-      // issue: `第${id}期`,
-      detail: ` 云想衣裳花想容,春风拂槛露华浓。若非群玉山头见,会向瑶台月下逢。`,
-      // detail: `这里是详细内容 ${id}...`,
-      images: ['../assets/image/01/Vx_03.jpg', ], // 示例图片路径
-      video: 'assets/video/sample.mp4', // 示例视频路径
-      audio: 'assets/audio/sample.mp3' // 示例音频路径
-    };
+  async loadContentById(id: string) {
+    try {
+      let query = new CloudQuery("PL_Contents");
+      query.equalTo('objectId', id); // 根据 ID 查询内容
+      const results = await query.find();
+      console.log('Loaded content:', results);
+      if (results.length > 0) {
+        this.content = results[0];
+        if (this.content) {
+          await this.loadContentsList(this.content.get('type')); // 加载内容列表
+          this.findPrevAndNextContent(); // 在这里调用
+        }
+      } else {
+        this.error = '内容未找到';
+      }
+    } catch (err) {
+      this.error = '加载内容时出错';
+      console.error(err);
+    } finally {
+      this.loading = false;
+    }
   }
 
-  goBack() {
-    this.router.navigate(['/tabs/tab1']); // 返回到 Tab1
+  async loadContentsList(type: string) {
+    try {
+      let query = new CloudQuery("PL_Contents");
+      query.equalTo('type', type); // 根据类型查询内容
+      query.orderByAscending('issue'); // 按 issue 升序排序
+      this.contentsList = await query.find();
+      console.log('Loaded contents list:', this.contentsList);
+      this.findPrevAndNextContent(); // 确保在此调用
+    } catch (err) {
+      console.error('加载内容列表时出错:', err);
+    }
+  }
+
+  findPrevAndNextContent() {
+    if (!this.content || !this.contentsList) return;
+
+    const contentId = this.content?.get('objectId');
+    if (!contentId) return;
+
+    const currentIndex = this.contentsList.findIndex(item => item.get('objectId') === contentId);
+    console.log('Current index:', currentIndex);
+    if (currentIndex > 0) {
+      this.prevContentData = this.contentsList[currentIndex - 1];
+    } else {
+      this.prevContentData = null; // 如果没有上一篇,确保设置为null
+    }
+    if (currentIndex < this.contentsList.length - 1) {
+      this.nextContentData = this.contentsList[currentIndex + 1];
+    } else {
+      this.nextContentData = null; // 如果没有下一篇,确保设置为null
+    }
+
+    console.log('Prev content:', this.prevContentData);
+    console.log('Next content:', this.nextContentData);
   }
+
   prevContent() {
-    const prevId = parseInt(this.content.issue.replace('第', '').replace('期', '')) - 1; // 简单逻辑示例
-    if (prevId > 0) {
-      this.router.navigate(['/card-detail'], { queryParams: { id: prevId } });
+    if (this.prevContentData) {
+      this.router.navigate(['/tabs/tab1/card-detail'], { queryParams: { id: this.prevContentData.get('objectId') } });
     }
   }
 
   nextContent() {
-    const nextId = parseInt(this.content.issue.replace('第', '').replace('期', '')) + 1; // 简单逻辑示例
-    this.router.navigate(['/card-detail'], { queryParams: { id: nextId } });
+    if (this.nextContentData) {
+      const nextId = this.nextContentData.get('objectId');
+      console.log('Navigating to next content with ID:', nextId); // 添加日志以调试
+      this.router.navigate(['/tabs/tab1/card-detail'], { queryParams: { id: nextId } });
+    }
+  }
+
+  goBack() {
+    this.router.navigate(['/tabs/tab1']); // 返回到 Tab1
   }
 }

+ 8 - 17
poem-life-app/src/app/tab1/tab1.page.html

@@ -1,7 +1,3 @@
-
-<!-- 头部一栏内容左侧分布一个日历图标(作用为点击进入一个导航页面,内面按照时间排布,每日的图文作为展示锚点,点击后进入对应日期发布的内容),右侧始终展示一个今日按钮,点击后返回最新内容的首页 -->
-<!-- //calendar没有正常显示图标 -->
-<!-- //这里的cards分别需要分给#个内容,图文(一张图片,下面附有文字内容诗句),视频,文章故事(扩写古诗),诗歌内容(纯粹的诗歌),音频内容(吟诵诗歌) -->
 <ion-header>
   <ion-toolbar>
     <ion-buttons slot="start">
@@ -10,9 +6,6 @@
         <span>日历</span>
       </ion-button>
     </ion-buttons>
-
-    <ion-title>诗</ion-title>
-
     <ion-buttons slot="end">
       <ion-button (click)="navigateToToday()">
         <ion-icon name="today-outline"></ion-icon>
@@ -23,21 +16,19 @@
 </ion-header>
 
 <ion-content [fullscreen]="true">
-  <div class="content-wrapper">
-
     <div class="main-content">
       <div class="card-section">
-
-        <div class="cards">
-          <div class="card" *ngFor="let item of contentItems" (click)="viewItemDetails(item)">
-            <img [src]="item.image" alt="{{ item.title }}" class="card-image" *ngIf="item.image">
-            <h4>{{ item.title }}</h4>
-            <p>{{ item.snippet }}</p>
+        <div class="cards" *ngIf="PLContentsList.length > 0">
+          <div class="card" *ngFor="let content of PLContentsList" (click)="viewItemDetails(content)">
+            <p>{{content.get('type')}}</p>
+            <h1 style="text-align: left;">{{ content.get('title') }}</h1>
+            <h4 style="text-align: left;">{{ content.get('editor') }}</h4>
+            <h4 style="text-align: left;">{{ content.get('snippet') }}</h4>
+            <img [src]="content.get('image')" alt="content.get('title')" class="card-image" >
+            <p style="text-align: left;">{{content.get('time')}}</p>
           </div>
         </div>
       </div>
     </div>
-  </div>
 </ion-content>
 
-<!-- <app-explore-container name="Tab 1 page"></app-explore-container> -->

+ 4 - 1
poem-life-app/src/app/tab1/tab1.page.scss

@@ -1,7 +1,10 @@
 .content-wrapper {
   padding: 16px;
 }
-
+div, p {
+  display: block;
+  visibility: visible;
+}
 .main-content {
   .card-section {
     margin-bottom: 20px;

+ 21 - 37
poem-life-app/src/app/tab1/tab1.page.ts

@@ -1,60 +1,44 @@
 import { Component, OnInit } from '@angular/core';
-import { IonHeader, IonToolbar, IonTitle, IonContent,IonButtons, IonButton, IonIcon,IonDatetime } from '@ionic/angular/standalone';
+import { IonHeader, IonToolbar, IonTitle, IonContent, IonButtons, IonButton, IonIcon, IonDatetime } from '@ionic/angular/standalone';
 import { ExploreContainerComponent } from '../explore-container/explore-container.component';
 import { addIcons } from 'ionicons';
 import { calendar, todayOutline } from 'ionicons/icons';
 import { FormsModule } from '@angular/forms';
 import { CommonModule } from '@angular/common';
 import { Router } from '@angular/router';
-
+import { CloudObject ,CloudQuery} from 'src/lib/ncloud';
 @Component({
   selector: 'app-tab1',
   templateUrl: 'tab1.page.html',
   styleUrls: ['tab1.page.scss'],
   standalone: true,
-  imports: [FormsModule,CommonModule,IonHeader, IonToolbar, IonTitle, IonContent,IonButtons, IonButton,IonDatetime, IonIcon,ExploreContainerComponent],
+  imports: [FormsModule, CommonModule, IonHeader, IonToolbar, IonTitle, IonContent, IonButtons, IonButton, IonDatetime, IonIcon, ExploreContainerComponent],
 })
-export class Tab1Page {
+export class Tab1Page implements OnInit {
+
+  contentItems: any[] = [];
+  loading: boolean = true; // 添加加载状态
+  error: string | null = null; // 添加错误状态
 
-  selectedDate!: string; // 定义 selectedDate
-  contentItems = [
-    {
-      title: '清平调',
-      snippet: '云想衣裳花想容,春风拂槛露华浓。若非群玉山头见,会向瑶台月下逢。',
-      image: '../assets/image/01/Vx_03.jpg'
-    },
-    {
-      title: '短歌行',
-      snippet: '对酒当歌,人生几何!譬如朝露,去日苦多。...',
-      image: '../assets/image/02/duangexing.jpg'
-    },
-    {
-      title: '念奴娇·赤壁怀古',
-      snippet: '赤壁之战的还原视频...',
-      image: '../assets/image/03/chibizhizhan.jpg' // 替换为视频封面图
-    },
-    {
-      title: '出师表',
-      snippet: '对出师表进行的精彩扩写...',
-      image: '../assets/image/04/chushibiao.jpg' // 替换为文章封面图
-    },
-    {
-      title: '吟诵音频',
-      snippet: '一段优美的吟诵音频...',
-      image: '' // 替换为音频封面图
-    }
-  ];
+  constructor(private router: Router) {
+    addIcons({ calendar, todayOutline });
+  }
 
+  ngOnInit() {
+    // 生命周期
+    this.loadPLContentsList();
+  }
 
+  // 创建用于数据列表存储的属性
+  PLContentsList:Array<CloudObject> = []
 
-  // poems = []; // 假设有一些诗
-  // pastPoems = []; // 假设有一些往期诗篇
-  constructor(private router: Router) {
-    addIcons({calendar,todayOutline});
+  async loadPLContentsList(){
+    let query = new CloudQuery("PL_Contents");
+    this.PLContentsList = await query.find()
   }
 
   navigateToDiary() {
-    this.router.navigateByUrl('/daily-content')
+    this.router.navigateByUrl('/daily-content');
     // 导航到日历页面的逻辑
   }
 

+ 40 - 22
poem-life-app/src/app/tab2/tab2.page.html

@@ -1,54 +1,72 @@
 <ion-header [translucent]="true">
   <ion-toolbar>
     <ion-buttons slot="end">
-      <ion-button (click)="openSearch()" class="search-button">
+      <ion-button class="search-button">
         <ion-icon name="search" slot="icon-only"></ion-icon>
       </ion-button>
     </ion-buttons>
 
-    <ion-segment [(ngModel)]="selectedSegment" (ionChange)="segmentChanged($event)" class="custom-segment">
-      <ion-segment-button value="collection">
-        <ion-label>分类</ion-label>
+    <ion-segment [(ngModel)]="selectedGenre" (ionChange)="onGenreSelect($event.detail.value)">
+      <ion-segment-button value="五言律诗">
+        <ion-label>五言律诗</ion-label>
       </ion-segment-button>
-      <ion-segment-button value="works">
-        <ion-label>作品</ion-label>
+      <ion-segment-button value="七言律诗">
+        <ion-label>七言律诗</ion-label>
       </ion-segment-button>
-      <ion-segment-button value="authors">
-        <ion-label>作者</ion-label>
+      <ion-segment-button value="五言绝句">
+        <ion-label>五言绝句</ion-label>
+      </ion-segment-button>
+      <ion-segment-button value="六言绝句">
+        <ion-label>六言绝句</ion-label>
+      </ion-segment-button>
+      <ion-segment-button value="七言绝句">
+        <ion-label>七言绝句</ion-label>
       </ion-segment-button>
     </ion-segment>
   </ion-toolbar>
 </ion-header>
 
 <ion-content [fullscreen]="true">
-  <ng-container *ngIf="selectedSegment === 'collection'">
+  <ng-container>
     <ion-grid>
       <ion-col size="2" class="fixed-sidebar">
         <ion-list>
-          <ion-item button *ngFor="let category of categories" (click)="selectCategory(category.id)">
-            <ion-label>{{ category.name }}</ion-label>
+          <ion-item button (click)="onGenreSelect('五言律诗')">
+            <ion-label>五言律诗</ion-label>
+          </ion-item>
+          <ion-item button (click)="onGenreSelect('七言律诗')">
+            <ion-label>七言律诗</ion-label>
+          </ion-item>
+          <ion-item button (click)="onGenreSelect('五言绝句')">
+            <ion-label>五言绝句</ion-label>
+          </ion-item>
+          <ion-item button (click)="onGenreSelect('六言绝句')">
+            <ion-label>六言绝句</ion-label>
+          </ion-item>
+          <ion-item button (click)="onGenreSelect('七言绝句')">
+            <ion-label>七言绝句</ion-label>
           </ion-item>
         </ion-list>
       </ion-col>
       <ion-col size="10" class="scrollable-content">
         <div class="book-cards-container">
-          <ion-card *ngFor="let book of filteredBooks" (click)="goToBookManagement(book.id)" class="book-card">
+          <div class="card" *ngFor="let book of filteredPoemsList" (click)="goToPoemDetail(book)">
+            <h1 style="text-align: left;">{{ book.get('title') }}</h1>
+
+            <h4 style="text-align: left;">{{ book.get('creation_time') }}</h4>
+
+
+          </div>
+          <!-- <ion-card class="bookcard" *ngFor="let book of filteredPoemsList"  (click)="goToPoemDetail(book)">
             <ion-card-header>
-              <ion-card-title>{{ book.title }}</ion-card-title>
+              <ion-card-title>{{ book.get('title') }}</ion-card-title>
             </ion-card-header>
             <ion-card-content>
-              <p>{{ book.count }} 个条目</p>
+              <p>{{ book.get('creation_time') }}</p>
             </ion-card-content>
-          </ion-card>
+          </ion-card> -->
         </div>
       </ion-col>
     </ion-grid>
   </ng-container>
-
-  <ng-container *ngIf="selectedSegment === 'works' || selectedSegment === 'authors'">
-    <div class="blank-page">
-      <p *ngIf="selectedSegment === 'works'">这里是作品页面的内容。</p>
-      <p *ngIf="selectedSegment === 'authors'">这里是作者页面的内容。</p>
-    </div>
-  </ng-container>
 </ion-content>

+ 33 - 2
poem-life-app/src/app/tab2/tab2.page.scss

@@ -47,8 +47,39 @@ ion-content {
    margin-left: auto; // 强制将搜索按钮推到最右边
   }
 
+
+  .card {
+    background: #ffffff;
+    border-radius: 8px;
+    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
+    padding: 10px;
+    cursor: pointer;
+    text-align: center;
+    transition: transform 0.2s;
+
+    &:hover {
+      transform: scale(1.05);
+    }
+
+    .card-image {
+      width: 100%;
+      height: auto;
+      border-radius: 8px;
+      margin-bottom: 8px;
+    }
+
+    h4 {
+      font-size: 16px;
+      margin: 0;
+    }
+
+    p {
+      font-size: 14px;
+      color: #666;
+    }
+  }
   /* 书籍卡片样式 */
-  .book-card {
+  .bookcard {
    margin: 0; /* 移除边距,由 .book-cards-container 控制 */
    border-radius: 8px;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
@@ -125,4 +156,4 @@ ion-content {
    color: #888;
   }
 
-  
+

+ 28 - 189
poem-life-app/src/app/tab2/tab2.page.ts

@@ -1,11 +1,11 @@
+import { IonicModule } from '@ionic/angular';
 import { Component, OnInit } from '@angular/core';
 import { HttpClient } from '@angular/common/http';
 import { Router } from '@angular/router';
 import { addIcons } from 'ionicons';
 import { search } from 'ionicons/icons';
-import { catchError, Observable, of, tap } from 'rxjs';
+import { CloudObject, CloudQuery } from 'src/lib/ncloud';
 import { CommonModule } from '@angular/common';
-import { IonicModule } from '@ionic/angular';
 import { FormsModule } from '@angular/forms';
 
 @Component({
@@ -17,209 +17,48 @@ import { FormsModule } from '@angular/forms';
 })
 export class Tab2Page implements OnInit {
   selectedSegment: string = 'collection'; // 默认选择分类标签
-  books: any[] = []; // 所有书籍
-  filteredBooks: any[] = []; // 筛选后的书籍
-  categories: any[] = []; // 分类列表
-
-  private baseUrl = 'http://localhost:3000/api'; // 后端 API 基础 URL
-  private loading = false; // 加载状态标志
+  selectedGenre: string = ''; // 存储选中的体裁
+  PLPoemsList: Array<CloudObject> = []; // 所有诗歌列表
+  filteredPoemsList: Array<CloudObject> = []; // 筛选后的诗歌列表
 
   constructor(private http: HttpClient, private router: Router) {
     addIcons({ search });
   }
 
   ngOnInit() {
-    this.loadCategories();
-    this.loadBooks();
-  }
-
-  private getBooks(categoryId?: number): Observable<any[]> {
-    const url = `${this.baseUrl}/books${categoryId ? `?category_id=${categoryId}` : ''}`;
-    return this.http.get<any[]>(url).pipe(
-      catchError(error => {
-        console.error('Error fetching books', error);
-        return of([]);
-      })
-    );
-  }
-
-  private getCategories(): Observable<any[]> {
-    return this.http.get<any[]>(`${this.baseUrl}/categories`).pipe(
-      catchError(error => {
-        console.error('Error fetching categories', error);
-        return of([]);
-      })
-    );
+    this.loadPLPoemsList();
   }
 
-  loadCategories(): void {
-    this.getCategories().subscribe(data => {
-      this.categories = data;
-    });
+  // 加载所有诗歌
+  async loadPLPoemsList() {
+    let query = new CloudQuery("PL_Poems");
+    this.PLPoemsList = await query.find();
+    this.filteredPoemsList = this.PLPoemsList; // 初始化时显示所有诗歌
   }
 
-  loadBooks(categoryId?: number): void {
-    this.loading = true;
-    this.getBooks(categoryId).pipe(
-      tap(data => {
-        this.books = data;
-        this.filteredBooks = categoryId ? data : this.books;
-      }),
-      tap(() => this.loading = false)
-    ).subscribe();
-  }
-
-  segmentChanged(event: any): void {
-    const newSegment = event.detail.value;
-    this.selectedSegment = newSegment;
-
-    if (newSegment === 'collection') {
-      this.filteredBooks = this.books;
-    } else {
-      this.filteredBooks = [];
-      // 根据需要添加其他逻辑
+  // 选择体裁
+  onGenreSelect(genre: string | number | undefined) {
+    if (typeof genre === 'string') {
+      this.selectedGenre = genre;
+      this.filterPoemsByGenre(genre);
+    } else if (typeof genre === 'number') {
+      // 如果 genre 是数字,可以根据需要进行处理,这里假设需要转换为字符串
+      this.selectedGenre = genre.toString();
+      this.filterPoemsByGenre(this.selectedGenre);
     }
   }
 
-  selectCategory(categoryId: number): void {
-    console.log('Selected category ID:', categoryId);
-    this.loadBooks(categoryId); // 使用新的方法加载特定分类的书籍
-  }
-
-  goToBookManagement(bookId: number): void {
-    if (bookId) {
-      this.router.navigate(['book-management', bookId]);
+  // 根据体裁过滤诗歌列表
+  filterPoemsByGenre(genre: string) {
+    if (genre) {
+      this.filteredPoemsList = this.PLPoemsList.filter(book => book.get('genre') === genre);
+      //query.equalTo('genre', 'genre'); // 添加查询条件来限制 type="对应的genre"
     } else {
-      console.warn('Invalid book ID');
+      this.filteredPoemsList = this.PLPoemsList; // 如果没有选择体裁,显示所有诗歌
     }
   }
 
-  openSearch(): void {
-    console.log('Search clicked');
+  goToPoemDetail(bookcard: any) {
+    this.router.navigate(['/poem-detail'],{ queryParams: { id: bookcard.id }  });
   }
 }
-
-
-// import { Component, OnInit } from '@angular/core';
-// import { CommonModule } from '@angular/common';
-// import { IonicModule } from '@ionic/angular';
-// import { HttpClient } from '@angular/common/http';
-// import { Router } from '@angular/router';
-// import { addIcons } from 'ionicons';
-// import { search } from 'ionicons/icons';
-// import { FormsModule } from '@angular/forms';
-// import { catchError, of, tap ,Observable} from 'rxjs';
-
-// @Component({
-//   selector: 'app-tab2',
-//   templateUrl: 'tab2.page.html',
-//   styleUrls: ['tab2.page.scss'],
-//   standalone: true,
-//   imports: [CommonModule, IonicModule, FormsModule]
-// })
-// export class Tab2Page implements OnInit {
-//   selectedSegment: string = 'collection';  // 默认选择分类标签
-//   books: any[] = [];  // 所有书籍
-//   filteredBooks: any[] = [];  // 筛选后的书籍
-//   categories: any[] = [];  // 分类列表
-
-//   private baseUrl = 'http://localhost:3000/api'; // 后端 API 基础 URL
-//   private loading = false; // 加载状态标志
-
-//   constructor(private http: HttpClient, private router: Router) {
-//     addIcons({ search });
-//   }
-
-//   ngOnInit() {
-//     this.loadCategories();
-//     this.loadBooks();
-//   }
-
-//   loadCategories(): void {
-//     this.http.get<any[]>(`${this.baseUrl}/categories`)
-//       .pipe(
-//         tap(data => this.categories = data),
-//         catchError(error => {
-//           console.error('Error fetching categories', error);
-//           return of([]);
-//         })
-//       ).subscribe();
-//   }
-
-//   loadBooks(categoryId?: number): void {
-//     this.loading = true;
-//     this.http.get<any[]>(`${this.baseUrl}/books${categoryId ? `?category_id=${categoryId}` : ''}`)
-//       .pipe(
-//         tap(data => {
-//           this.books = data;
-//           this.filteredBooks = categoryId ? data : this.books;
-//         }),
-//         catchError(error => {
-//           console.error('Error fetching books', error);
-//           return of([]);
-//         }),
-//         tap(() => this.loading = false)
-//       ).subscribe();
-//   }
-
-//   // ngOnInit() {
-//   //   // 获取分类数据
-//   //   this.getCategories().subscribe((data: any[]) => {
-//   //     this.categories = data;  // 保存分类数据
-//   //   }, (error: any) => {
-//   //     console.error('Error fetching categories', error);
-//   //   });
-
-//   //   // 获取书籍数据
-//   //   this.getBooks().subscribe((data: any[]) => {
-//   //     this.books = data;
-//   //     this.filteredBooks = this.books;
-//   //   }, (error: any) => {
-//   //     console.error('Error fetching books', error);
-//   //   });
-//   // }
-
-//   getBooks(categoryId?: number) {
-//     const url = `${this.baseUrl}/books${categoryId ? `?category_id=${categoryId}` : ''}`;
-//     return this.http.get<any[]>(url); // 获取书籍数据
-//   }
-
-//   getCategories() {
-//     return this.http.get<any[]>(`${this.baseUrl}/categories`); // 获取分类数据
-//   }
-
-//   segmentChanged(event: any) {
-//     const newSegment = event.detail.value;
-//     if (newSegment === 'collection') {
-//       this.filteredBooks = this.books; // 默认显示所有书籍
-//     } else if (newSegment === 'works') {
-//       this.filteredBooks = []; // 清空书籍列表,您可以根据需要添加逻辑
-//     } else if (newSegment === 'authors') {
-//       this.filteredBooks = []; // 清空书籍列表,您可以根据需要添加逻辑
-//     }
-//   }
-  
-//   selectCategory(categoryId: number) {
-//     console.log('Selected category ID:', categoryId);
-//     // 根据类别获取书籍
-//     this.getBooks(categoryId).subscribe({
-//       next: data => {
-//         this.filteredBooks = data; // 更新书籍列表
-//       },
-//       error: err => {
-//         console.error('Error fetching books for category', err);
-//       },
-//       complete: () => {
-//         console.log('Request completed'); // 可选的完成回调
-//       }
-//     });
-//   }
-
-//   goToBookManagement(bookId: number) {
-//     this.router.navigate(['book-management', bookId]); // 直接传递 bookId
-//   }
-
-//   openSearch() {
-//     console.log('Search clicked');
-//   }
-// }

+ 4 - 4
poem-life-app/src/app/tab3/tab3.page.html

@@ -52,9 +52,9 @@
 <!-- 退出登录按钮 -->
 <div style="text-align: center; margin: 30px;">
   @if(!currentUser?.id){
-  <ion-button expand="block" (click)="signup()">注册</ion-button> 
+  <ion-button expand="block" (click)="signup()">注册</ion-button>
   <ion-button expand="block"  (click)="login()">登录</ion-button>
-  } 
+  }
   @if(currentUser?.id){
     <h1>您已登录成功</h1>
   <ion-button expand="block" (click)="logout()">登出</ion-button>
@@ -84,7 +84,7 @@
 
 
   <div class="profile-container">
-    <img src="../../assets/image/01/Vx_03.jpg" alt="背景图片" />
+    <img src="../../assets/image/01/shige01.jpg" alt="背景图片" />
 
     <div class="profile-card">
 
@@ -174,4 +174,4 @@
     <!-- 内容将由updateContent方法动态插入 -->
   </div>
 </ion-content>
-</div>
+</div>

+ 0 - 10
poem-life-app/src/app/tabs/tabs.routes.ts

@@ -25,11 +25,6 @@ export const routes: Routes = [
         path: 'tab4',
         loadComponent: () => import('../tab4/tab4.page').then( m => m.Tab4Page)
       },
-      // {
-      //   path: 'tab5',
-      //   loadComponent: () =>
-      //     import('../tab5/tab5.component').then((m) => m.Tab5Component),
-      // },
       {
         path: 'create',
         loadComponent: () => import('../page-create/page-create.component').then( m => m.PageCreateComponent)
@@ -38,11 +33,6 @@ export const routes: Routes = [
         path: 'createpic',
         loadComponent: () => import('../page-createpic/page-createpic.component').then( m => m.PageCreatepicComponent)
       },
-      
-      // {
-      //   path: 'login',  // 添加 login 页面路径
-      //   loadComponent: () => import('../login/login.component').then(m => m.LoginComponent)
-      // },
       {
         path: '',
         redirectTo: '/tabs/tab1',

+ 0 - 0
poem-life-app/src/assets/image/04/chushibiao.jpg → poem-life-app/src/assets/image/01/gushi01.jpg


+ 0 - 0
poem-life-app/src/assets/image/01/Vx_03.jpg → poem-life-app/src/assets/image/01/shige01.jpg


BIN
poem-life-app/src/assets/image/01/shipin01.jpg


BIN
poem-life-app/src/assets/image/01/tuwen01.jpg


BIN
poem-life-app/src/assets/image/01/tuwen02.jpg


BIN
poem-life-app/src/assets/image/01/yinpin01.jpg


+ 18 - 3
poem-life-app/src/lib/ncloud.ts

@@ -83,6 +83,7 @@ export class CloudObject {
 export class CloudQuery {
     className: string;
     whereOptions: Record<string, any> = {};
+    orderOptions: string[] = []; // 用于存储排序条件
 
     constructor(className: string) {
         this.className = className;
@@ -112,6 +113,14 @@ export class CloudQuery {
         this.whereOptions[key] = value;
     }
 
+    orderByAscending(key: string) {
+      this.orderOptions.push(`${key}`);
+  }
+
+  orderByDescending(key: string) {
+      this.orderOptions.push(`-${key}`);
+  }
+
     async get(id: string) {
         const url = `http://dev.fmode.cn:1337/parse/classes/${this.className}/${id}?`;
 
@@ -138,6 +147,10 @@ export class CloudQuery {
             url += `where=${whereStr}`;
         }
 
+        if (this.orderOptions.length) {
+          url += `${url.includes('?') ? '&' : '?'}order=${this.orderOptions.join(',')}`;
+      }
+
         const response = await fetch(url, {
             headers: {
                 "if-none-match": "W/\"1f0-ghxH2EwTk6Blz0g89ivf2adBDKY\"",
@@ -215,7 +228,7 @@ export class CloudUser extends CloudObject {
             console.error("用户未登录");
             return null;
         }
-        
+
         const response = await fetch(`http://dev.fmode.cn:1337/parse/users/me`, {
             headers: {
                 "x-parse-application-id": "dev",
@@ -248,7 +261,7 @@ export class CloudUser extends CloudObject {
             console.error(result?.error);
             return null;
         }
-        
+
         // 设置用户信息
         this.id = result?.objectId;
         this.sessionToken = result?.sessionToken;
@@ -317,4 +330,6 @@ export class CloudUser extends CloudObject {
         this.data = result; // 保存用户数据
         return this;
     }
-}
+}
+
+// CloudCard.ts