Bläddra i källkod

feat:modal-login signup

s202226701053 6 månader sedan
förälder
incheckning
42a764b9ba

+ 14 - 0
E-Cover-app/src/agent/tasks/generate/generate-picture.ts

@@ -1,6 +1,7 @@
 import { ModalController } from "@ionic/angular";
 import { ImagineWork, DalleOptions } from 'fmode-ng';
 import { AgentTaskStep } from "src/agent/agent.task";
+import { CloudObject, CloudQuery, CloudUser } from "src/lib/ncloud";
 
 export function TaskGeneratePicture(options: {
     modalCtrl: ModalController
@@ -32,6 +33,19 @@ export function TaskGeneratePicture(options: {
                     options.shareData.images = work?.get("images");
                     clearInterval(countDownInt);
                     task3.progress = 1;
+                    console.log(options.shareData.images[0]);
+                    //将图片url导入数据库
+                    let currentUser = new CloudUser();
+                    let image = options.shareData.images[0];
+                    let designPrompt = JSON.stringify(options.shareData.designPrompt);
+                    let content = designPrompt
+                    let newImageUrl = new CloudObject("GenerateResult");
+                    newImageUrl.set({
+                        "image": image,
+                        "content": content,
+                        "UserID": currentUser.toPointer()
+                    });
+                    newImageUrl.save();
                     resolve(true);
                 }
             })

+ 5 - 3
E-Cover-app/src/app/chat-panel/chat-panel.component.html

@@ -1,6 +1,8 @@
+<!--头部内容,包含标题和返回按钮-->
 <ion-header>
-  <ion-toolbar>
-    <ion-title>Chat</ion-title>
-  </ion-toolbar>
+  <div class="header-container">
+    <ion-icon name="arrow-back-outline" size="large" class="back-icon" (click)="goBack()"></ion-icon>
+    <p class="header-title">个性化生成</p>
+  </div>
 </ion-header>
 <!-- fmode聊天组件 -->

+ 30 - 50
E-Cover-app/src/app/chat-panel/chat-panel.component.scss

@@ -1,53 +1,33 @@
-.chat-container {
-  display: flex;
-  flex-direction: column;
-  justify-content: flex-end;
+ion-header {
+  background-color: #f8f8f8;
   padding: 10px;
-}
-
-.message-content {
-  display: flex;
-  align-items: center;
-  margin-bottom: 10px;
-}
-
-.my-message .message-content {
-  justify-content: flex-end;
-}
-
-.other-message .message-content {
-  justify-content: flex-start;
-}
-
-.my-message .message {
-  background-color: #0078ff; /* 自己的消息背景色 */
-  color: white;
-  border-radius: 20px;
-  padding: 10px 15px;
-  max-width: 70%;
-  word-wrap: break-word;
-  display: inline-block;
-}
-
-.other-message .message {
-  background-color: #f0f0f0; /* 对方的消息背景色 */
+  padding-top: 30px;
   color: black;
-  border-radius: 20px;
-  padding: 10px 15px;
-  max-width: 70%;
-  word-wrap: break-word;
-  display: inline-block;
-}
-
-ion-avatar {
-  margin: 0 10px;
-}
-
-ion-button[disabled] {
-  opacity: 0.5;
-}
-
-ion-input {
-  flex-grow: 1;
-  margin-right: 10px;
+  height: 60px;
+  box-shadow: none;
+
+  .header-container {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    position: relative;
+    height: 100%;
+    /* 确保容器占满整个 header 高度 */
+    padding: 10px;
+  }
+
+  .back-icon {
+    position: absolute;
+    left: 10px;
+    /* 图标距左侧的距离 */
+    cursor: pointer;
+  }
+
+  .header-title {
+    font-size: 18px;
+    /* 根据需要调整字体大小 */
+    font-weight: bold;
+    /* 可选,加粗字体 */
+    margin: 0;
+  }
 }

+ 5 - 3
E-Cover-app/src/app/chat-panel/chat-panel.component.ts

@@ -4,7 +4,7 @@ import { FormsModule } from '@angular/forms';
 import { CommonModule } from '@angular/common';
 import { ActivatedRoute, Router } from '@angular/router';
 import { ChatPanelOptions, FmodeChat, openChatPanelModal } from 'fmode-ng';
-import { ModalController } from '@ionic/angular/standalone';
+import { ModalController, NavController } from '@ionic/angular/standalone';
 
 
 @Component({
@@ -15,9 +15,11 @@ import { ModalController } from '@ionic/angular/standalone';
   imports: [IonicModule, FormsModule, CommonModule],
 })
 export class ChatPanelComponent implements OnInit {
-  constructor(private route: ActivatedRoute,private modalCtrl:ModalController) { }
+  constructor(private route: ActivatedRoute,private modalCtrl:ModalController,private navCtrl:NavController) { }
   ngOnInit() { this.openGenerate() }
-
+  goBack() {
+    this.navCtrl.back();
+  }
   /**
    * @打开聊天窗口
    * 打开fmode聊天窗口的页面

+ 17 - 2
E-Cover-app/src/app/generate-option/generate-option.component.ts

@@ -11,6 +11,8 @@ import { TaskExecutor } from 'src/agent/agent.start';
 import { TaskGeneratePrompt } from 'src/agent/tasks/generate/generate-prompt';
 import { TaskGeneratePicture } from 'src/agent/tasks/generate/generate-picture';
 import { FmodeChat, ChatPanelOptions, FmodeChatMessage, openChatPanelModal } from 'fmode-ng';
+import { CloudUser } from 'src/lib/ncloud';
+import { openUserLoginModal } from 'src/lib/user/modal-user-login/modal-user-login.component';
 addIcons({ 'arrow-back-outline': arrowBackOutline, radioButtonOffOutline, closeCircleOutline, checkmarkCircleOutline, reloadOutline });
 @Component({
   selector: 'app-generate-option',
@@ -248,15 +250,28 @@ export class GenerateOptionComponent implements OnInit {
   }
   /**
    * @发送提示词到下一个页面并跳转到生成结果页面
-   * 1.调用sendMsg方法
-   * 2.调用goChatPanel方法
+   * 1.调用validate方法
+   * 2.调用showJudgePage方法
+   * 3.调用doGenerateTask方法
    */
   sendMsgAndGoGenerateResult() {
+    if(this.validate()){
     this.showJudgePage();
     console.log("展示当前读取到的用户信息:");
     console.log(this.userProfile);
     this.doGenerateTask();
+    }
+  }
 
+  validate(){
+    console.log("开始验证用户信息");
+    let currentUser = new CloudUser();
+    if(!currentUser?.id){
+      console.log("用户未登录,请先登录");
+      openUserLoginModal(this.modalCtrl as any);
+      return false;
+    }
+    return true;
   }
 }
 /**

+ 2 - 2
E-Cover-app/src/app/tab1/tab1.page.html

@@ -59,6 +59,6 @@
     </div>
 </div>
 <ion-content>
-    <h3>数据库渲染测试 {{userInfoList[1].get('name')}}</h3>
-    <h3 *ngFor="let user of userInfoList">{{user.get('name')}}</h3>
+    <h3>数据库渲染测试</h3>
+    <h3 *ngFor="let user of userInfoList">{{ user.get('name')}}</h3>
 </ion-content>

+ 2 - 2
E-Cover-app/src/app/tab1/tab1.page.ts

@@ -16,7 +16,7 @@ addIcons({ 'location-outline': locationOutline, 'notifications-outline': notific
   templateUrl: 'tab1.page.html',
   styleUrls: ['tab1.page.scss'],
   standalone: true,
-  imports: [ExploreContainerComponent, IonicModule,CommonModule],
+  imports: [ExploreContainerComponent, IonicModule, CommonModule],
   schemas: [CUSTOM_ELEMENTS_SCHEMA],
 })
 
@@ -32,7 +32,7 @@ export class Tab1Page {
 
   userInfoList: Array<CloudObject> = [];
   async loadUserInfoList() {
-    let query = new CloudQuery("UserInfo");
+    let query = new CloudQuery("_User");
     this.userInfoList = await query.find();
   }
 }

+ 27 - 15
E-Cover-app/src/app/tab3/tab3.page.html

@@ -1,17 +1,29 @@
-<ion-header [translucent]="true">
-  <ion-toolbar>
-    <ion-title>
-      Tab 3
-    </ion-title>
-  </ion-toolbar>
-</ion-header>
-
 <ion-content [fullscreen]="true">
-  <ion-header collapse="condense">
-    <ion-toolbar>
-      <ion-title size="large">Tab 3</ion-title>
-    </ion-toolbar>
-  </ion-header>
-
-  <app-explore-container name="Tab 3 page"></app-explore-container>
+  <!-- 用户登录状态 -->
+  <ion-card>
+    <!-- 未登录 -->
+     @if(!currentUser?.id){
+       <ion-card-header>
+         <ion-card-title>请登录</ion-card-title>
+         <ion-card-subtitle>暂无信息</ion-card-subtitle>
+        </ion-card-header>
+      }
+        <!-- 未登录 -->
+     @if(currentUser?.id){
+      <ion-card-header>
+        <ion-card-title>{{currentUser?.get("username")}} {{currentUser?.get("realname")}}</ion-card-title>
+        <ion-card-subtitle>性别:{{currentUser?.get("gender")||"-"}} 年龄:{{currentUser?.get("age")||"-"}}</ion-card-subtitle>
+      </ion-card-header>
+      }
+      <ion-card-content>
+      @if(!currentUser?.id){
+        <ion-button expand="block" (click)="signup()">注册</ion-button>
+        <ion-button expand="block" (click)="login()">登录</ion-button>
+      }
+     @if(currentUser?.id){
+      <ion-button expand="block" (click)="editUser()">编辑资料</ion-button>
+      <ion-button expand="block" (click)="logout()" color="light">登出</ion-button>
+    }
+    </ion-card-content>
+  </ion-card>
 </ion-content>

+ 30 - 4
E-Cover-app/src/app/tab3/tab3.page.ts

@@ -1,14 +1,40 @@
 import { Component } from '@angular/core';
-import { IonHeader, IonToolbar, IonTitle, IonContent } from '@ionic/angular/standalone';
-import { ExploreContainerComponent } from '../explore-container/explore-container.component';
+import { IonicModule } from '@ionic/angular';
+import { ModalController } from '@ionic/angular/standalone';
+import { CloudUser,CloudObject } from 'src/lib/ncloud';
+import { openUserLoginModal } from 'src/lib/user/modal-user-login/modal-user-login.component';
 
 @Component({
   selector: 'app-tab3',
   templateUrl: 'tab3.page.html',
   styleUrls: ['tab3.page.scss'],
   standalone: true,
-  imports: [IonHeader, IonToolbar, IonTitle, IonContent, ExploreContainerComponent],
+  imports: [IonicModule],
 })
 export class Tab3Page {
-  constructor() {}
+  currentUser:CloudUser|undefined
+  constructor(private modalCtrl: ModalController) {
+    this.currentUser = new CloudUser();
+  }
+  async login(){
+    //弹窗登录
+    let user=await openUserLoginModal(this.modalCtrl);
+    if(user?.id){
+      this.currentUser = user;
+    }
+
+  }
+  async signup(){
+    //弹窗注册
+    let user=await openUserLoginModal(this.modalCtrl,"signup");
+    if(user?.id){
+      this.currentUser = user;
+    }
+  }
+  logout(){
+    this.currentUser?.logout();
+  }
+  editUser(){
+
+  }
 }

+ 129 - 0
E-Cover-app/src/lib/ncloud.ts

@@ -191,4 +191,133 @@ export class CloudQuery {
         existsObject.updatedAt = exists.updatedAt;
         return existsObject;
     }
+}
+
+// CloudUser.ts
+export class CloudUser extends CloudObject {
+    constructor() {
+        super("_User"); // 假设用户类在Parse中是"_User"
+        // 读取用户缓存信息
+        let userCacheStr = localStorage.getItem("NCloud/hcx/User")
+        if(userCacheStr){
+            let userData = JSON.parse(userCacheStr)
+            // 设置用户信息
+            this.id = userData?.objectId;
+            this.sessionToken = userData?.sessionToken;
+            this.data = userData; // 保存用户数据
+        }
+    }
+
+    sessionToken:string|null = ""
+    /** 获取当前用户信息 */
+    async current() {
+        if (!this.sessionToken) {
+            console.error("用户未登录");
+            return null;
+        }
+        return this;
+        /*const response = await fetch(`http://1.94.237.145:1337/parse/users/me`, {
+            headers: {
+                "x-parse-application-id": "hcx",
+                "x-parse-session-token": this.sessionToken // 使用sessionToken进行身份验证
+            },
+            method: "GET"
+        });
+
+        const result = await response?.json();
+        if (result?.error) {
+            console.error(result?.error);
+            return null;
+        }
+        return result;*/
+    }
+
+    /** 登录 */
+    async login(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.data = result; // 保存用户数据
+        // 缓存用户信息
+        console.log(result)
+        localStorage.setItem("NCloud/hcx/User",JSON.stringify(result))
+        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"
+        });
+
+        const result = await response?.json();
+        if (result?.error) {
+            console.error(result?.error);
+            return false;
+        }
+
+        // 清除用户信息
+        localStorage.removeItem("NCloud/hcx/User")
+        this.id = null;
+        this.sessionToken = null;
+        this.data = {};
+        return true;
+    }
+
+    /** 注册 */
+    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;
+    }
 }

+ 3 - 0
E-Cover-app/src/lib/user/modal-user-edit/modal-user-edit.component.html

@@ -0,0 +1,3 @@
+<p>
+  modal-user-edit works!
+</p>

+ 0 - 0
E-Cover-app/src/lib/user/modal-user-edit/modal-user-edit.component.scss


+ 22 - 0
E-Cover-app/src/lib/user/modal-user-edit/modal-user-edit.component.spec.ts

@@ -0,0 +1,22 @@
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+
+import { ModalUserEditComponent } from './modal-user-edit.component';
+
+describe('ModalUserEditComponent', () => {
+  let component: ModalUserEditComponent;
+  let fixture: ComponentFixture<ModalUserEditComponent>;
+
+  beforeEach(waitForAsync(() => {
+    TestBed.configureTestingModule({
+      imports: [ModalUserEditComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(ModalUserEditComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  }));
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 15 - 0
E-Cover-app/src/lib/user/modal-user-edit/modal-user-edit.component.ts

@@ -0,0 +1,15 @@
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+  selector: 'app-modal-user-edit',
+  templateUrl: './modal-user-edit.component.html',
+  styleUrls: ['./modal-user-edit.component.scss'],
+  standalone: true,
+})
+export class ModalUserEditComponent  implements OnInit {
+
+  constructor() { }
+
+  ngOnInit() {}
+
+}

+ 40 - 0
E-Cover-app/src/lib/user/modal-user-login/modal-user-login.component.html

@@ -0,0 +1,40 @@
+<!-- 用户登录状态 -->
+<ion-card>
+  <ion-card-header>
+    <ion-card-title>
+      <ion-segment [value]="type" (ionChange)="typeChange($event)">
+        <ion-segment-button value="login">
+          <ion-label>登录</ion-label>
+        </ion-segment-button>
+        <ion-segment-button value="signup">
+          <ion-label>注册</ion-label>
+        </ion-segment-button>
+      </ion-segment>
+    </ion-card-title>
+    <ion-card-subtitle>请输入账号密码</ion-card-subtitle>
+  </ion-card-header>
+
+  <ion-card-content>
+    <ion-item>
+      <ion-input [value]="username" (ionChange)="usernameChange($event)" label="账号" placeholder="请输入"></ion-input>
+    </ion-item>
+    <ion-item>
+      <ion-input [value]="password" (ionChange)="passwordChange($event)" label="密码" type="password"
+        value="password"></ion-input>
+    </ion-item>
+    @if(type == 'signup'){
+    <ion-item>
+      <ion-input [value]="password2" (ionChange)="password2Change($event)" label="密码2" type="password"
+        value="password2"></ion-input>
+    </ion-item>
+    }
+    @if(type == 'login'){
+    <ion-button expand="block" (click)="login()">登录</ion-button>
+    }
+    @if(type == 'signup'){
+    <ion-button expand="block" (click)="signup()">注册</ion-button>
+    }
+
+
+  </ion-card-content>
+</ion-card>

+ 0 - 0
E-Cover-app/src/lib/user/modal-user-login/modal-user-login.component.scss


+ 22 - 0
E-Cover-app/src/lib/user/modal-user-login/modal-user-login.component.spec.ts

@@ -0,0 +1,22 @@
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+
+import { ModalUserLoginComponent } from './modal-user-login.component';
+
+describe('ModalUserLoginComponent', () => {
+  let component: ModalUserLoginComponent;
+  let fixture: ComponentFixture<ModalUserLoginComponent>;
+
+  beforeEach(waitForAsync(() => {
+    TestBed.configureTestingModule({
+      imports: [ModalUserLoginComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(ModalUserLoginComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  }));
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 84 - 0
E-Cover-app/src/lib/user/modal-user-login/modal-user-login.component.ts

@@ -0,0 +1,84 @@
+import { Component, Input, OnInit } from '@angular/core';
+import { IonicModule } from '@ionic/angular';
+import { ModalController } from '@ionic/angular/standalone';
+import { CloudUser } from 'src/lib/ncloud';
+
+@Component({
+  selector: 'app-modal-user-login',
+  templateUrl: './modal-user-login.component.html',
+  styleUrls: ['./modal-user-login.component.scss'],
+  standalone: true,
+  imports: [IonicModule],
+})
+export class ModalUserLoginComponent implements OnInit {
+  @Input()
+  type: "login" | "signup" = "login";
+  typeChange(ev: any) {
+    this.type = ev?.detail?.value || ev?.value || 'login';
+  }
+  username: string = "";
+  usernameChange(ev: any) {
+    this.username = ev?.detail?.value;
+  }
+  password: string = "";
+  passwordChange(ev: any) {
+    this.password = ev?.detail?.value;
+  }
+  password2: string = "";
+  password2Change(ev: any) {
+    this.password2 = ev?.detail?.value;
+  }
+  constructor(private modalCtrl: ModalController) { }
+
+  ngOnInit() { }
+
+  async login() {
+    if (!this.username || !this.password) {
+      console.log("请输入完整")
+      return
+    }
+    let user: any = new CloudUser();
+    user = await user.login(this.username, this.password);
+    if (user?.id) {
+      this.modalCtrl.dismiss(user, "confirm")
+    } else {
+      console.log("登录失败");
+    }
+  }
+
+  async signup() {
+    if (!this.username || !this.password || !this.password2) {
+      console.log("请输入完整")
+      return
+    }
+    if (this.password2 != this.password) {
+      console.log("两次密码不一致")
+      return
+    }
+
+    let user: any = new CloudUser();
+    user = await user.signUp(this.username, this.password);
+    if(user){
+      this.type = "login";
+      console.log("注册成功,请登录");
+    }
+
+  }
+}
+
+export async function openUserLoginModal(modalCtrl: ModalController,type:"login"|"signup"="login"): Promise<CloudUser | null> {
+  const modal = await modalCtrl.create({
+    component: ModalUserLoginComponent,
+    componentProps: { type:type },
+    breakpoints: [0.5, 0.7],
+    initialBreakpoint: 0.5
+  });
+  modal.present();
+
+  const { data, role } = await modal.onWillDismiss();
+
+  if (role === 'confirm') {
+    return data;
+  }
+  return null;
+}

+ 16 - 16
E-Cover-server/migration/data.js

@@ -1,4 +1,4 @@
-module.exports.UserInfoList = [
+module.exports._UserList = [
     {
         "UserID": "1",
         "name": "野猪peppa",
@@ -149,7 +149,7 @@ module.exports.UserPreferList = [
         "PreferID": "prefer1",
         "UserID": {
             "__type": "Pointer",
-            "className": "UserInfo",
+            "className": "_User",
             "objectId": "1"
         },
         "ItemID": {
@@ -163,7 +163,7 @@ module.exports.UserPreferList = [
         "PreferID": "prefer2",
         "UserID": {
             "__type": "Pointer",
-            "className": "UserInfo",
+            "className": "_User",
             "objectId": "2"
         },
         "ItemID": {
@@ -177,7 +177,7 @@ module.exports.UserPreferList = [
         "PreferID": "prefer3",
         "UserID": {
             "__type": "Pointer",
-            "className": "UserInfo",
+            "className": "_User",
             "objectId": "3"
         },
         "ItemID": {
@@ -191,7 +191,7 @@ module.exports.UserPreferList = [
         "PreferID": "prefer4",
         "UserID": {
             "__type": "Pointer",
-            "className": "UserInfo",
+            "className": "_User",
             "objectId": "4"
         },
         "ItemID": {
@@ -205,7 +205,7 @@ module.exports.UserPreferList = [
         "PreferID": "prefer5",
         "UserID": {
             "__type": "Pointer",
-            "className": "UserInfo",
+            "className": "_User",
             "objectId": "5"
         },
         "ItemID": {
@@ -219,7 +219,7 @@ module.exports.UserPreferList = [
         "PreferID": "prefer6",
         "UserID": {
             "__type": "Pointer",
-            "className": "UserInfo",
+            "className": "_User",
             "objectId": "6"
         },
         "ItemID": {
@@ -233,7 +233,7 @@ module.exports.UserPreferList = [
         "PreferID": "prefer7",
         "UserID": {
             "__type": "Pointer",
-            "className": "UserInfo",
+            "className": "_User",
             "objectId": "7"
         },
         "ItemID": {
@@ -247,7 +247,7 @@ module.exports.UserPreferList = [
         "PreferID": "prefer8",
         "UserID": {
             "__type": "Pointer",
-            "className": "UserInfo",
+            "className": "_User",
             "objectId": "8"
         },
         "ItemID": {
@@ -261,7 +261,7 @@ module.exports.UserPreferList = [
         "PreferID": "prefer9",
         "UserID": {
             "__type": "Pointer",
-            "className": "UserInfo",
+            "className": "_User",
             "objectId": "9"
         },
         "ItemID": {
@@ -275,7 +275,7 @@ module.exports.UserPreferList = [
         "PreferID": "prefer10",
         "UserID": {
             "__type": "Pointer",
-            "className": "UserInfo",
+            "className": "_User",
             "objectId": "10"
         },
         "ItemID": {
@@ -289,7 +289,7 @@ module.exports.UserPreferList = [
         "PreferID": "prefer11",
         "UserID": {
             "__type": "Pointer",
-            "className": "UserInfo",
+            "className": "_User",
             "objectId": "1"
         },
         "ItemID": {
@@ -303,7 +303,7 @@ module.exports.UserPreferList = [
         "PreferID": "prefer12",
         "UserID": {
             "__type": "Pointer",
-            "className": "UserInfo",
+            "className": "_User",
             "objectId": "2"
         },
         "ItemID": {
@@ -317,7 +317,7 @@ module.exports.UserPreferList = [
         "PreferID": "prefer13",
         "UserID": {
             "__type": "Pointer",
-            "className": "UserInfo",
+            "className": "_User",
             "objectId": "3"
         },
         "ItemID": {
@@ -331,7 +331,7 @@ module.exports.UserPreferList = [
         "PreferID": "prefer14",
         "UserID": {
             "__type": "Pointer",
-            "className": "UserInfo",
+            "className": "_User",
             "objectId": "4"
         },
         "ItemID": {
@@ -345,7 +345,7 @@ module.exports.UserPreferList = [
         "PreferID": "prefer15",
         "UserID": {
             "__type": "Pointer",
-            "className": "UserInfo",
+            "className": "_User",
             "objectId": "5"
         },
         "ItemID": {