Преглед на файлове

完善发帖界面及功能

s202226701053 преди 5 месеца
родител
ревизия
2156336a55

+ 19 - 18
E-Cover-app/src/app/send-post/send-post.component.html

@@ -1,8 +1,8 @@
 <!--头部-->
 <app-custom-header [param]="['发布帖子','    ']"></app-custom-header>
-<ion-button shape="round" class="publish-button" (click)="publishPost()"
+<ion-button size="small" shape="round" class="publish-button" (click)="publishPost()"
   [ngClass]="{'active': inputText.length > 0 && remainingChars<20}"
-  [disabled]="inputText.length === 0 || remainingChars < 0">
+  [disabled]="inputText.length === 0 || remainingChars == 20">
   发布
 </ion-button>
 <!--内容-->
@@ -14,29 +14,33 @@
       <span class="char-counter">{{ remainingChars }} </span>
     </div>
     <!--如果用户选择了标签,则显示-->
-    <div *ngIf="tags.length > 0" id="show-tag">
-      <ion-button class="tags" shape="round" *ngFor="let tag of tags" (click)="removeTags(tag)">
+    <div *ngIf="tags.length > 0" id="show-tag" class="tag-container">
+      <div class="tags" *ngFor="let tag of tags" (click)="removeTags(tag)">
         <ion-img src="https://s1.imagehub.cc/images/2024/12/24/713f569886bd5eb876b5cf543777062b.png" />
-        {{ tag }}
-      </ion-button>
+        <p>{{ tag?.get('name') }}</p>
+      </div>
     </div>
     <ion-textarea [(ngModel)]="inputText" [autoGrow]="true" placeholder="分享你的穿搭...">
     </ion-textarea>
   </div>
   <!--图片-->
-  <div class="image-box" *ngFor="let image of images; let i = index">
-    <img [src]="image" alt="Post Image" class="image">
-    <ion-icon name="close-circle-outline" class="delete-icon" (click)="removeImage(i)"></ion-icon>
+  <div class="image-container">
+    <div class="image-box" *ngFor="let image of images; let i = index">
+      <img [src]="image" alt="Post Image" class="image">
+      <ion-icon name="close-circle-outline" class="delete-icon" (click)="removeImage(i)"></ion-icon>
+    </div>
   </div>
 </ion-content>
 <!--标签-->
-<ion-content class="tag-container">
-  <ion-button class="tags" shape="round" *ngFor="let tag of ['标签1','标签2','标签3','标签4']" (click)="addTags(tag)">
+<div class="tag-container">
+  <div class="tags" *ngFor="let tag of sixTags" (click)="addTags(tag)">
     <ion-img src="https://s1.imagehub.cc/images/2024/12/24/713f569886bd5eb876b5cf543777062b.png" />
-    {{ tag }}
-  </ion-button>
-</ion-content>
-
+    <p>{{ tag?.get('name') }}</p>
+  </div>
+  <div style="width: 30px;height: 30px;display: flex;align-items: center;">
+    <ion-icon name="chevron-forward-outline"></ion-icon>
+  </div>
+</div>
 
 <ion-footer class="footer">
   <div class="left-icons">
@@ -51,11 +55,8 @@
     </div>
   </div>
   <div class="location-tag" (click)="removeLocationTag()" *ngIf="showLocationTag">
-
-    <ion-icon name="pin"></ion-icon>
     <span>南昌市</span>
     <ion-icon name="close-outline" slot="end"></ion-icon>
-
   </div>
   <!-- 隐藏的文件输入 -->
   <input type="file" accept="image/*" (change)="onFileChange($event)" style="display: none;" #fileInput>

+ 82 - 34
E-Cover-app/src/app/send-post/send-post.component.scss

@@ -1,29 +1,26 @@
 .publish-button {
     position: absolute;
     z-index: 99999;
-    height: 50px;
-    width: 120px;
-    background-color: rgb(236, 235, 233);
+    --background: rgb(220, 220, 220);
     color: gray;
     font-size: 18px;
     right: 10px;
-
+    top: 13px;
+    --box-shadow: none;
 
     &.active {
         /* 当输入框有内容时的样式 */
-        background-color: white;
-        /* 背景色变为黑色 */
-        color: black;
-        /* 字体颜色变为白色 */
+        --background: black;
+        color: white;
     }
 }
 
 .content {
+    --background: white;
     display: flex;
     flex-direction: column;
     /* 垂直排列子元素 */
     height: 100%;
-    /* 确保内容区域占满整个高度 */
 }
 
 .input-area {
@@ -38,17 +35,16 @@
     display: flex;
     /* 使用 flex 布局 */
     justify-content: space-between;
-    /* 左右对齐 */
     align-items: center;
-    /* 垂直居中对齐 */
     margin-bottom: 10px;
     /* 标题输入框与文本区域之间的间距 */
-}
 
+    font-size: 20px;
+    font-weight: bolder;
+}
 
 .title-input ion-input {
     border: none;
-    /* 移除默认边框 */
     border-bottom: 1px solid #ccc;
     /* 添加下边框 */
     flex: 1;
@@ -66,25 +62,29 @@
     /* 防止换行 */
 }
 
+ion-textarea {
+    --border-color: none;
+}
+
 .footer {
     display: flex;
-    /* 使用 flex 布局 */
     justify-content: space-between;
-    /* 左右对齐 */
     align-items: center;
-    /* 垂直居中对齐 */
     padding-left: 10px;
     height: 60px;
-    /* 设置底部的高度 */
-    background-color: #f0f0f0;
-    /* 设置背景色 */
+    background-color: #f8f8f8;
+    bottom: 0;
 }
 
 .left-icons {
     display: flex;
-    /* 使用 flex 布局 */
     align-items: center;
-    /* 垂直居中对齐 */
+    height: 100%;
+
+    ion-icon {
+        width: 35px;
+        height: 35px;
+    }
 }
 
 .location-tag {
@@ -106,9 +106,7 @@
 .footer-button {
     color: black;
     font-size: 40px;
-    margin-right: 20px;
-    margin-top: 30px;
-    margin-bottom: 10px;
+    margin: 10px;
 }
 
 /* 表情选择器样式 */
@@ -167,21 +165,33 @@
 //标签
 .tag-container {
     display: flex;
-    justify-content: flex-start;
-    margin-bottom: 10px;
-    height: 10px;
-    bottom: 10px;
+    align-items: center;
+    background-color: white;
+    border-color: none;
+    scrollbar-width: none;
+    overflow-x: auto;
+    padding-left: 10px;
+    height: 50px;
 }
 
 .tags {
-    --background: rgba(94, 94, 94, 0.503);
-    --padding-start: 5px;
-    --padding-end: 5px;
-    font-size: 17px;
+    background: rgba(248, 248, 248);
+    border-radius: 1000px;
+    padding: 10px 5px;
+    font-size: 15px;
+    color: black;
+    margin: 8px;
+    display: flex;
+    white-space: nowrap;
+
+    p {
+        margin: 0;
+        padding: 0;
+    }
 
     ion-img {
-        width: 25px;
-        height: 25px;
+        width: 20px;
+        height: 20px;
     }
 }
 
@@ -193,4 +203,42 @@
 
 .posts-container {
     width: 100%; // 宽度占满父元素
+}
+
+.image-container {
+    display: flex;
+    width: 100%;
+    justify-content: center;
+    flex-wrap: wrap;
+}
+
+//图片边框
+.image-box {
+    position: relative;
+    /* 使子元素绝对定位 */
+    width: 120px;
+    height: 120px;
+    border-radius: 3px;
+    margin: 0 5px;
+    float: left;
+}
+
+.delete-icon {
+    position: absolute;
+    top: 5px;
+    right: 5px;
+    color: white;
+    font-size: 20px;
+    cursor: pointer;
+    background: black;
+    border-radius: 50%;
+}
+
+.image {
+    width: 100%;
+    /* 图片宽度100% */
+    height: 100%;
+    /* 图片高度100% */
+    object-fit: cover;
+    /* 保持纵横比,填充整个容器 */
 }

+ 75 - 27
E-Cover-app/src/app/send-post/send-post.component.ts

@@ -5,13 +5,13 @@ import { Router } from '@angular/router';
 import { NavController } from '@ionic/angular';
 import { IonButton, IonButtons, IonCardContent, IonContent, IonFooter, IonHeader, IonIcon, IonImg, IonInfiniteScrollContent, IonInput, IonItem, IonTextarea, IonTitle, IonToolbar, } from '@ionic/angular/standalone';
 import { addIcons } from 'ionicons';
-import { atOutline, bookmarkOutline, chevronBackSharp, closeOutline, happyOutline, imageOutline, } from 'ionicons/icons';
-import { CloudObject, CloudUser } from 'src/lib/ncloud';
+import { atOutline, bookmarkOutline, chevronBackSharp, chevronForwardOutline, closeOutline, happyOutline, imageOutline, } from 'ionicons/icons';
+import { CloudObject, CloudQuery, CloudUser } from 'src/lib/ncloud';
 import { IonModal, } from '@ionic/angular/standalone'; // 导入独立组件
 import { HwobsProvider } from './hwobs.service';
 import { CustomHeaderComponent } from 'src/lib/component/custom-header/custom-header.component';
 
-addIcons({ chevronBackSharp, imageOutline, atOutline, happyOutline, closeOutline, bookmarkOutline });
+addIcons({ chevronBackSharp, imageOutline, atOutline, happyOutline, closeOutline, bookmarkOutline, chevronForwardOutline });
 @Component({
   selector: 'app-send-post',
   templateUrl: './send-post.component.html',
@@ -27,12 +27,12 @@ export class SendPostComponent implements OnInit {
   showLocationTag: boolean = true; // 控制标签是否显示
   remainingChars: number = 20; // 剩余字符数
   images: string[] = []; // 存储图片的数组
-  tags: string[] = []; // 存储标签的数组
+  tags: any = []; // 存储选中的标签
   isPost: boolean = false; // 帖子发布状态
   @Input() url: string = "";
   @Output() onUrlChange: EventEmitter<string> = new EventEmitter<string>()
   uploader: HwobsProvider | undefined
-  ngOnInit() {
+  async ngOnInit() {
     this.uploader = new HwobsProvider({
       bucketName: "nova-cloud",
       prefix: "dev/jxnu/storage/",
@@ -40,6 +40,8 @@ export class SendPostComponent implements OnInit {
       access_key_id: "XSUWJSVMZNHLWFAINRZ1",
       secret_access_key: "P4TyfwfDovVNqz08tI1IXoLWXyEOSTKJRVlsGcV6"
     });
+    await this.getTags(); // 获取所有标签
+    this.getSixTags(); // 获取六个标签
   }
   constructor(private router: Router, private navCtrl: NavController) { }
   goBack() {
@@ -50,14 +52,14 @@ export class SendPostComponent implements OnInit {
    * 
    */
   // 添加标签
-  addTags(tag: string) {
+  addTags(tag: any) {
     this.tags.push(tag); // 添加标签到 tags 数组中
     console.log(this.tags)
   }
   // 删除标签
-  removeTags(tag: string) {
-    this.tags = this.tags.filter((item) => item !== tag); // 从 tags 数组中删除指定标签
-    console.log(this.tags)
+  removeTags(tag: any) {
+    this.tags = this.tags.filter((item: any) => item !== tag); // 从 tags 数组中删除指定标签
+    console.log(this.tags);
   }
   // 添加图片
   uploadImage() {
@@ -71,9 +73,13 @@ export class SendPostComponent implements OnInit {
     this.images.splice(index, 1); // 从数组中删除指定索引的图片
   }
   // 发布帖子
-  publishPost() {
+  async publishPost() {
     this.isPost = true;
     const post = new CloudObject('post');
+    //tags数组中的每一个对象元素只取id和data属性
+    for (let i = 0; i < this.tags.length; i++) {
+      this.tags[i] = { id: this.tags[i].id, data: this.tags[i].data };
+    }
     //设置帖子默认属性
     post.set({
       UserID: new CloudUser().toPointer(),
@@ -84,18 +90,48 @@ export class SendPostComponent implements OnInit {
       like: 0,
     });
     // 保存帖子到数据库
-    post.save()
-      .then(() => {
-        console.log('帖子已发布');
-        // 清空输入框和其他状态
-        this.inputText = '';
-        this.title = '';
-        this.images = [];
-        this.tags = [];
-      })
-      .catch((error: any) => {
-        console.error('发布帖子时出错:', error);
-      });
+    post.save().then(() => {
+      console.log('帖子已发布');
+      // 清空输入框和其他状态
+      this.inputText = '';
+      this.title = '';
+      this.images = [];
+      this.tags = [];
+    }).catch((error: any) => {
+      console.error('发布帖子时出错:', error);
+    });
+    // 标签数组中每一个id对应的tag的click加1,更新至数据库中
+    let newTag = new CloudObject('tag');
+    let query = new CloudQuery('tag');
+    for (let i = 0; i < this.tags.length; i++) {
+      console.log("正在更新第" + i + "/" + this.tags.length + "的点击数");
+      const tagId = this.tags[i].id;
+      console.log("正在更新" + tagId + "的点击数");
+
+      // 根据标签ID查询对应的tag对象
+      query.equalTo('objectId', tagId); // 设置查询条件为标签ID
+      try {
+        let result = await query.find();
+        if (result.length === 0) {
+          console.error("未找到对应的标签对象:", tagId);
+          continue; // 如果没有找到对应的标签对象,则跳过当前迭代
+        }
+        let tag = result[0]; // 获取查询结果
+        console.log("即将要修改:");
+        console.log(tag);
+        let click = tag.get('click') + 1; // 获取点击数并加一
+        newTag.id = tagId; // 设置标签对象的 ID
+        newTag.set({ click: click }); // 设置新的点击数
+        try {
+          await newTag.save(); // 保存更新后的标签对象
+          console.log("更新成功" + tagId + "的点击数");
+        } catch (saveError) {
+          console.error("保存标签对象时出错:", saveError);
+        }
+      } catch (findError) {
+        console.error("查询标签对象时出错:", findError);
+      }
+    }
     this.isPost = true; // 发布成功后,将 isPost 设置为 true
     this.goBack();
   }
@@ -103,7 +139,7 @@ export class SendPostComponent implements OnInit {
   /**
    * @内置操作函数
    */
-  //  删除标签
+  //  删除位置标签
   removeLocationTag() {
     this.showLocationTag = false; // 设置为 false 隐藏标签
   }
@@ -111,7 +147,22 @@ export class SendPostComponent implements OnInit {
   updateTitleLength() {
     this.remainingChars = 20 - this.title.length; // 更新剩余字符数
   }
-
+  //获取全部标签列表
+  allTags: any[] = [];
+  async getTags() {
+    let query = new CloudQuery('tag');
+    let result = await query.find();
+    this.allTags = result; // 将查询结果赋值给 tags 数组
+    console.log("获取所有标签列表成功:")
+    console.log(this.allTags);
+  }
+  //获取前六个标签
+  sixTags: any[] = [];
+  getSixTags() {
+    this.sixTags = this.allTags?.slice(0, 6); // 获取前六个标签
+    console.log("获取前六个标签成功:")
+    console.log(this.sixTags);
+  }
   file: File | undefined
   fileData: any = ""
   fileList: File[] = []
@@ -168,16 +219,13 @@ export class SendPostComponent implements OnInit {
   openEmojiPicker() {
     this.isEmojiPickerOpen = true;
   }
-
   // 关闭表情选择器
   closeEmojiPicker() {
     this.isEmojiPickerOpen = false; // 关闭模态框
   }
-
   // 添加表情到输入框
   addEmoji(emoji: string) {
     this.inputText += emoji; // 将选中的表情添加到输入框
-
   }
 
 }

+ 0 - 664
E-Cover-app/src/lib/ncloud1.ts

@@ -1,664 +0,0 @@
-// CloudObject.ts
-export class CloudObject {
-    className: string;
-    id: string | null = null;
-    createdAt: any;
-    updatedAt: any;
-    sessionToken: string | null = ""
-    data: Record<string, any> = {};
-
-    constructor(className: string) {
-        this.className = className;
-    }
-
-    toPointer() {
-        return { "__type": "Pointer", "className": this.className, "objectId": this.id };
-    }
-
-    set(json: Record<string, any>) {
-        Object.keys(json).forEach(key => {
-            if (["objectId", "id", "createdAt", "updatedAt", "ACL"].indexOf(key) > -1) {
-                return;
-            }
-            this.data[key] = json[key];
-        });
-    }
-
-    get(key: string) {
-        return this.data[key] || null;
-    }
-
-    async save() {
-        let method = "POST";
-        let url = `http://1.94.237.145:1337/parse/classes/${this.className}`;
-
-        // 更新
-        if (this.id) {
-            url += `/${this.id}`;
-            method = "PUT";
-        }
-        console.log("准备发送" + method + "请求:" + url + ",body为:");
-        const body = JSON.stringify(this.data);
-        console.log(body);
-        const response = await fetch(url, {
-            headers: {
-                "content-type": "application/json;charset=UTF-8",
-                "x-parse-session-token": this.sessionToken || "",
-                "x-parse-application-id": "hcx"
-            },
-            body: body,
-            method: method,
-            mode: "cors",
-            credentials: "omit"
-        });
-        console.log(response);
-        const result = await response?.json();
-        if (result?.error) {
-            console.error(result?.error);
-        }
-        if (result?.objectId) {
-            this.id = result?.objectId;
-        }
-        return this;
-    }
-
-    async destroy() {
-        if (!this.id) return;
-        const response = await fetch(`http://1.94.237.145:1337/parse/classes/${this.className}/${this.id}`, {
-            headers: {
-                "x-parse-application-id": "hcx"
-            },
-            body: null,
-            method: "DELETE",
-            mode: "cors",
-            credentials: "omit"
-        });
-
-        const result = await response?.json();
-        if (result) {
-            this.id = null;
-        }
-        return true;
-    }
-}
-
-// CloudQuery.ts
-// export class CloudQuery {
-//     className: string;
-//     sessionToken: string | null = "";
-//     whereOptions: Record<string, any> = {};
-
-//     constructor(className: string) {
-//         this.className = className;
-//     }
-
-//     include(...fileds: string[]) {
-//         this.whereOptions["include"] = fileds;
-//     }
-//     greaterThan(key: string, value: any) {
-//         if (!this.whereOptions["where"][key]) this.whereOptions["where"][key] = {};
-//         this.whereOptions["where"][key]["$gt"] = value;
-//     }
-
-//     greaterThanAndEqualTo(key: string, value: any) {
-//         if (!this.whereOptions["where"][key]) this.whereOptions["where"][key] = {};
-//         this.whereOptions["where"][key]["$gte"] = value;
-//     }
-
-//     lessThan(key: string, value: any) {
-//         if (!this.whereOptions["where"][key]) this.whereOptions["where"][key] = {};
-//         this.whereOptions["where"][key]["$lt"] = value;
-//     }
-
-//     lessThanAndEqualTo(key: string, value: any) {
-//         if (!this.whereOptions["where"][key]) this.whereOptions["where"][key] = {};
-//         this.whereOptions["where"][key]["$lte"] = value;
-//     }
-
-//     equalTo(key: string, value: any) {
-//         if (!this.whereOptions["where"]) this.whereOptions["where"] = {};
-//         this.whereOptions["where"][key] = value;
-//     }
-
-//     async get(id: string) {
-//         const url = `http://1.94.237.145:1337/parse/classes/${this.className}/${id}?`;
-
-//         const response = await fetch(url, {
-//             headers: {
-//                 "if-none-match": "W/\"1f0-ghxH2EwTk6Blz0g89ivf2adBDKY\"",
-//                 "x-parse-application-id": "hcx"
-//             },
-//             body: null,
-//             method: "GET",
-//             mode: "cors",
-//             credentials: "omit"
-//         });
-
-//         const json = await response?.json();
-//         if (json) {
-//             let existsObject = this.dataToObj(json);
-//             return existsObject;
-//         }
-//         return null;
-//     }
-//     /**
-//      * @select查询
-//      */
-//     async main() {
-//         let response = await fetch(`http://1.94.237.145:1337/api/psql/select`, {
-//             headers: {
-//                 "Content-Type": "application/json",
-//             },
-//             body: JSON.stringify({ "sql": "SELECT * FROM \"_User\" limit 5", "params": [] }),
-//             method: "POST",
-//             mode: "cors",
-//             credentials: "omit"
-//         });
-
-//         let result = await response?.json();
-//         console.log(result)
-//     }
-
-//     async find(): Promise<Array<CloudObject>> {
-//         let url = `http://1.94.237.145:1337/parse/classes/${this.className}?`;
-
-//         let queryStr = ``
-//         // if (Object.keys(this.whereOptions).length) {
-//         //     const whereStr = JSON.stringify(this.whereOptions);
-//         //     url += `where=${whereStr}`;
-//         // }
-//         Object.keys(this.whereOptions).forEach(key => {
-//             let paramStr = JSON.stringify(this.whereOptions[key]);
-//             if (key == "include") {
-//                 paramStr = this.whereOptions[key]?.join(",")
-//             }
-//             if (queryStr) {
-//                 url += `${key}=${paramStr}`;
-//             } else {
-//                 url += `&${key}=${paramStr}`;
-//             }
-//         })
-
-//         const response = await fetch(url, {
-//             headers: {
-//                 "if-none-match": "W/\"1f0-ghxH2EwTk6Blz0g89ivf2adBDKY\"",
-//                 "x-parse-application-id": "hcx"
-//             },
-//             body: null,
-//             method: "GET",
-//             mode: "cors",
-//             credentials: "omit"
-//         });
-
-//         const json = await response?.json();
-//         let list = json?.results || []
-//         let objList = list.map((item: any) => this.dataToObj(item))
-//         return objList || [];
-//     }
-//     /**
-//      * @返回第一个查找到的结果
-//      * @返回结果参考:CloudObject {
-//      * id: 'e3wWcCfNwm', 
-//      * data: {…}, 
-//      * className: '_User', 
-//      * sessionToken:"r:c0f4fe9cb8eb83d7f0295ff57e948419"
-//      * createdAt: '2024-12-17T02:41:34.768Z', 
-//      * updatedAt: '2024-12-23T00:33:15.961Z'}
-//      */
-//     async first() {
-//         let url = `http://1.94.237.145:1337/parse/classes/${this.className}?`;
-
-//         if (Object.keys(this.whereOptions["where"]).length) {
-//             const whereStr = JSON.stringify(this.whereOptions["where"]);
-//             console.log("first查询条件" + whereStr)
-//             url += `where=${whereStr}`;
-//             console.log("first方法请求URL:" + url)
-//         }
-
-//         const response = await fetch(url, {
-//             headers: {
-//                 "if-none-match": "W/\"1f0-ghxH2EwTk6Blz0g89ivf2adBDKY\"",
-//                 "x-parse-application-id": "hcx",
-//                 "x-parse-session-token": this.sessionToken || "",
-//             },
-//             body: null,
-//             method: "GET",
-//             mode: "cors",
-//             credentials: "omit"
-//         });
-
-//         const json = await response?.json();
-//         const exists = json?.results?.[0] || null;
-//         if (exists) {
-//             let existsObject = this.dataToObj(exists)
-//             return existsObject;
-//         }
-//         return null
-//     }
-
-//     dataToObj(exists: any): CloudObject {
-//         let existsObject = new CloudObject(this.className);
-//         existsObject.set(exists);
-//         existsObject.id = exists.objectId;
-//         existsObject.createdAt = exists.createdAt;
-//         existsObject.updatedAt = exists.updatedAt;
-//         return existsObject;
-//     }
-// }
-
-export class CloudQuery {
-    className: string;
-    sessionToken: string | null = null;
-    whereOptions: Record<string, any> = {};
-    orderOptions: string[] = []; // 用于存储排序字段和方向的数组
-    limit: number | null = null; // 限制返回对象的数量
-
-    constructor(className: string) {
-        this.className = className;
-    }
-
-    include(...fields: string[]) {
-        this.whereOptions["include"] = fields;
-    }
-
-    greaterThan(key: string, value: any) {
-        if (!this.whereOptions["where"]) this.whereOptions["where"] = {};
-        this.whereOptions["where"][key] = { "$gt": value };
-    }
-
-    greaterThanAndEqualTo(key: string, value: any) {
-        if (!this.whereOptions["where"]) this.whereOptions["where"] = {};
-        this.whereOptions["where"][key] = { "$gte": value };
-    }
-
-    lessThan(key: string, value: any) {
-        if (!this.whereOptions["where"]) this.whereOptions["where"] = {};
-        this.whereOptions["where"][key] = { "$lt": value };
-    }
-
-    lessThanAndEqualTo(key: string, value: any) {
-        if (!this.whereOptions["where"]) this.whereOptions["where"] = {};
-        this.whereOptions["where"][key] = { "$lte": value };
-    }
-
-    equalTo(key: string, value: any) {
-        if (!this.whereOptions["where"]) this.whereOptions["where"] = {};
-        this.whereOptions["where"][key] = value;
-    }
-
-    orderByAscending(key: string) {
-        this.orderOptions.push(key); // 升序排序
-    }
-
-    orderByDescending(key: string) {
-        this.orderOptions.push(`-${key}`); // 降序排序
-    }
-
-    setLimit(limit: number) {
-        this.limit = limit;
-    }
-
-    async get(id: string): Promise<CloudObject | null> {
-        const url = `http://1.94.237.145:1337/parse/classes/${this.className}/${id}`;
-
-        const response = await fetch(url, {
-            headers: {
-                "X-Parse-Application-Id": "hcx",
-                "X-Parse-Session-Token": this.sessionToken || ""
-            },
-            method: "GET",
-            mode: "cors",
-            credentials: "omit"
-        });
-
-        const json = await response.json();
-        if (json) {
-            return this.dataToObj(json);
-        }
-        return null;
-    }
-    /**
-     * @select查询
-     */
-    async main() {
-        let response = await fetch(`http://1.94.237.145:1337/api/psql/select`, {
-            headers: {
-                "Content-Type": "application/json",
-            },
-            body: JSON.stringify({ "sql": "SELECT * FROM \"_User\" limit 5", "params": [] }),
-            method: "POST",
-            mode: "cors",
-            credentials: "omit"
-        });
-
-        let result = await response?.json();
-        console.log(result)
-    }
-
-    async find(): Promise<Array<CloudObject>> {
-        const url = new URL(`http://1.94.237.145:1337/parse/classes/${this.className}`);
-        const params = new URLSearchParams();
-
-        // 添加 where 参数
-        if (this.whereOptions["where"]) {
-            params.append('where', JSON.stringify(this.whereOptions["where"]));
-        }
-
-        // 添加 include 参数
-        if (this.whereOptions["include"]) {
-            params.append('include', this.whereOptions["include"].join(','));
-        }
-
-        // 添加 order 参数
-        if (this.orderOptions.length > 0) {
-            params.append('order', this.orderOptions.join(','));
-        }
-
-        // 添加 limit 参数
-        if (this.limit !== null) {
-            params.append('limit', this.limit.toString());
-        }
-
-        // 设置 URL 的搜索参数
-        url.search = params.toString();
-
-        const response = await fetch(url.href, {
-            headers: {
-                "X-Parse-Application-Id": "hcx",
-                "X-Parse-Session-Token": this.sessionToken || ""
-            },
-            method: "GET",
-            mode: "cors",
-            credentials: "omit"
-        });
-
-        const json = await response.json();
-        const results = json.results || [];
-        return results.map((item: any) => this.dataToObj(item));
-    }
-    /**
-     * @返回第一个查找到的结果
-     * @返回结果参考:CloudObject {
-     * id: 'e3wWcCfNwm', 
-     * data: {…}, 
-     * className: '_User', 
-     * sessionToken:"r:c0f4fe9cb8eb83d7f0295ff57e948419"
-     * createdAt: '2024-12-17T02:41:34.768Z', 
-     * updatedAt: '2024-12-23T00:33:15.961Z'}
-     */
-    async first() {
-        let url = `http://1.94.237.145:1337/parse/classes/${this.className}?`;
-
-        if (Object.keys(this.whereOptions["where"]).length) {
-            const whereStr = JSON.stringify(this.whereOptions["where"]);
-            console.log("first查询条件" + whereStr)
-            url += `where=${whereStr}`;
-            console.log("first方法请求URL:" + url)
-        }
-
-        const response = await fetch(url, {
-            headers: {
-                "if-none-match": "W/\"1f0-ghxH2EwTk6Blz0g89ivf2adBDKY\"",
-                "x-parse-application-id": "hcx",
-                "x-parse-session-token": this.sessionToken || "",
-            },
-            body: null,
-            method: "GET",
-            mode: "cors",
-            credentials: "omit"
-        });
-
-        const json = await response?.json();
-        const exists = json?.results?.[0] || null;
-        if (exists) {
-            let existsObject = this.dataToObj(exists)
-            return existsObject;
-        }
-        return null
-    }
-
-    dataToObj(data: any): CloudObject {
-        let obj = new CloudObject(this.className);
-        obj.set(data);
-        obj.id = data.objectId;
-        obj.createdAt = data.createdAt;
-        obj.updatedAt = data.updatedAt;
-        return obj;
-    }
-}
-
-// CloudUser.ts
-export class CloudUser extends CloudObject {
-    constructor() {
-        super("_User"); // 假设用户类在Parse中是"_User"
-        // 读取用户缓存信息
-        this.readCache();
-    }
-
-    //sessionToken: string | null = ""
-    /** 获取当前用户信息 */
-    current() {
-        if (!this.sessionToken) {
-            console.error("用户未登录");
-            return null;
-        }
-        return this;
-    }
-
-    /**更新用户缓存 */
-    async updateCache() {
-        if (!this.sessionToken) {
-            console.error("正在执行更新用户缓存:用户未登录");
-            return;
-        }
-        let query = new CloudQuery("_User");
-        query.equalTo("objectId", this.id)
-        console.log("设置条件:objectId==" + this.id)
-        let user: any = await query.find()
-        console.log("查询到条件用户信息:")
-        console.log(user)
-        //需要把sessionToken也保存起来
-        user.sessionToken = this.sessionToken
-        localStorage.setItem("NCloud/hcx/User", JSON.stringify(user))
-        console.log("已将该信息更新至用户缓存!请检查");
-        this.readCache();
-        return user;
-    }
-
-    /** 登录 */
-    async loginByUsername(username: string, password: string): Promise<CloudUser | null> {
-        const response = await fetch(`http://1.94.237.145:1337/parse/login`, {
-            headers: {
-                "x-parse-application-id": "hcx",
-                "Content-Type": "application/json"
-            },
-            body: JSON.stringify({ username, password }),
-            method: "POST"
-        });
-
-        const result = await response?.json();
-        if (result?.error) {
-            console.error(result?.error);
-            return null;
-        }
-
-        // 设置用户信息
-        this.id = result?.objectId;
-        this.sessionToken = result?.sessionToken;
-        this.updatedAt = result?.updatedAt;
-        this.className = '_User';
-        this.createdAt = result?.createdAt;
-        let excludedKeys = ["objectId", "sessionToken", "createdAt", "updatedAt"];
-        for (let key of excludedKeys) {
-            delete result[key];
-        }
-        this.data = result; // 保存用户数据
-        // 缓存用户信息
-        console.log("登录成功后即将缓存的信息如下:");
-        console.log(this)
-        localStorage.setItem("NCloud/hcx/User", JSON.stringify(this))
-        return this;
-    }
-
-    async loginByPhone(phone: string, verCode: string, trueVerCode: string): Promise<CloudUser | null> {
-        if (trueVerCode !== verCode) {
-            console.error('验证码错误');
-            return null;
-        }
-        let query = new CloudQuery("_User");
-        query.equalTo("phone", phone);
-        let user: any = await query.first();
-        //查询手机号对应的用户信息
-        let username: string = '';
-        let password: string = 'secretpassword';
-        if (!user?.id) {
-            console.error('该手机号未注册');
-            //用户名即为手机号
-            username = phone.slice(0, 3) + '****' + phone.slice(-4);
-            console.log('该手机号未注册,即将自动创建该用户:' + username + ',密码为:' + password);
-        }
-        //如果用户存在,则直接登录
-        console.log('该手机号已注册,即将直接登录该用户')
-        username = user.get('username');
-        console.log('用户名:' + username + ',密码为:' + password);
-        const response = await fetch(`http://1.94.237.145:1337/parse/login`, {
-            headers: {
-                "x-parse-application-id": "hcx",
-                "Content-Type": "application/json"
-            },
-            body: JSON.stringify({ username, password }), // 假设后端需要这个字段名
-            method: "POST"
-        });
-
-        const result = await response?.json();
-        if (result?.error) {
-            console.error(result?.error);
-            return null;
-        }
-
-        // 设置用户信息
-        this.id = result?.objectId;
-        this.sessionToken = result?.sessionToken;
-        this.updatedAt = result?.updatedAt;
-        this.className = '_User';
-        this.createdAt = result?.createdAt;
-        let excludedKeys = ["objectId", "sessionToken", "createdAt", "updatedAt"];
-        for (let key of excludedKeys) {
-            delete result[key];
-        }
-        this.data = result; // 保存用户数据
-
-        // 缓存用户信息
-        console.log("登录成功后即将缓存的信息如下:");
-        console.log(this);
-        localStorage.setItem("NCloud/hcx/User", JSON.stringify(this));
-        return this;
-    }
-
-
-    /** 登出 */
-    async logout() {
-        if (!this.sessionToken) {
-            console.error("用户未登录");
-            return;
-        }
-
-        const response = await fetch(`http://1.94.237.145:1337/parse/logout`, {
-            headers: {
-                "x-parse-application-id": "hcx",
-                "x-parse-session-token": this.sessionToken
-            },
-            method: "POST"
-        });
-
-        let result = await response?.json();
-
-        if (result?.error) {
-            console.error(result?.error);
-            if (result?.error == "Invalid session token") {
-                this.clearUserCache()
-                return true;
-            }
-            return false;
-        }
-
-        this.clearUserCache()
-        return true;
-    }
-    clearUserCache() {
-        // 清除用户信息
-        localStorage.removeItem("NCloud/hcx/User")
-        this.id = null;
-        this.sessionToken = null;
-        this.data = {};
-    }
-
-    /** 注册 */
-    async signUp(username: string, password: string, additionalData: Record<string, any> = {}) {
-        const userData = {
-            username,
-            password,
-            ...additionalData // 合并额外的用户数据
-        };
-
-        const response = await fetch(`http://1.94.237.145:1337/parse/users`, {
-            headers: {
-                "x-parse-application-id": "hcx",
-                "Content-Type": "application/json"
-            },
-            body: JSON.stringify(userData),
-            method: "POST"
-        });
-
-        const result = await response?.json();
-        if (result?.error) {
-            console.error(result?.error);
-            return null;
-        }
-
-        // 设置用户信息
-        // 缓存用户信息
-        console.log(result)
-        localStorage.setItem("NCloud/hcx/User", JSON.stringify(result))
-        this.id = result?.objectId;
-        this.sessionToken = result?.sessionToken;
-        this.data = result; // 保存用户数据
-        return this;
-    }
-
-    /**
-     * @读取缓存
-     * @读取示例:json{
-     *  id: "5b29481e037c6a007f7d0320",
-     *  className: "_User",
-     *  createdAt: "2018-06-27T09:54:38.815Z",
-     *  updatedAt: "2018-06-27T09:54:38.815Z",
-     *  sessionToken: "<KEY>",
-     *  data: {...}
-     * }
-     */
-    readCache() {
-        console.log("正在执行readCache方法:读取用户缓存信息");
-        let userCacheStr = localStorage.getItem("NCloud/hcx/User")
-        console.log("读取到的用户缓存信息:");
-        console.log(userCacheStr);
-        if (userCacheStr) {
-            let userData = JSON.parse(userCacheStr)
-            console.log(userData)
-            // 设置用户信息
-            console.log(userData?.id)
-            this.id = userData?.id;
-            this.className = "_User";
-            console.log(userData?.updatedAt)
-            this.updatedAt = userData?.updatedAt;
-            console.log(userData?.createdAt)
-            this.createdAt = userData?.createdAt;
-            console.log(userData?.sessionToken)
-            this.sessionToken = userData?.sessionToken;
-            this.data = userData.data // 保存用户数据
-            console.log("用户缓存信息读取完毕:");
-            console.log(this);
-        }
-        return this;
-    }
-}