李佳青 3 місяців тому
батько
коміт
9a71f0d791

+ 2 - 0
package.json

@@ -27,7 +27,9 @@
     "@capacitor/keyboard": "6.0.0",
     "@capacitor/status-bar": "6.0.0",
     "@ionic/angular": "^8.2.2",
+    "@types/parse": "^3.0.9",
     "ionicons": "^7.0.0",
+    "parse": "^5.1.0",
     "rxjs": "~7.8.0",
     "swiper": "^11.1.4",
     "tslib": "^2.3.0",

+ 5 - 1
src/app/app-routing.module.ts

@@ -9,7 +9,11 @@ const routes: Routes = [
   {
     path: 'tab1/person',
     loadChildren: () => import('./tab1-person/tab1-person.module').then(m => m.Tab1PersonPageModule)
-  }
+  },
+  {
+    path: 'user',
+    loadChildren: () => import('../modules/user/user.module').then(m => m.UserModule)
+  },
 ];
 @NgModule({
   imports: [

+ 5 - 0
src/app/app.component.ts

@@ -1,6 +1,11 @@
 import { Component } from '@angular/core';
 import { register } from 'swiper/element/bundle';
 
+// 根组件顶部引用并初始化Parse服务
+import * as Parse from "parse";
+Parse.initialize("dev");
+(Parse as any).serverURL = 'http://web2023.fmode.cn:9999/parse'
+
 register();
 
 @Component({

+ 8 - 6
src/app/tab1/tab1.page.html

@@ -16,12 +16,14 @@
   <!--虚拟身份-->
   <ion-card>
     <ion-item lines="full">
-      <ion-avatar slot="start">
-        <img alt="头像" src="https://ionicframework.com/docs/img/demos/avatar.svg" />
-      </ion-avatar>
-      <ion-label>
-        <ion-note>虚拟身份名</ion-note>
-      </ion-label>
+      <ng-container *ngFor="let person of dePerson">
+        <ion-avatar slot="start">
+          <img alt="头像" [src]="person?.get('avatar')" />
+        </ion-avatar>
+        <ion-label>
+          <ion-note>{{person?.get('name')||'虚拟身份名' }} </ion-note>
+        </ion-label>
+      </ng-container>
       <ion-buttons slot="end">
         <ion-button shape="round">
           <ion-icon name="swap-horizontal-outline"></ion-icon>

+ 21 - 2
src/app/tab1/tab1.page.ts

@@ -1,4 +1,6 @@
 import { Component } from '@angular/core';
+import { ToastController } from '@ionic/angular';
+import * as Parse from "parse"
 
 @Component({
   selector: 'app-tab1',
@@ -7,10 +9,27 @@ import { Component } from '@angular/core';
 })
 export class Tab1Page {
 
-  constructor() { }
+
+  currentUser: Parse.User | undefined
+
+  constructor(private toastCtrl: ToastController,
+  ) { }
   foods = [
     { time: '早饭', content: '五彩虾仁炒饭,营养丰富,早餐最爱' },
     { time: '中饭', content: '蜜汁烤五花肉,经典家常,上桌就光盘' },
     { time: '晚饭', content: '凉拌西蓝花,鲜香可口,美味下饭' },
-  ]
+  ];
+
+  async ngOnInit() {
+    this.dePerson = await this.getPersonDate()
+  }
+  //虚拟角
+  dePerson: Array<Parse.Object> = []
+  async getPersonDate() {
+    let query = new Parse.Query("DePerson");
+    query.equalTo("user", Parse.User.current()?.toPointer())
+    query.include("user")
+    let list = await query.find();
+    return list
+  }
 }

+ 8 - 5
src/app/tab3/tab3.page.html

@@ -24,7 +24,7 @@
         </ng-template>
       </ion-popover>
     </ion-buttons>
-    <ion-buttons slot="end">
+    <ion-buttons slot="end" routerLink="/user/edit/info">
       <ion-button>
         <ion-icon slot="start" name="create-outline"></ion-icon>
       </ion-button>
@@ -37,15 +37,16 @@
     <ion-list [inset]="true">
       <ion-item lines="full">
         <ion-avatar slot="start">
-          <img alt="头像" src="https://ionicframework.com/docs/img/demos/avatar.svg" />
+          <img alt="头像" [src]="user?.get('avatar')" />
         </ion-avatar>
         <ion-label>
-          <ion-note>用户名</ion-note>
+          <ion-note>{{user?.get("name") || '用户名(未登录)'}}</ion-note>
         </ion-label>
       </ion-item>
       <ion-item lines="none">
         <ion-label color="medium">
-          <ion-note>介绍一下自己吧</ion-note>
+          <ion-note *ngIf="!user?.id">请您登陆后继续使用</ion-note>
+          <ion-note *ngIf="user?.id">{{user?.get("desc")||'介绍一下自己吧' }}</ion-note>
         </ion-label>
       </ion-item>
     </ion-list>
@@ -72,4 +73,6 @@
     </ion-list>
   </ion-card>
   <!--退出 -->
-  <ion-button expand="block">退出</ion-button>
+  <!-- 新增:根据用户状态,显示登录/登出按钮,执行跳转或登出函数 -->
+  <ion-button *ngIf="!user?.id" expand="block" routerLink="/user/login">登录</ion-button>
+  <ion-button *ngIf="user?.id" expand="block" (click)="logout()">登出</ion-button>

+ 18 - 3
src/app/tab3/tab3.page.ts

@@ -1,12 +1,27 @@
-import { Component } from '@angular/core';
+import { Component, OnInit } from '@angular/core';
+// 由于Parse本身是js库,在ts中加载需要通过 * as Parse转换一下
+import * as Parse from "parse"
 
 @Component({
   selector: 'app-tab3',
   templateUrl: 'tab3.page.html',
   styleUrls: ['tab3.page.scss']
 })
-export class Tab3Page {
+export class Tab3Page implements OnInit {
 
-  constructor() {}
+  constructor() { };
+
+  // 由于Parse.User.current()是随着localStorage变化的属性
+  // 为了避免首次复制后用户状态变化,页面不同步,通过get方法实现实时获取
+  user: Parse.User | undefined
+  async ngOnInit() {
+    this.user = await Parse.User.current()
+    setInterval(async () => {
+      this.user = await Parse.User.current()
+    }, 1000)
+  }
+  logout() {
+    Parse.User.logOut();
+  }
 
 }

+ 5 - 1
src/app/tabs/tabs-routing.module.ts

@@ -19,6 +19,10 @@ const routes: Routes = [
         path: 'tab3',
         loadChildren: () => import('../tab3/tab3.module').then(m => m.Tab3PageModule)
       },
+      // {
+      //   path: 'tab3',
+      //   loadChildren: () => import('../../modules/user/mine/mine.module').then(mod => mod.MinePageModule)
+      // },
       {
         path: '',
         redirectTo: '/tabs/tab1',
@@ -36,4 +40,4 @@ const routes: Routes = [
 @NgModule({
   imports: [RouterModule.forChild(routes)],
 })
-export class TabsPageRoutingModule {}
+export class TabsPageRoutingModule { }

+ 17 - 0
src/modules/user/edit-info/edit-info-routing.module.ts

@@ -0,0 +1,17 @@
+import { NgModule } from '@angular/core';
+import { Routes, RouterModule } from '@angular/router';
+
+import { EditInfoPage } from './edit-info.page';
+
+const routes: Routes = [
+  {
+    path: '',
+    component: EditInfoPage
+  }
+];
+
+@NgModule({
+  imports: [RouterModule.forChild(routes)],
+  exports: [RouterModule],
+})
+export class EditInfoPageRoutingModule {}

+ 20 - 0
src/modules/user/edit-info/edit-info.module.ts

@@ -0,0 +1,20 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+
+import { IonicModule } from '@ionic/angular';
+
+import { EditInfoPageRoutingModule } from './edit-info-routing.module';
+
+import { EditInfoPage } from './edit-info.page';
+
+@NgModule({
+  imports: [
+    CommonModule,
+    FormsModule,
+    IonicModule,
+    EditInfoPageRoutingModule
+  ],
+  declarations: [EditInfoPage]
+})
+export class EditInfoPageModule {}

+ 29 - 0
src/modules/user/edit-info/edit-info.page.html

@@ -0,0 +1,29 @@
+<ion-header [translucent]="true">
+  <ion-toolbar>
+    <ion-title>{{currentUser?.get('username')}} - {{currentUser?.id}}资料编辑</ion-title>
+    <ion-buttons slot="start">
+      <ion-button routerLink="/tabs/tab3" fill="clear" color="dark">
+        <ion-icon name="chevron-back-outline" size="large"></ion-icon>
+
+      </ion-button>
+    </ion-buttons>
+  </ion-toolbar>
+</ion-header>
+
+<ion-content color="light">
+  <ion-card>
+    <ion-list>
+      <ion-item>
+        <ion-input [(ngModel)]="userInfo.name" label="昵称:"></ion-input>
+      </ion-item>
+      <ion-item>
+        <ion-input [(ngModel)]="userInfo.desc" label="签名:"></ion-input>
+      </ion-item>
+    </ion-list>
+  </ion-card>
+
+  <ion-list [inset]="true">
+    <ion-button expand="block" (click)="save()">保存</ion-button>
+    <ion-button expand="block" (click)="cancel()">取消</ion-button>
+  </ion-list>
+</ion-content>

+ 0 - 0
src/modules/user/edit-info/edit-info.page.scss


+ 17 - 0
src/modules/user/edit-info/edit-info.page.spec.ts

@@ -0,0 +1,17 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { EditInfoPage } from './edit-info.page';
+
+describe('EditInfoPage', () => {
+  let component: EditInfoPage;
+  let fixture: ComponentFixture<EditInfoPage>;
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(EditInfoPage);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 54 - 0
src/modules/user/edit-info/edit-info.page.ts

@@ -0,0 +1,54 @@
+import { Component, OnInit } from '@angular/core';
+import { NavController } from '@ionic/angular';
+import * as Parse from 'parse';
+
+@Component({
+  selector: 'app-edit-info',
+  templateUrl: './edit-info.page.html',
+  styleUrls: ['./edit-info.page.scss'],
+})
+export class EditInfoPage implements OnInit {
+
+  userInfo: any = {
+    name: '',
+    desc: '',
+  };
+  currentUser: Parse.User | undefined
+  constructor(private navController: NavController) { }
+
+  ngOnInit() {
+    this.currentUser = Parse.User.current();
+    if (this.currentUser) {
+      // 修改uesrInfo赋值逻辑,仅加载被编辑的字段属性值
+      let json = this.currentUser.toJSON();
+      for (const key in json) {
+        if (this.userInfo.hasOwnProperty(key)) {
+          this.userInfo[key] = json[key]
+        }
+      }
+    }
+    console.log(this.userInfo)
+  }
+
+  save() {
+    this.currentUser = Parse.User.current();
+    if (this.currentUser) {
+      console.log(this.userInfo)
+      for (const key in this.userInfo) {
+        if (this.userInfo.hasOwnProperty(key)) {
+          this.currentUser.set(key, this.userInfo[key]);
+        }
+      }
+      this.currentUser.save().then(() => {
+        this.navController.back();
+      }).catch((error) => {
+        console.error('Error saving user data: ', error);
+      });
+    }
+  }
+
+  cancel() {
+    this.navController.back();
+  }
+
+}

+ 17 - 0
src/modules/user/login/login-routing.module.ts

@@ -0,0 +1,17 @@
+import { NgModule } from '@angular/core';
+import { Routes, RouterModule } from '@angular/router';
+
+import { LoginPage } from './login.page';
+
+const routes: Routes = [
+  {
+    path: '',
+    component: LoginPage
+  }
+];
+
+@NgModule({
+  imports: [RouterModule.forChild(routes)],
+  exports: [RouterModule],
+})
+export class LoginPageRoutingModule {}

+ 20 - 0
src/modules/user/login/login.module.ts

@@ -0,0 +1,20 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+
+import { IonicModule } from '@ionic/angular';
+
+import { LoginPageRoutingModule } from './login-routing.module';
+
+import { LoginPage } from './login.page';
+
+@NgModule({
+  imports: [
+    CommonModule,
+    FormsModule,
+    IonicModule,
+    LoginPageRoutingModule
+  ],
+  declarations: [LoginPage]
+})
+export class LoginPageModule {}

+ 31 - 0
src/modules/user/login/login.page.html

@@ -0,0 +1,31 @@
+<ion-header>
+  <ion-toolbar>
+    <ion-buttons slot="start">
+      <!-- 新增路由返回逻辑,执行back函数 -->
+      <ion-button (click)="back()" fill="clear" color="dark">
+        <ion-icon name="chevron-back-outline" size="small"></ion-icon>返回
+      </ion-button>
+    </ion-buttons>
+  </ion-toolbar>
+</ion-header>
+<ion-content color="light">
+
+  <div class="login-modal">
+    <ion-card>
+      <ion-card-header>
+        <ion-card-title>登录/注册</ion-card-title>
+        <ion-card-subtitle>该页面需登陆可继续使用</ion-card-subtitle>
+      </ion-card-header>
+
+      <ion-card-content>
+        <ion-input [(ngModel)]="username" placeholder="账号" [clearInput]="true" [counter]="true" maxlength="11">
+        </ion-input>
+        <ion-input [(ngModel)]="password" placeholder="密码" [clearInput]="true" [counter]="true" maxlength="20"
+          type="password">
+        </ion-input>
+      </ion-card-content>
+      <ion-button expand="block" (click)="login()">登录</ion-button>
+      <ion-button expand="block" (click)="register()">注册</ion-button>
+    </ion-card>
+  </div>
+</ion-content>

+ 0 - 0
src/modules/user/login/login.page.scss


+ 17 - 0
src/modules/user/login/login.page.spec.ts

@@ -0,0 +1,17 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { LoginPage } from './login.page';
+
+describe('LoginPage', () => {
+  let component: LoginPage;
+  let fixture: ComponentFixture<LoginPage>;
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(LoginPage);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 93 - 0
src/modules/user/login/login.page.ts

@@ -0,0 +1,93 @@
+import { Component, OnInit } from '@angular/core';
+import { AlertController, NavController } from '@ionic/angular';
+import * as Parse from "parse"
+// 引用Router服务
+@Component({
+  selector: 'app-login',
+  templateUrl: './login.page.html',
+  styleUrls: ['./login.page.scss'],
+})
+export class LoginPage implements OnInit {
+
+  username:string = ""
+  password:string = ""
+  constructor(
+    // 新增:Router服务,用于路由跳转
+    private navCtrl:NavController,
+    private alertController:AlertController
+  ) { }
+
+  ngOnInit() {
+  }
+
+  async login(){
+    let user
+    try {
+      user = await Parse.User.logIn(this.username,this.password)
+    } catch (error:any) {
+      let message:string = ""
+      // 新增提示词详情,根据Parse.User.login方法返回的不同英文提示词,增加对应的中文内容转换
+      if(error?.message.indexOf("is required")>-1){
+        message = "必须输入账号或邮箱"
+      }
+      if(error?.message.indexOf("Invalid username")>-1){
+        message = "账号或密码错误,请检查"
+      }
+      this.presentAlert({
+        header:"登录失败",
+        subHeader:"状态码:"+error.code,
+        message:message || error.message
+      })
+    }
+    console.log(user)
+    if(user?.id){
+      this.navCtrl.back()
+    }
+  }
+  async register(){
+    let user = new Parse.User()
+    user.set("username",this.username)
+    user.set("password",this.password)
+    try {
+        let result = await user.signUp();
+        console.log(result)
+        if(result?.id){
+          this.navCtrl.back()
+        }
+        // Hooray! Let them use the app now.
+    } catch (error:any) {
+        // 新增提示词详情,根据Parse.User.signUp方法返回的不同英文提示词,增加对应的中文内容转换
+        let message:string = ""
+        if(error?.message.indexOf("already exists")>-1){
+          message = "该账号已存在请修改后重试"
+        }
+        if(error?.message.indexOf("empty")>-1){
+          message = "账号不能为空请输入后重试"
+        }
+        this.presentAlert({
+          header:"注册失败",
+          subHeader:"状态码:"+error.code,
+          message:message || error.message
+        })
+    }
+  }
+
+  async presentAlert(options:{header:string,subHeader:string,message:string}) {
+    const alert = await this.alertController.create({
+      header: options?.header,
+      subHeader: options?.subHeader,
+      message: options?.message,
+      buttons: ['好的'],
+    });
+
+    await alert.present();
+  }
+
+  /**
+   * 返回上级页面函数
+   * @desc
+   */
+  back(){
+    this.navCtrl.back()
+  }
+}

+ 13 - 0
src/modules/user/user-routing.module.ts

@@ -0,0 +1,13 @@
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+
+const routes: Routes = [
+    {path: 'login', loadChildren: () => import('./login/login.module').then(mod => mod.LoginPageModule)},
+    {path: 'edit/info', loadChildren: () => import('./edit-info/edit-info.module').then(mod => mod.EditInfoPageModule)},
+];
+
+@NgModule({
+  imports: [RouterModule.forChild(routes)],
+  exports: [RouterModule]
+})
+export class UserRoutingModule { }

+ 14 - 0
src/modules/user/user.module.ts

@@ -0,0 +1,14 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+import { UserRoutingModule } from './user-routing.module';
+
+
+@NgModule({
+  declarations: [],
+  imports: [
+    CommonModule,
+    UserRoutingModule
+  ]
+})
+export class UserModule { }