瀏覽代碼

update:tab3 page

cainiao-hue 4 月之前
父節點
當前提交
8d3eb1d0d3

+ 0 - 1
docs-prod/schema.md

@@ -28,7 +28,6 @@ class ChatPartner {
 class ChatRecord {
     + objectId: String //聊天记录唯一标识符
     + title:String //聊天标题
-    + timestamp: Date //聊天时间
     + content:String //聊天内容
     - chatList: Array //聊天记录
     + user: Pointer<User> //关联的用户对象

+ 15 - 4
soul-app/src/app/tab2/tab2.page.html

@@ -27,9 +27,9 @@
             </ion-avatar>
             <ion-label>
               <h2>{{ chatpartner.get('name') }}</h2>
-              <p>专业领域:{{ chatpartner.get('expertise') }}</p>
+              <p style="font-size: 15px;">专业领域:{{ chatpartner.get('expertise') }}</p>
             </ion-label>
-            <ion-button slot="end" (click)="clickToConsult(chatpartner)">开始陪聊</ion-button>
+            <ion-button slot="end" (click)="clickToConsult(chatpartner)" style="margin-left: 10px;">开始陪聊</ion-button>
           </ion-item>
         </ion-list>
       </ion-card-content>
@@ -38,13 +38,24 @@
 
   <!-- 陪聊服务区 -->
   <section>
-    <ion-card>
+    <!--<ion-card>
       <ion-card-header>
         <ion-card-title>普通聊天</ion-card-title>
       </ion-card-header>
       <ion-card-content>
         <p>在这里,无论是生活上的开心,还是工作上的糟糕,你都可以跟我分享,这里是属于你一个人的空间,你可以大胆放心的使用。</p>
-        <ion-button expand="full" (click)="goChat()">开始聊天</ion-button>
+        <ion-button expand="block" color="danger" (click)="goChat()">开始聊天</ion-button>
+      </ion-card-content>
+    </ion-card>-->
+    <ion-card>
+      <ion-card-header>
+        <div style="display: flex; justify-content: space-between; align-items: center;">
+          <ion-card-title style="flex: 1;">普通聊天</ion-card-title>
+          <ion-button (click)="goChat()" style="margin-left: 0px;">开始聊天</ion-button>
+        </div>
+      </ion-card-header>
+      <ion-card-content>
+        <p style="font-size: 16px; text-indent:2em;">在这里,无论是生活上的开心,还是工作上的糟糕,你都可以跟我分享,这里是属于你一个人的空间,你可以大胆放心的使用。</p>
       </ion-card-content>
     </ion-card>
   </section>

+ 18 - 6
soul-app/src/app/tab2/tab2.page.ts

@@ -7,7 +7,8 @@ import { CommonModule } from '@angular/common';
 import { Router } from '@angular/router';
 import { ChatPanelOptions, FmodeChat, FmodeChatMessage, openChatPanelModal } from 'fmode-ng';
 import { ModalController } from '@ionic/angular/standalone';
-import { CloudObject, CloudQuery } from 'src/lib/ncloud';
+import { CloudObject, CloudQuery, CloudUser } from 'src/lib/ncloud';
+import { openUserLoginModal } from 'src/lib/user/modal-user-login/modal-user-login.component';
 
 @Component({
   selector: 'app-tab2',
@@ -30,15 +31,26 @@ export class Tab2Page {
     this.modalCtrl = modalCtrl;
     // 其他构造函数代码
   }
-  clickToConsult(chatpartner:CloudObject) {
+  async clickToConsult(chatpartner:CloudObject) {
+    // 验证用户登录
+    let currentUser = new CloudUser();
+    if(!currentUser?.id){
+      console.log("用户未登录,请登录后重试")
+      let user = await openUserLoginModal(this.modalCtrl)
+      if(!user?.id){
+        return
+      }
+    }
     // 弹窗形式聊天:开始咨询
     localStorage.setItem("company","E4KpGvTEto")
+
     let consult = new CloudObject("ChatRecord")
     let now = new Date();
     let dateStr = `${now.getFullYear()}-${now.getMonth()+1}-${now.getDate()}`
     consult.set({
-      title:`${chatpartner.get('expertise') || ""}聊天记录${dateStr}-${chatpartner.get('name')}`,
+      title:`${chatpartner.get('expertise') || ""}领域聊天记录${dateStr}-${chatpartner.get('name')}`,
       chatpartner:chatpartner.toPointer(),
+      user:currentUser.toPointer()
     })
     let options:ChatPanelOptions = {
       roleId:"2DXJkRsjXK",
@@ -53,7 +65,7 @@ export class Tab2Page {
         # 角色设定
         您是${chatpartner.get("name")},一位${chatpartner.get("bio")},${chatpartner.get("expertise")},需要为用户提供陪伴和支持等积极情绪。
         # 对话环节
-        用户提及到关于不想聊了、不想说了、有事先走了类似的话语,耐心积极开导回复结束后请在消息结尾附带: [聊天结束]
+        每次回复用户消息都在消息结尾附带[祝你有愉快的一天]
         # 开始话语
         当您准备好了,可以以一个关心用户的朋友的身份,向来访的用户打招呼。
         `);
@@ -62,8 +74,8 @@ export class Tab2Page {
         console.log("onMessage",message)
         let content:any = message?.content
         if(typeof content == "string"){
-          if(content?.indexOf("[聊天结束]")>-1){
-            console.log("聊天结束")
+          if(content?.indexOf("[祝你有愉快的一天]")>-1){
+            console.log("对话结束")
             consult.set({
               content:content
             })

+ 1 - 0
soul-app/src/app/tab3/README.md

@@ -0,0 +1 @@
+{{currentUser?.get("realname")}}

+ 38 - 16
soul-app/src/app/tab3/tab3.page.html

@@ -7,16 +7,44 @@
 </ion-header>
 
 <ion-content [fullscreen]="true">
-  <!-- 用户信息区域 -->
-  <div class="user-info">
-    <ion-avatar>
-      <img src="assets/avatar-default.png" alt="头像">
-    </ion-avatar>
-    <div class="user-details">
-      <h2>用户名</h2>
-      <p>ID: 12345678</p>
-    </div>
-  </div>
+
+
+  <!-- 用户登录状态 -->
+  <ion-card>
+    <!-- 未登录 -->
+     @if(!currentUser?.id){
+       <ion-card-header>
+         <ion-card-title>未登录,请先登录</ion-card-title>
+        </ion-card-header>
+      }
+        <!-- 已登录 -->
+     @if(currentUser?.id){
+      <ion-card-header>
+        <div style="display: flex; align-items: center;">
+          <img src="{{currentUser?.get('avatar')}}" alt="头像" style="width: 50px; height: 50px; border-radius: 50%; margin-right: 10px;">
+          <div>
+            <ion-card-title>{{currentUser?.get("username")}} </ion-card-title>
+            <ion-card-subtitle style="font-size: 16px;">性别: {{currentUser?.get("gender") || "-"}} 年龄: {{currentUser?.get("age") || "-"}}</ion-card-subtitle>
+          </div>
+        </div>
+
+      </ion-card-header>
+      }
+      <ion-card-content>
+      @if(!currentUser?.id){
+        <div style="display: flex; justify-content: space-between;">
+          <!--<ion-button expand="block"  color="danger" (click)="signup()" style="flex: 1; margin-right: 5px;">注册</ion-button>-->
+          <ion-button expand="block"  color="danger" (click)="login()" style="flex: 1; margin-left: 5px;">登录</ion-button>
+        </div>
+      }
+     @if(currentUser?.id){
+      <div style="display: flex; justify-content: space-between;">
+      <ion-button expand="block"  color="danger" (click)="editUser()" style="flex: 1; margin-right: 5px;">编辑资料</ion-button>
+      <ion-button expand="block"  color="danger" (click)="logout()" style="flex: 1; margin-right: 5px;">登出</ion-button>
+      </div>
+    }
+    </ion-card-content>
+  </ion-card>
 
   <!-- 功能列表 -->
   <ion-list>
@@ -56,10 +84,4 @@
     </ion-item>
   </ion-list>
 
-  <!-- 退出登录按钮 -->
-  <div class="logout-button">
-    <ion-button expand="block" color="danger">
-      退出登录
-    </ion-button>
-  </div>
 </ion-content>

+ 28 - 45
soul-app/src/app/tab3/tab3.page.ts

@@ -1,62 +1,45 @@
 import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
-import { 
-  IonHeader, 
-  IonToolbar, 
-  IonTitle, 
-  IonContent, 
-  IonList,
-  IonItem,
-  IonIcon,
-  IonLabel,
-  IonButton,
-  IonAvatar
-} from '@ionic/angular/standalone';
+import { IonHeader, IonToolbar, IonTitle, IonContent, IonList,IonItem,IonIcon,IonLabel,IonButton,IonAvatar,
+  IonCard,IonCardContent, IonCardHeader, IonCardSubtitle, IonCardTitle} from '@ionic/angular/standalone';
 import { ExploreContainerComponent } from '../explore-container/explore-container.component';
-import { addIcons } from 'ionicons';
-import { 
-  personOutline, 
-  heartOutline, 
-  notificationsOutline, 
-  settingsOutline, 
-  informationCircleOutline,
-  chevronForwardOutline 
-} from 'ionicons/icons';
+import { CloudUser } from 'src/lib/ncloud';
+import { openUserLoginModal } from 'src/lib/user/modal-user-login/modal-user-login.component';
+import { ModalController } from '@ionic/angular/standalone';
 
 @Component({
   selector: 'app-tab3',
   templateUrl: 'tab3.page.html',
   styleUrls: ['tab3.page.scss'],
   standalone: true,
-  imports: [
-    IonHeader, 
-    IonToolbar, 
-    IonTitle, 
-    IonContent, 
-    IonList,
-    IonItem,
-    IonIcon,
-    IonLabel,
-    IonButton,
-    IonAvatar,
+  imports: [IonHeader,IonToolbar,IonTitle,IonContent,IonList,IonItem,IonIcon,IonLabel,IonButton,IonAvatar,
+    IonCard,IonCardContent,IonCardHeader,IonCardTitle,IonCardSubtitle,
     ExploreContainerComponent
   ],
   schemas: [CUSTOM_ELEMENTS_SCHEMA]
 })
 export class Tab3Page {
-  constructor() {
-    // 注册图标
-    addIcons({
-      personOutline, 
-      heartOutline, 
-      notificationsOutline, 
-      settingsOutline, 
-      informationCircleOutline,
-      chevronForwardOutline
-    });
+
+  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
+    }
+    //直接登录测试
+    //let user:any = new CloudUser();
+    //user = await user.login("馒头","123");
+  }
+  logout(){
+    this.currentUser?.logout();
+  }
+  signup(){
+
   }
+  editUser(){
 
-  // 退出登录方法
-  logout() {
-    console.log('退出登录');
   }
 }

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

@@ -218,4 +218,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;
+        }
+        return this;
+        //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;
+    }
 }

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

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

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


+ 22 - 0
soul-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
soul-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() {}
+
+}

+ 36 - 0
soul-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"  color="danger" (click)="login()" style="flex: 1; margin-left: 5px;">登录</ion-button>
+    }
+    @if(type==="signup"){
+      <ion-button expand="block"  color="danger" (click)="signup()" style="flex: 1; margin-right: 5px;">注册</ion-button>
+    }
+  </ion-card-content>
+</ion-card>

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


+ 22 - 0
soul-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
soul-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
+}