Ver Fonte

个人主页完善数据库

何何何 há 1 ano atrás
pai
commit
a7a5bfabc2

+ 27 - 23
paint-app/src/app/tab3/tab3.page.html

@@ -9,9 +9,6 @@
 
   <!-- 控件区域 -->
   <ion-list>
-    <ion-item>
-      <ion-label>账号资料</ion-label>
-    </ion-item>
     <ion-item>
       <ion-label>安全隐私</ion-label>
     </ion-item>
@@ -55,7 +52,8 @@
   </ion-list>
   <!-- 退出登录按钮 -->
   <div style="text-align: center; margin: 30px;">
-    <ion-button expand="block" color="danger">退出登录</ion-button>
+
+    <ion-button expand="block" (click)="logout()">登出</ion-button>
   </div>
     </ion-content>
   </ion-menu>
@@ -70,33 +68,38 @@
       </ion-toolbar>
     </ion-header>
     <ion-content>   
-      <!-- 用户信息区域 -->
-      <!-- <ion-list class="top-list">
-        <ion-item (click)="router.navigate([userInfoPage])">
-          <ion-avatar slot="start">
-            <img src="../../assets/icon/bd.jpg"/>
-          </ion-avatar>
-          <ion-label>
-            <h2>{{ userName }}</h2>
-            <p>账号: {{ userPhone }}</p>
-          </ion-label>
-          <ion-icon name="chevron-forward" slot="end"></ion-icon>
-        </ion-item>
-      </ion-list>
-      <div style="text-align: center; margin: 10px;"></div>  -->
       <div class="box">
         <div class="top">
           <div class="region">
             <div class="upper">
+              @if(!currentUser?.id){
+              <div class="img-box">
+                <img src="../../assets/icon/head1.png" alt="User Image" />
+              </div>
+              <div class="info">
+                <div class="name">未登录</div>
+                <div class="no">***********</div>
+              </div>
+            }
+            @if(currentUser?.id){
               <div class="img-box">
-                <img src="../../assets/icon/tou1.jpg" alt="User Image" />
+                <img src="../../assets/icon/head1.png" alt="User Image" />
               </div>
               <div class="info">
-                <div class="name">海棠花</div>
-                <div class="no">1517656799</div>
+                <div class="name">{{currentUser?.get("realname")}}</div>
+                <div class="no">邮箱:{{currentUser?.get("email")||"-"}}</div>
               </div>
+              }
             </div>
           </div>
+          @if(!currentUser?.id){
+            <div class="lower1">
+    
+            <ion-button expand="block" class="custom-button" (click)="login()">登录</ion-button>
+            <ion-button expand="block"class="custom-button"  (click)="signup()">注册</ion-button>  
+          </div>
+          }
+          @if(currentUser?.id){
           <div class="lower">落霞与孤鹜齐飞,天水共长天一色</div>
           <div class="count">
             <div class="title">
@@ -105,8 +108,9 @@
               <span>获赞:99</span>
             </div>
           </div>
+        }
         </div>
-  </div>
+   </div>
   <div class="icon-container">
     <div class="icon-item">
       <ion-icon name="folder-outline"></ion-icon>
@@ -166,7 +170,7 @@
   <div style="margin-top: 60px;width: 100%;">
     <div style="width: 100%;padding-left: 20px;"><p class="left-align">更多服务:</p></div>
   <ion-list lines="none">
-    <ion-item>
+    <ion-item (click)="!currentUser?.id ? showAlert() : editUser()">
       <ion-icon slot="start" name="person-outline" style="font-size: 20px;"></ion-icon>
       <ion-label>个人信息</ion-label>
       <ion-icon slot="end" name="chevron-forward-outline" style="color: lightgray;"></ion-icon>

+ 15 - 0
paint-app/src/app/tab3/tab3.page.scss

@@ -105,6 +105,21 @@
   font-size: 16px; 
   color: #b3dffe;
 }
+.lower1 {
+  width: 200px;
+  height: 10px;
+  display: flex;
+  margin: auto;
+  flex-direction: column; /* 设置为垂直方向 */
+}
+
+.custom-button {
+  color: #b3dffe;
+}
+
+.custom-button:hover {
+  --background: rgba(255, 255, 255, 0.7); /* 悬停时背景颜色变亮 */
+}
 
 .count {
   display: flex; /* 使用弹性盒布局,使子元素能够灵活排列 */

+ 61 - 4
paint-app/src/app/tab3/tab3.page.ts

@@ -6,19 +6,76 @@ import { addIcons } from 'ionicons';
 import {folderOutline,timeOutline,starOutline,heartOutline,chevronForwardOutline,personOutline,shieldOutline,callOutline,lockClosedOutline} from 'ionicons/icons';
 addIcons({folderOutline,timeOutline,starOutline,heartOutline,chevronForwardOutline,personOutline,shieldOutline,callOutline,lockClosedOutline})
 
+import { CloudUser } from 'src/lib/ncloud';
+import { openUserEditModal } from 'src/lib/user/modal-user-edit/modal-user-edit.component';
+import { openUserLoginModal } from 'src/lib/user/modal-user-login/modal-user-login.component';
+import { Router } from '@angular/router';
+import { ModalController } from '@ionic/angular/standalone';
+import { AlertController } from '@ionic/angular/standalone'; // 导入所需的模块
 @Component({
   selector: 'app-tab3',
   templateUrl: 'tab3.page.html',
   styleUrls: ['tab3.page.scss'],
   standalone: true,
-  imports: [CommonModule,IonIcon,IonLabel,IonList,IonButton,IonMenu,IonToolbar,IonMenuButton,IonTitle,IonButtons,IonItem,IonHeader,IonContent,IonBadge],
+  imports: [CommonModule,IonIcon,IonLabel,IonList,IonButton,IonMenu,IonToolbar,IonMenuButton,IonTitle,IonButtons,IonItem,IonHeader,IonContent,IonBadge
+  ],
 })
 export class Tab3Page {
 
   public environmentInjector = inject(EnvironmentInjector);
-  constructor() {
-    addIcons({ folderOutline,timeOutline,starOutline,heartOutline});
-  }
 
+ currentUser:CloudUser|undefined
+   constructor(
+    private alertController: AlertController,
+     private router: Router,
+     private modalCtrl:ModalController) {
+     addIcons({ folderOutline,timeOutline,starOutline,heartOutline});
+     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(){
+     openUserEditModal(this.modalCtrl)
+   }
+ 
+   editTags:Array<String>=[]
+    async setTagsValue(ev:any){
+     let currentUser = new CloudUser();
+     let userPrompt = ``
+     if(!currentUser?.id){
+       console.log("用户未登录,请登录后重试");
+       let user = await openUserLoginModal(this.modalCtrl);
+       if(!user?.id){
+         return
+       }
+       currentUser = user;
+     }
+   //console.log("setTagsValue",ev);
+   this.editTags=ev;
+ }
+ async showAlert() {
+  const alert = await this.alertController.create({
+    header: '提示', // 提示框的标题
+    message: '请先登录以查看个人信息。', // 提示框的消息
+    buttons: ['确定'], // 按钮文本,用户点击后关闭提示框
+  });
+
+  await alert.present(); // 显示提示框
+}
 }

+ 5 - 0
paint-app/src/app/tabs/tabs.routes.ts

@@ -41,6 +41,11 @@ export const routes: Routes = [
         loadComponent: () =>
           import('../page-test/page-test.component').then((m) => m.PageTestComponent),
       },
+      {
+        path: 'test2-page',
+        loadComponent: () =>
+          import('../test2-page/test2-page.component').then((m) => m.Test2PageComponent),
+      },
       {
         path: '',
         redirectTo: '/tabs/tab1',

+ 27 - 0
paint-app/src/app/test2-page/test2-page.component.html

@@ -0,0 +1,27 @@
+<!-- 用户登录状态 -->
+<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>

+ 0 - 0
paint-app/src/app/test2-page/test2-page.component.scss


+ 22 - 0
paint-app/src/app/test2-page/test2-page.component.spec.ts

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

+ 62 - 0
paint-app/src/app/test2-page/test2-page.component.ts

@@ -0,0 +1,62 @@
+import { Component } from '@angular/core';
+import { Router } from '@angular/router';
+import { IonHeader, IonToolbar, IonTitle, IonContent, IonCard, IonCardContent, IonButton, IonCardHeader, IonCardTitle, IonCardSubtitle, ModalController } from '@ionic/angular/standalone';
+import { CloudUser } from 'src/lib/ncloud';
+import { openUserEditModal } from 'src/lib/user/modal-user-edit/modal-user-edit.component';
+import { openUserLoginModal } from 'src/lib/user/modal-user-login/modal-user-login.component';
+
+@Component({
+  selector: 'app-test2-page',
+  templateUrl: './test2-page.component.html',
+  styleUrls: ['./test2-page.component.scss'],
+  standalone: true,
+  imports: [IonHeader, IonToolbar, IonTitle, IonContent, 
+    IonCard,IonCardContent,IonButton,IonCardHeader,IonCardTitle,IonCardSubtitle
+  ],
+})
+export class Test2PageComponent  {
+  currentUser:CloudUser|undefined
+  constructor(
+    private router: Router,
+    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(){
+    openUserEditModal(this.modalCtrl)
+  }
+
+  editTags:Array<String>=[]
+   async setTagsValue(ev:any){
+    let currentUser = new CloudUser();
+    let userPrompt = ``
+    if(!currentUser?.id){
+      console.log("用户未登录,请登录后重试");
+      let user = await openUserLoginModal(this.modalCtrl);
+      if(!user?.id){
+        return
+      }
+      currentUser = user;
+    }
+  //console.log("setTagsValue",ev);
+  this.editTags=ev;
+}
+
+}

BIN
paint-app/src/assets/icon/head1.png


BIN
paint-app/src/assets/icon/head2.png


+ 126 - 0
paint-app/src/lib/ncloud.ts

@@ -191,4 +191,130 @@ 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/dev/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;
+        }
+        
+        const response = await fetch(`http://dev.fmode.cn:1337/parse/users/me`, {
+            headers: {
+                "x-parse-application-id": "dev",
+                "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://dev.fmode.cn:1337/parse/login`, {
+            headers: {
+                "x-parse-application-id": "dev",
+                "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/dev/User",JSON.stringify(result))
+        return this;
+    }
+
+    /** 登出 */
+    async logout() {
+        if (!this.sessionToken) {
+            console.error("用户未登录");
+            return;
+        }
+
+        const response = await fetch(`http://dev.fmode.cn:1337/parse/logout`, {
+            headers: {
+                "x-parse-application-id": "dev",
+                "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/dev/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://dev.fmode.cn:1337/parse/users`, {
+            headers: {
+                "x-parse-application-id": "dev",
+                "Content-Type": "application/json"
+            },
+            body: JSON.stringify(userData),
+            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; // 保存用户数据
+        return this;
+    }
 }

+ 29 - 0
paint-app/src/lib/user/modal-user-edit/modal-user-edit.component.html

@@ -0,0 +1,29 @@
+<!-- 用户登录状态 -->
+<ion-card>
+  <ion-card-header>
+    <ion-card-title>
+      用户名:{{currentUser?.get("username")}}
+    </ion-card-title>
+    <ion-card-subtitle>请输入您的详细资料</ion-card-subtitle>
+   </ion-card-header>
+ <ion-card-content>
+
+   <ion-item>
+     <ion-input [value]="userData['realname']" (ionChange)="userDataChange('realname',$event)" label="姓名" placeholder="请您输入真实姓名"></ion-input>
+   </ion-item>
+   <ion-item>
+     <ion-input type="number" [value]="userData['age']" (ionChange)="userDataChange('age',$event)" label="年龄" placeholder="请您输入年龄"></ion-input>
+    </ion-item>
+  <ion-item>
+     <ion-input [value]="userData['gender']" (ionChange)="userDataChange('gender',$event)" label="性别" placeholder="请您输入男/女"></ion-input>
+    </ion-item>
+    <ion-item>
+      <ion-input [value]="userData['avatar']" (ionChange)="userDataChange('avatar',$event)" label="头像" placeholder="请您输入头像地址"></ion-input>
+     </ion-item>
+
+   <ion-button expand="block" (click)="save()">保存</ion-button>
+   <ion-button expand="block" (click)="cancel()">取消</ion-button>
+ 
+
+</ion-card-content>
+</ion-card>

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


+ 22 - 0
paint-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();
+  });
+});

+ 73 - 0
paint-app/src/lib/user/modal-user-edit/modal-user-edit.component.ts

@@ -0,0 +1,73 @@
+import { Input, OnInit } from '@angular/core';
+import { Component } from '@angular/core';
+import { IonHeader, IonToolbar, IonTitle, IonContent, IonCard, IonCardContent, IonButton, IonCardHeader, IonCardTitle, IonCardSubtitle, ModalController, IonInput, IonItem, IonSegment, IonSegmentButton, IonLabel } from '@ionic/angular/standalone';
+import { CloudUser } from 'src/lib/ncloud';
+
+@Component({
+  selector: 'app-modal-user-edit',
+  templateUrl: './modal-user-edit.component.html',
+  styleUrls: ['./modal-user-edit.component.scss'],
+  standalone: true,
+  imports: [IonHeader, IonToolbar, IonTitle, IonContent, 
+    IonCard,IonCardContent,IonButton,IonCardHeader,IonCardTitle,IonCardSubtitle,
+    IonInput,IonItem,
+    IonSegment,IonSegmentButton,IonLabel
+  ],
+})
+export class ModalUserEditComponent  implements OnInit {
+
+  currentUser:CloudUser|undefined
+  userData:any = {}
+  userDataChange(key:string,ev:any){
+    let value = ev?.detail?.value
+    if(value){
+      this.userData[key] = value
+    }
+  }
+  constructor(private modalCtrl:ModalController) { 
+    this.currentUser = new CloudUser();
+    this.userData = this.currentUser.data;
+  }
+
+  ngOnInit() {}
+
+  async save(){
+    Object.keys(this.userData).forEach(key=>{
+      if(key=="age"){
+        this.userData[key] = Number(this.userData[key])
+      }
+    })
+
+    this.currentUser?.set(this.userData)
+    await this.currentUser?.save()
+    this.modalCtrl.dismiss(this.currentUser,"confirm")
+  }
+  cancel(){
+    this.modalCtrl.dismiss(null,"cancel")
+
+  }
+}
+// 导出一个异步函数,用于打开用户编辑模态框并返回编辑后的用户信息
+export async function openUserEditModal(modalCtrl: ModalController): Promise<CloudUser | null> {
+  
+  // 创建模态框实例,指定要显示的组件和模态框的高度设置
+  const modal = await modalCtrl.create({
+    component: ModalUserEditComponent, // 指定模态框中要显示的组件
+    breakpoints: [0.7, 1.0], // 设置模态框的可调整高度的断点
+    initialBreakpoint: 1.0 // 设置模态框初始显示的高度为 70%
+  });
+
+  // 显示模态框
+  modal.present();
+
+  // 等待模态框关闭,并获取关闭时传递的数据和角色
+  const { data, role } = await modal.onWillDismiss();
+
+  // 如果模态框是通过确认操作关闭,返回传递的数据
+  if (role === 'confirm') {
+    return data; // 返回用户编辑后的数据
+  }
+
+  // 如果模态框是通过取消或其他方式关闭,返回 null
+  return null;
+}

+ 36 - 0
paint-app/src/lib/user/modal-user-login/modal-user-login.component.html

@@ -0,0 +1,36 @@
+<!-- 用户登录状态 -->
+<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="密码二次" type="password" value="password"></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
paint-app/src/lib/user/modal-user-login/modal-user-login.component.scss


+ 22 - 0
paint-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();
+  });
+});

+ 94 - 0
paint-app/src/lib/user/modal-user-login/modal-user-login.component.ts

@@ -0,0 +1,94 @@
+import { Input, OnInit } from '@angular/core';
+import { Component } from '@angular/core';
+import { IonHeader, IonToolbar, IonTitle, IonContent, IonCard, IonCardContent, IonButton, IonCardHeader, IonCardTitle, IonCardSubtitle, ModalController, IonInput, IonItem, IonSegment, IonSegmentButton, IonLabel } 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: [IonHeader, IonToolbar, IonTitle, IonContent, 
+    IonCard,IonCardContent,IonButton,IonCardHeader,IonCardTitle,IonCardSubtitle,
+    IonInput,IonItem,
+    IonSegment,IonSegmentButton,IonLabel
+  ],
+})
+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){
+    console.log(ev)
+    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) {
+    console.log(this.type)
+   }
+
+  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.password!=this.password2){
+      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
+}