Kaynağa Gözat

feat:用户信息表seUser建立与连接

刘嘉轩 7 ay önce
ebeveyn
işleme
5f65916fbf

+ 20 - 0
smarteat-app/package-lock.json

@@ -25,6 +25,7 @@
         "fmode-ng": "^0.0.62",
         "ionicons": "^7.2.1",
         "rxjs": "~7.8.0",
+        "swiper": "^11.1.15",
         "tslib": "^2.3.0",
         "zone.js": "~0.14.2"
       },
@@ -17438,6 +17439,25 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/swiper": {
+      "version": "11.1.15",
+      "resolved": "https://registry.npmmirror.com/swiper/-/swiper-11.1.15.tgz",
+      "integrity": "sha512-IzWeU34WwC7gbhjKsjkImTuCRf+lRbO6cnxMGs88iVNKDwV+xQpBCJxZ4bNH6gSrIbbyVJ1kuGzo3JTtz//CBw==",
+      "funding": [
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/swiperjs"
+        },
+        {
+          "type": "open_collective",
+          "url": "http://opencollective.com/swiper"
+        }
+      ],
+      "license": "MIT",
+      "engines": {
+        "node": ">= 4.7.0"
+      }
+    },
     "node_modules/symbol-observable": {
       "version": "4.0.0",
       "resolved": "https://registry.npmmirror.com/symbol-observable/-/symbol-observable-4.0.0.tgz",

+ 1 - 0
smarteat-app/package.json

@@ -30,6 +30,7 @@
     "fmode-ng": "^0.0.62",
     "ionicons": "^7.2.1",
     "rxjs": "~7.8.0",
+    "swiper": "^11.1.15",
     "tslib": "^2.3.0",
     "zone.js": "~0.14.2"
   },

+ 39 - 82
smarteat-app/src/app/page-edit/page-edit.component.html

@@ -15,7 +15,6 @@
   <ion-item>
     <ion-label>头像 <span style="color: red;">*</span></ion-label>
     <ion-avatar slot="start">
-      <!-- 显示头像,如果没有头像,显示默认头像 -->
       <img [src]="avatar || 'assets/default-avatar.png'" />
     </ion-avatar>
     <ion-button fill="outline" slot="end" (click)="uploadAvatar()">上传头像</ion-button>
@@ -24,136 +23,94 @@
   <!-- 用户名输入框 -->
   <ion-item>
     <ion-label>姓名 <span style="color: red;">*</span></ion-label>
-    <ion-input 
-      labelPlacement="stacked" 
-      [(ngModel)]="name" 
-      placeholder="请输入姓名" 
-      required>
-    </ion-input>
+    <ion-input [value]="name" (ionInput)="nameInput($event)" placeholder="请输入姓名" autoGrow="true"></ion-input>
   </ion-item>
 
   <!-- 邮箱输入框 -->
   <ion-item>
     <ion-label>邮箱 <span style="color: red;">*</span></ion-label>
-    <ion-input 
-      labelPlacement="stacked" 
-      [(ngModel)]="email" 
-      placeholder="请输入邮箱" 
-      type="email" 
-      required
-      [pattern]="emailPattern">
-    </ion-input>
+    <ion-input [value]="email" (ionInput)="emailInput($event)" placeholder="XXX@XX.com" autoGrow="true"></ion-input>
   </ion-item>
 
   <!-- 电话输入框 -->
   <ion-item>
     <ion-label>电话 <span style="color: red;">*</span></ion-label>
-    <ion-input 
-      labelPlacement="stacked" 
-      [(ngModel)]="phone" 
-      placeholder="请输入电话号码" 
-      type="tel" 
-      required
-      [pattern]="phonePattern">
-    </ion-input>
-  </ion-item>
-
-  <!-- 地址输入框 -->
-  <ion-item>
-    <ion-label>地址</ion-label>
-    <ion-input 
-      labelPlacement="stacked" 
-      [(ngModel)]="address" 
-      placeholder="请输入地址">
-    </ion-input>
+    <ion-input [value]="phone" (ionInput)="phoneInput($event)" placeholder="请输入电话号码" autoGrow="true"></ion-input>
   </ion-item>
 
   <!-- 年龄输入框 -->
   <ion-item>
     <ion-label>年龄 <span style="color: red;">*</span></ion-label>
-    <ion-input 
-      labelPlacement="stacked" 
-      [(ngModel)]="age" 
-      placeholder="请输入年龄" 
-      type="number" 
-      required 
-      [min]="0" 
-      [max]="150">
-    </ion-input>
+    <ion-input [value]="age" (ionInput)="ageInput($event)" placeholder="请输入年龄" autoGrow="true"></ion-input>
   </ion-item>
 
   <!-- 性别选择框 -->
   <ion-item>
     <ion-label>性别 <span style="color: red;">*</span></ion-label>
     <ion-select 
-      [(ngModel)]="gender" 
-      interface="popover" 
-      required>
-      <ion-select-option value="male">男</ion-select-option>
-      <ion-select-option value="female">女</ion-select-option>
-      <ion-select-option value="other">其他</ion-select-option>
-    </ion-select>
+    [value]="gender"  
+    (ionChange)="genderInput($event)"  
+    placeholder="请选择性别"
+    interface="popover"
+    required>
+    <ion-select-option value="男">男</ion-select-option>
+    <ion-select-option value="女">女</ion-select-option>
+    <ion-select-option value="other">其他</ion-select-option>
+  </ion-select>
   </ion-item>
 
   <!-- 身高输入框 -->
   <ion-item>
     <ion-label>身高(cm) <span style="color: red;">*</span></ion-label>
-    <ion-input 
-      labelPlacement="stacked" 
-      [(ngModel)]="height" 
-      placeholder="请输入身高" 
-      type="number" 
-      required
-      [min]="0" 
-      [pattern]="heightPattern">
-    </ion-input>
+    <ion-input [value]="height" (ionInput)="heightInput($event)" placeholder="请输入身高" autoGrow="true"></ion-input>
   </ion-item>
 
   <!-- 体重输入框 -->
   <ion-item>
     <ion-label>体重(kg) <span style="color: red;">*</span></ion-label>
-    <ion-input 
-      labelPlacement="stacked" 
-      [(ngModel)]="weight" 
-      placeholder="请输入体重" 
-      type="number" 
-      required
-      [min]="0" 
-      [pattern]="weightPattern">
-    </ion-input>
+    <ion-input [value]="weight" (ionInput)="weightInput($event)" placeholder="请输入体重" autoGrow="true"></ion-input>
   </ion-item>
 
   <!-- 活动水平选择框 -->
   <ion-item>
     <ion-label>活动水平</ion-label>
-    <ion-select [(ngModel)]="activityLevel" interface="popover">
-      <ion-select-option value="low">低</ion-select-option>
-      <ion-select-option value="moderate">中</ion-select-option>
-      <ion-select-option value="high">高</ion-select-option>
+    <ion-select [value]="activityLevel"
+    (ionChange)="activityLevelInput($event)"  
+    placeholder="请选择活动水平"
+    interface="popover"
+    required>
+      <ion-select-option value="低">低</ion-select-option>
+      <ion-select-option value="中">中</ion-select-option>
+      <ion-select-option value="高">高</ion-select-option>
     </ion-select>
   </ion-item>
 
-  <!-- 饮食偏好选择框 -->
+  <!-- 更新后的饮食偏好选择框 -->
   <ion-item>
     <ion-label>饮食偏好 <span style="color: red;">*</span></ion-label>
     <ion-select 
-      [(ngModel)]="dietPreference" 
+      [value]="dietPreference" 
+      (ionChange)="dietPreferenceInput($event)"  
+      placeholder="请选择活动水平"
       interface="popover" 
       required>
-      <ion-select-option value="vegetarian">素食</ion-select-option>
-      <ion-select-option value="nonVegetarian">非素食</ion-select-option>
-      <ion-select-option value="vegan">纯素</ion-select-option>
-      <ion-select-option value="glutenFree">无麸质</ion-select-option>
+      <ion-select-option value="无麸质饮食">无麸质饮食</ion-select-option>
+      <ion-select-option value="低碳水化合物饮食">低碳水化合物饮食</ion-select-option>
+      <ion-select-option value="低脂饮食">低脂饮食</ion-select-option>
+      <ion-select-option value="高蛋白饮食">高蛋白饮食</ion-select-option>
+      <ion-select-option value="无要求">无要求</ion-select-option>
     </ion-select>
   </ion-item>
 
   <!-- 饮食群体输入框 -->
   <ion-item>
     <ion-label>饮食群体 <span style="color: red;">*</span></ion-label>
-    <ion-input 
-      labelPlacement="stacked" 
-      [(ngModel)]="dietGroup" 
-      placeholder="请输入饮食群体">
-    </ion-input>
+    <ion-input [value]="dietGroup" (ionInput)="dietGroupInput($event)" placeholder="请输入饮食群体" autoGrow="true"></ion-input>
+  </ion-item>
+
+  <!-- 新增过敏信息输入框 -->
+  <ion-item>
+    <ion-label>过敏信息 <span style="color: red;">*</span></ion-label>
+    <ion-input [value]="allergies" (ionInput)="allergiesInput($event)" placeholder="请输入过敏信息" autoGrow="true"></ion-input>
   </ion-item>
 </ion-content>

+ 104 - 54
smarteat-app/src/app/page-edit/page-edit.component.ts

@@ -1,5 +1,6 @@
 import { Component, OnInit } from '@angular/core';
 import { ModalController } from '@ionic/angular';
+import { CloudSeUser } from 'src/lib/cloudSeuser';  // 引入CloudSeUser类
 import { IonicModule } from '@ionic/angular';
 import { FormsModule } from '@angular/forms';
 
@@ -11,12 +12,11 @@ import { FormsModule } from '@angular/forms';
   standalone: true,
 })
 export class PageEditComponent implements OnInit {
-  
+
   // 初始化表单字段
   name: string = '';
   email: string = '';
   phone: string = '';
-  address: string = '';
   age: number | null = null;
   gender: string = '';
   height: number | null = null;
@@ -25,6 +25,45 @@ export class PageEditComponent implements OnInit {
   dietPreference: string = '';
   dietGroup: string = '';
   avatar: string | null = null;
+  allergies: string = '';
+
+  nameInput(ev: any) {
+    this.name = ev.detail.value;
+  }
+  emailInput(ev: any) {
+    this.email = ev.detail.value;
+  }
+  phoneInput(ev: any) {
+    this.phone = ev.detail.value;
+  }
+  ageInput(ev: any) {
+    this.age = ev.detail.value;
+  }
+  genderInput(ev: any) {
+    this.gender = ev.detail.value;
+  }
+  heightInput(ev: any) {
+    this.height = ev.detail.value;
+  }
+  weightInput(ev: any) {
+    this.weight = ev.detail.value;
+  }
+  activityLevelInput(ev: any) {
+    this.activityLevel = ev.detail.value;
+  }
+  dietPreferenceInput(ev: any) {
+    this.dietPreference = ev.detail.value;
+  }
+  dietGroupInput(ev: any) {
+    this.dietGroup = ev.detail.value;
+  }
+  avatarInput(ev: any) {
+    this.avatar = ev.detail.value;
+  }
+  allergiesInput(ev: any) {
+    this.allergies = ev.detail.value;
+  }
+
 
   // 正则表达式
   emailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;
@@ -32,85 +71,96 @@ export class PageEditComponent implements OnInit {
   heightPattern = /^[1-9][0-9]{1,2}$/;
   weightPattern = /^[1-9][0-9]{1,2}$/;
 
-  constructor(private modalCtrl: ModalController) {}
+  cloudSeUser: CloudSeUser;  // 引入CloudSeUser实例
 
-  ngOnInit(): void {
-    this.loadSavedData();  // 加载上次保存的数据
+  constructor(private modalCtrl: ModalController) {
+    this.cloudSeUser = new CloudSeUser();  // 实例化CloudSeUser
   }
 
-  // 加载上次保存的数据
-  loadSavedData() {
-    const savedData = JSON.parse(localStorage.getItem('userData') || '{}');
-
-    if (savedData) {
-      // 使用本地存储的数据填充表单
-      this.name = savedData.name || '';
-      this.email = savedData.email || '';
-      this.phone = savedData.phone || '';
-      this.address = savedData.address || '';
-      this.age = savedData.age || null;
-      this.gender = savedData.gender || '';
-      this.height = savedData.height || null;
-      this.weight = savedData.weight || null;
-      this.activityLevel = savedData.activityLevel || '';
-      this.dietPreference = savedData.dietPreference || '';
-      this.dietGroup = savedData.dietGroup || '';
-      this.avatar = savedData.avatar || null;
-    }
+  ngOnInit(): void {
+    this.loadUserData();  // 页面初始化时加载用户数据
   }
 
-  // 保存数据至本地存储
-  saveData() {
-    const userData = {
-      name: this.name,
-      email: this.email,
-      phone: this.phone,
-      address: this.address,
-      age: this.age,
-      gender: this.gender,
-      height: this.height,
-      weight: this.weight,
-      activityLevel: this.activityLevel,
-      dietPreference: this.dietPreference,
-      dietGroup: this.dietGroup,
-      avatar: this.avatar
-    };
-    localStorage.setItem('userData', JSON.stringify(userData)); // 将数据保存至本地
+  // 从 seUser 表加载当前用户数据
+  async loadUserData() {
+    try {
+      const userData = await this.cloudSeUser.getCurrentUserInfo();
+      if (userData) {
+        // 通过 get() 方法获取 CloudSeUser 中的数据
+        this.name = userData.get('name') || '';  
+        this.email = userData.get('email') || '';  
+        this.phone = userData.get('phone') || '';  
+        this.age = userData.get('age') || null;  
+        this.gender = userData.get('gender') || '';  
+        this.height = userData.get('height') || null;  
+        this.weight = userData.get('weight') || null;  
+        this.activityLevel = userData.get('activityLevel') || '';  
+        this.dietPreference = userData.get('dietPreference') || '';  
+        this.dietGroup = userData.get('dietGroup') || '';  
+        this.avatar = userData.get('avatar') || null;  
+        this.allergies = userData.get('allergies') || '';  
+      }
+    } catch (error) {
+      console.error('加载用户数据失败', error);
+    }
   }
 
+  // 取消操作,关闭页面
   cancel() {
-    return this.modalCtrl.dismiss(null, 'cancel');
+    this.modalCtrl.dismiss();
   }
 
-  confirm() {
+  // 确认操作,提交用户数据
+  async confirm() {
     // 验证表单内容是否完整
     if (!this.name || !this.email || !this.phone || !this.age || !this.gender || !this.height || !this.weight || !this.dietPreference || !this.dietGroup) {
       alert("请确保所有必填项已填写!");
       return;
     }
 
-    // 保存用户输入的数据
-    this.saveData();
-
-    // 返回数据给父组件
     const userData = {
       name: this.name,
       email: this.email,
       phone: this.phone,
-      address: this.address,
-      age: this.age,
+      age: Number(this.age),
       gender: this.gender,
-      height: this.height,
-      weight: this.weight,
+      height: Number(this.height),  // 转换 height 为 Number
+      weight: Number(this.weight),  // 转换 weight 为 Number
       activityLevel: this.activityLevel,
       dietPreference: this.dietPreference,
       dietGroup: this.dietGroup,
-      avatar: this.avatar
+      avatar: this.avatar,
+      allergies: this.allergies
     };
-
-    return this.modalCtrl.dismiss(userData, 'confirm');
+    try {
+      // 判断是否已有用户数据,如果存在则更新,否则创建新用户
+      const userDataFromServer = await this.cloudSeUser.getCurrentUserInfo();
+      if (userDataFromServer) {
+        // 如果已有数据,执行更新
+        const updatedUser = await this.cloudSeUser.updateUserInfo(userData);
+        if (updatedUser) {
+          console.log("用户信息更新成功");
+          this.modalCtrl.dismiss();  // 更新成功后关闭页面
+        } else {
+          alert("更新失败,请稍后再试");
+        }
+      } else {
+        // 如果没有用户数据,执行保存(创建新用户)
+        const newUser = await this.cloudSeUser.saveUserInfo(userData);
+        if (newUser) {
+          console.log("新用户信息保存成功");
+          this.modalCtrl.dismiss();  // 保存成功后关闭页面
+        } else {
+          alert("保存失败,请稍后再试");
+        }
+      }
+    } catch (error) {
+      console.error("保存用户数据时出错", error);
+      alert("保存数据时出错,请稍后再试");
+    }
   }
 
+  // 上传头像
   uploadAvatar() {
     const input = document.createElement('input');
     input.type = 'file';

+ 18 - 0
smarteat-app/src/app/tab1/tab1.page.html

@@ -4,6 +4,24 @@
   </ion-toolbar>
 
 <ion-content [fullscreen]="true">
+   <!-- 轮播图区域 -->
+   <div class="carousel-container" style="border-radius: 25px; margin: 5px auto;">
+    <div class="carousel" [style.transform]="'translateX(-' + currentSlide * 100 + '%)'">
+      <div class="slide" *ngFor="let image of images">
+        <img [src]="image" alt="轮播图">
+      </div>
+    </div>
+  
+    <button class="prev" (click)="prevSlide()">&#10094;</button>
+    <button class="next" (click)="nextSlide()">&#10095;</button>
+  
+    <div class="dots">
+      <span class="dot" *ngFor="let image of images; let i = index" 
+            [class.active]="i === currentSlide" 
+            (click)="goToSlide(i)"></span>
+    </div>
+  </div>
+
 <!-- 推荐健康建议 -->
 <ion-card>
 <ion-card-header>

+ 68 - 0
smarteat-app/src/app/tab1/tab1.page.scss

@@ -1,3 +1,71 @@
+//   /* 设置轮播图区域 */
+.carousel-container {
+  position: relative;
+  overflow: hidden;
+  width: 100%;
+  max-width: 600px; /* 可根据需要调整宽度 */
+  margin: 0 auto;
+}
+
+.carousel {
+  display: flex;
+  transition: transform 0.5s ease;
+}
+
+.slide {
+  min-width: 100%;
+  max-width: 100%;
+}
+
+.slide img {
+  width: 100%;
+  height: auto;
+  border-radius: 15px;
+}
+
+button {
+  position: absolute;
+  top: 50%;
+  transform: translateY(-50%);
+  background: rgba(0, 0, 0, 0.5);
+  color: #fff;
+  border: none;
+  padding: 10px;
+  cursor: pointer;
+  z-index: 10;
+}
+
+button.prev {
+  left: 10px;
+}
+
+button.next {
+  right: 10px;
+}
+
+.dots {
+  position: absolute;
+  bottom: 10px;
+  left: 50%;
+  transform: translateX(-50%);
+  display: flex;
+  justify-content: center;
+}
+
+.dot {
+  width: 10px;
+  height: 10px;
+  margin: 0 5px;
+  background-color: rgba(255, 255, 255, 0.5);
+  border-radius: 50%;
+  cursor: pointer;
+}
+
+.dot.active {
+  background-color: #fff;
+}
+
+
 /* 设置所有矩形框为圆角矩形 */
 ion-card {
     border-radius: 12px; /* 卡片圆角 */

+ 39 - 2
smarteat-app/src/app/tab1/tab1.page.ts

@@ -2,21 +2,58 @@ import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
 import { IonicModule} from '@ionic/angular'; // 导入 IonicModule
 import { addIcons } from 'ionicons';
 import { ExploreContainerComponent } from '../explore-container/explore-container.component';
-import {  albumsOutline, documentOutline, leafOutline, scanOutline, storefrontOutline } from 'ionicons/icons';
+import { albumsOutline, documentOutline, leafOutline, scanOutline, storefrontOutline } from 'ionicons/icons';
 import { Router } from '@angular/router';
+import { CommonModule } from '@angular/common';  // 导入 CommonModule
+
 
 @Component({
   selector: 'app-tab1',
   templateUrl: 'tab1.page.html',
   styleUrls: ['tab1.page.scss'],
   standalone: true, // 使用 standalone 组件
-  imports: [IonicModule, ExploreContainerComponent],  // 通过 IonicModule 导入所有 Ionic 组件
+  imports: [IonicModule, ExploreContainerComponent,CommonModule],  // 通过 IonicModule 导入所有 Ionic 组件
   schemas: [CUSTOM_ELEMENTS_SCHEMA], 
 })
 export class Tab1Page {
+
   constructor(private router: Router) {
     addIcons({scanOutline, documentOutline, storefrontOutline,albumsOutline,leafOutline});
   }
+  
+  // 存储图片的数组
+  images = [
+    'https://example.com/image1.jpg',
+    'https://example.com/image2.jpg',
+    'https://example.com/image3.jpg',
+    'https://example.com/image4.jpg'
+  ];
+
+  // 当前显示的幻灯片索引
+  currentSlide: number = 0;
+
+  // 前一个幻灯片
+  prevSlide() {
+    if (this.currentSlide > 0) {
+      this.currentSlide--;
+    } else {
+      this.currentSlide = this.images.length - 1; // 如果是第一个幻灯片,跳转到最后一个
+    }
+  }
+
+  // 后一个幻灯片
+  nextSlide() {
+    if (this.currentSlide < this.images.length - 1) {
+      this.currentSlide++;
+    } else {
+      this.currentSlide = 0; // 如果是最后一个幻灯片,跳转到第一个
+    }
+  }
+
+  // 跳转到指定的幻灯片
+  goToSlide(index: number) {
+    this.currentSlide = index;
+  }
 
   goHealthTips(){
     this.router.navigate([`/tabs/tips`])

+ 2 - 0
smarteat-app/src/global.scss

@@ -35,3 +35,5 @@
 /* @import "@ionic/angular/css/palettes/dark.always.css"; */
 /* @import "@ionic/angular/css/palettes/dark.class.css"; */
 @import '@ionic/angular/css/palettes/dark.system.css';
+
+// @import 'swiper/swiper-bundle.min.css';

+ 155 - 0
smarteat-app/src/lib/cloudSeuser.ts

@@ -0,0 +1,155 @@
+import { CloudUser, CloudObject, CloudQuery } from './ncloud'; // 引入 CloudUser 类,用于获取当前用户
+
+export class CloudSeUser extends CloudObject {
+    constructor() {
+        super("seUser"); // 假设 seUser 类在 Parse 中是 "seUser"
+    }
+
+    /** 获取单个用户信息 */
+    async getUser(id: string) {
+        const url = `http://dev.fmode.cn:1337/parse/classes/seUser/${id}?`;
+
+        const response = await fetch(url, {
+            headers: {
+                "x-parse-application-id": "dev"
+            },
+            method: "GET",
+            mode: "cors",
+            credentials: "omit"
+        });
+
+        const result = await response?.json();
+        if (result?.error) {
+            console.error(result?.error);
+            return null;
+        }
+
+        return this.dataToObj(result);
+    }
+
+    /** 获取当前登录用户的 `seUser` 信息 */
+    async getCurrentUserInfo() {
+        const cloudUser = new CloudUser();
+        const currentUser = await cloudUser.current();
+
+        if (!currentUser) {
+            console.error("用户未登录");
+            return null;
+        }
+
+        const currentUserId = currentUser.objectId;
+
+        // 通过 _User 的 objectId 查询 seUser 表中的记录
+        const query = new CloudQuery("seUser");
+        query.equalTo("user", { "__type": "Pointer", "className": "_User", "objectId": currentUserId });
+
+        const seUser = await query.first();
+        return seUser;
+    }
+
+    /** 创建或保存用户信息 */
+    async saveUserInfo(userData: Record<string, any>) {
+        const cloudUser = new CloudUser();
+        const currentUser = await cloudUser.current();
+
+        if (!currentUser) {
+            console.error("用户未登录");
+            return null;
+        }
+
+        const userPointer = { "__type": "Pointer", "className": "_User", "objectId": currentUser.objectId };
+
+        const newUserInfo = {
+            ...userData,
+            user: userPointer // 将当前用户作为外键关联到 seUser 表
+        };
+
+        const url = `http://dev.fmode.cn:1337/parse/classes/seUser`;
+
+        const response = await fetch(url, {
+            headers: {
+                "Content-Type": "application/json",
+                "x-parse-application-id": "dev"
+            },
+            method: "POST",
+            body: JSON.stringify(newUserInfo),
+            mode: "cors",
+            credentials: "omit"
+        });
+
+        const result = await response?.json();
+        if (result?.error) {
+            console.error(result?.error);
+            return null;
+        }
+
+        return this.dataToObj(result);
+    }
+
+    /** 更新当前用户的信息 */
+    async updateUserInfo(updatedData: Record<string, any>) {
+        const cloudUser = new CloudUser();
+        const currentUser = await cloudUser.current();
+
+        if (!currentUser) {
+            console.error("用户未登录");
+            return null;
+        }
+
+        const currentUserId = currentUser.objectId;
+
+        // 查找当前用户的 seUser 信息
+        const query = new CloudQuery("seUser");
+        query.equalTo("user", { "__type": "Pointer", "className": "_User", "objectId": currentUserId });
+
+        const seUser = await query.first();
+        if (!seUser) {
+            console.error("未找到用户信息");
+            return null;
+        }
+
+        // 更新信息
+        seUser.set(updatedData);
+        await seUser.save();
+
+        return seUser;
+    }
+
+    /** 删除当前用户的 seUser 信息 */
+    async deleteUserInfo() {
+        const cloudUser = new CloudUser();
+        const currentUser = await cloudUser.current();
+
+        if (!currentUser) {
+            console.error("用户未登录");
+            return false;
+        }
+
+        const currentUserId = currentUser.objectId;
+
+        // 查找当前用户的 seUser 信息
+        const query = new CloudQuery("seUser");
+        query.equalTo("user", { "__type": "Pointer", "className": "_User", "objectId": currentUserId });
+
+        const seUser = await query.first();
+        if (!seUser) {
+            console.error("未找到用户信息");
+            return false;
+        }
+
+        // 删除 seUser 记录
+        await seUser.destroy();
+
+        return true;
+    }
+
+    /** 将查询结果转换为 CloudObject */
+    private dataToObj(result: any): CloudObject {
+        let userObject = new CloudObject(this.className);
+        userObject.set(result);
+        userObject.id = result.objectId;
+        userObject.createdAt = result.createdAt;
+        userObject.updatedAt = result.updatedAt;
+        return userObject;
+    }
+}

+ 75 - 0
smarteat-app/src/lib/import-data.js

@@ -0,0 +1,75 @@
+fetch("http://dev.fmode.cn:1337/parse/classes/seUser?", {
+    "headers": {
+      "accept": "*/*",
+      "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
+      "x-parse-application-id": "dev"
+    },
+    "referrer": "http://127.0.0.1:4040/",
+    "referrerPolicy": "strict-origin-when-cross-origin",
+    "body": null,
+    "method": "GET",
+    "mode": "cors",
+    "credentials": "omit"
+  });
+
+fetch("http://dev.fmode.cn:1337/parse/classes/seUser?", {
+  "headers": {
+    "accept": "*/*",
+    "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
+    "if-none-match": "W/\"e-24vRBFXLdkiGHboJ0qD/fA5L4XI\"",
+    "x-parse-application-id": "dev"
+  },
+  "referrer": "http://127.0.0.1:4040/",
+  "referrerPolicy": "strict-origin-when-cross-origin",
+  "body": null,
+  "method": "GET",
+  "mode": "cors",
+  "credentials": "omit"
+});
+
+
+
+
+  fetch("http://dev.fmode.cn:1337/parse/classes/seUser", {
+    "headers": {
+      "accept": "*/*",
+      "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
+      "content-type": "text/plain;charset=UTF-8",
+      "x-parse-application-id": "dev"
+    },
+    "referrer": "http://127.0.0.1:4040/",
+    "referrerPolicy": "strict-origin-when-cross-origin",
+    "body": "",
+    "method": "POST",
+    "mode": "cors",
+    "credentials": "omit"
+  });
+
+  fetch("http://dev.fmode.cn:1337/parse/classes/seUser", {
+    "headers": {
+      "accept": "*/*",
+      "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
+      "content-type": "text/plain;charset=UTF-8",
+      "x-parse-application-id": "dev"
+    },
+    "referrer": "http://127.0.0.1:4040/",
+    "referrerPolicy": "strict-origin-when-cross-origin",
+    "body": "",
+    "method": "PUT",
+    "mode": "cors",
+    "credentials": "omit"
+  });
+
+  fetch("http://dev.fmode.cn:1337/parse/classes/seUser", {
+    "headers": {
+      "accept": "*/*",
+      "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
+      "x-parse-application-id": "dev"
+    },
+    "referrer": "http://127.0.0.1:4040/",
+    "referrerPolicy": "strict-origin-when-cross-origin",
+    "body": null,
+    "method": "DELETE",
+    "mode": "cors",
+    "credentials": "omit"
+  });

+ 158 - 1
smarteat-app/src/lib/ncloud.ts

@@ -317,4 +317,161 @@ export class CloudUser extends CloudObject {
         this.data = result; // 保存用户数据
         return this;
     }
-}
+}
+// import { CloudUser,CloudObject,CloudQuery } from './ncloud'; // 引入 CloudUser 类,用于获取当前用户
+
+export class CloudSeUser extends CloudObject {
+    constructor() {
+        super("seUser"); // 假设seUser类在Parse中是"seUser"
+    }
+
+    // 获取单个用户信息
+    async getUser(id: string) {
+        const url = `http://dev.fmode.cn:1337/parse/classes/seUser/${id}?`;
+
+        const response = await fetch(url, {
+            headers: {
+                "x-parse-application-id": "dev"
+            },
+            method: "GET",
+            mode: "cors",
+            credentials: "omit"
+        });
+
+        const result = await response?.json();
+        if (result?.error) {
+            console.error(result?.error);
+            return null;
+        }
+
+        let userObject = this.dataToObj(result);
+        return userObject;
+    }
+
+    // 获取当前登录用户的 `seUser` 信息
+    async getCurrentUserInfo() {
+        const cloudUser = new CloudUser();
+        const currentUser = await cloudUser.current();
+        
+        if (!currentUser) {
+            console.error("用户未登录");
+            return null;
+        }
+
+        const currentUserId = currentUser.objectId;
+
+        // 通过 _User 的 objectId 查询 seUser 表中的记录
+        const query = new CloudQuery("seUser");
+        query.equalTo("user", { "__type": "Pointer", "className": "_User", "objectId": currentUserId });
+
+        const seUser = await query.first();
+        return seUser;
+    }
+
+    // 添加新的用户信息
+    async createUserInfo(additionalData: Record<string, any>) {
+        const cloudUser = new CloudUser();
+        const currentUser = await cloudUser.current();
+        
+        if (!currentUser) {
+            console.error("用户未登录");
+            return null;
+        }
+
+        const userPointer = { "__type": "Pointer", "className": "_User", "objectId": currentUser.objectId };
+
+        const newUserInfo = {
+            ...additionalData,
+            user: userPointer // 将当前用户作为外键关联到 seUser 表
+        };
+
+        const url = `http://dev.fmode.cn:1337/parse/classes/seUser`;
+
+        const response = await fetch(url, {
+            headers: {
+                "Content-Type": "application/json",
+                "x-parse-application-id": "dev"
+            },
+            method: "POST",
+            body: JSON.stringify(newUserInfo),
+            mode: "cors",
+            credentials: "omit"
+        });
+
+        const result = await response?.json();
+        if (result?.error) {
+            console.error(result?.error);
+            return null;
+        }
+
+        let newSeUser = this.dataToObj(result);
+        return newSeUser;
+    }
+
+    // 更新当前用户的信息
+    async updateUserInfo(updatedData: Record<string, any>) {
+        const cloudUser = new CloudUser();
+        const currentUser = await cloudUser.current();
+
+        if (!currentUser) {
+            console.error("用户未登录");
+            return null;
+        }
+
+        const currentUserId = currentUser.objectId;
+
+        // 查找当前用户的 seUser 信息
+        const query = new CloudQuery("seUser");
+        query.equalTo("user", { "__type": "Pointer", "className": "_User", "objectId": currentUserId });
+
+        const seUser = await query.first();
+        if (!seUser) {
+            console.error("未找到用户信息");
+            return null;
+        }
+
+        // 更新信息
+        seUser.set(updatedData);
+        await seUser.save();
+
+        return seUser;
+    }
+
+    // 删除当前用户的 seUser 信息
+    async deleteUserInfo() {
+        const cloudUser = new CloudUser();
+        const currentUser = await cloudUser.current();
+
+        if (!currentUser) {
+            console.error("用户未登录");
+            return false;
+        }
+
+        const currentUserId = currentUser.objectId;
+
+        // 查找当前用户的 seUser 信息
+        const query = new CloudQuery("seUser");
+        query.equalTo("user", { "__type": "Pointer", "className": "_User", "objectId": currentUserId });
+
+        const seUser = await query.first();
+        if (!seUser) {
+            console.error("未找到用户信息");
+            return false;
+        }
+
+        // 删除 seUser 记录
+        await seUser.destroy();
+
+        return true;
+    }
+
+    // 将查询结果转换为 CloudObject
+    dataToObj(result: any): CloudObject {
+        let userObject = new CloudObject(this.className);
+        userObject.set(result);
+        userObject.id = result.objectId;
+        userObject.createdAt = result.createdAt;
+        userObject.updatedAt = result.updatedAt;
+        return userObject;
+    }
+}