Browse Source

个人主页

warrior 3 months ago
parent
commit
de358deddf

+ 19 - 6
projects/live-app/src/moduls/live/chat/chat.component.html

@@ -115,20 +115,22 @@
       labelPlacement="stacked"
       [clearInput]="true"
       placeholder="和ta说点什么"
-      [(ngModel)]="msg"
+      [(ngModel)]="text"
+      (keydown)="comfirmText($event)"
     >
     </ion-input>
     <div class="tools" slot="end">
-      <ion-icon name="happy-outline"></ion-icon>
+      <ion-icon name="happy-outline" (click)="changeShowEmoji()"></ion-icon>
       <ion-icon name="videocam-outline"></ion-icon>
-      <ion-icon name="gift-outline"></ion-icon>
+      <ion-icon name="gift-outline" (click)="isOpen = true"></ion-icon>
       <span class="splice">|</span>
       <!-- <div class="send">发送</div> -->
       <ion-button
         class="send"
         fill="outline"
         size="small"
-        [disabled]="msg.length == 0"
+        [disabled]="text.length == 0"
+        (click)="comfirmText()"
         >发送</ion-button
       >
     </div>
@@ -141,8 +143,8 @@
     <div class="emoji-box">
       @for (item of emojis; track $index) {
       <div class="emoji-item">
-        <div class="emoji-img" (click)="emojiChoose(item)">
-          {{ item?.char }}
+        <div class="emoji-img" (click)="emojiChoose(item.char)">
+          {{ item.char }}
         </div>
       </div>
       }
@@ -156,3 +158,14 @@
   </div>
   }
 </ion-footer>
+<ion-modal
+  (click)="isOpen = false"
+  (didDismiss)="dismiss($event)"
+  [isOpen]="isOpen"
+  [initialBreakpoint]="0.5"
+  [breakpoints]="[0, 0.5, 1]"
+>
+  <ng-template>
+    <div class="block">Block of Content</div>
+  </ng-template>
+</ion-modal>

+ 32 - 1
projects/live-app/src/moduls/live/chat/chat.component.scss

@@ -97,7 +97,38 @@
     }
   }
 }
-
+.emoji-content {
+  background: #fbfbfb;
+  height: 160px;
+  overflow-y: scroll;
+  .emoji-box {
+    display: flex;
+    flex-wrap: wrap;
+    width: 100%;
+    .emoji-item {
+      width: 30px;
+      height:30px;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      .emoji-img{
+        width: 20px;
+        height: 20px;
+      }
+    }
+    .emoji-item__del {
+      width: 30px;
+      height:30px;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      .emoji-img{
+        width: 20px;
+        height: 20px;
+      }
+    }
+  }
+}
 ion-popover {
   --width: 150px;
 }

+ 165 - 97
projects/live-app/src/moduls/live/chat/chat.component.ts

@@ -2,7 +2,16 @@ import { DatePipe } from '@angular/common';
 import { HttpClient } from '@angular/common/http';
 import { Component, OnInit } from '@angular/core';
 import { FormsModule } from '@angular/forms';
-import { IonicModule, ScrollDetail } from '@ionic/angular';
+import {
+  IonicModule,
+  LoadingController,
+  ModalController,
+  ScrollDetail,
+  ToastController,
+} from '@ionic/angular';
+// import * as JIMServ from '../../services/common/jim';
+// var JIM = JIMServ.JIM;
+// var Events = JIMServ.Events;
 import * as Parse from 'parse';
 
 @Component({
@@ -15,10 +24,10 @@ import * as Parse from 'parse';
 })
 export class ChatComponent implements OnInit {
   targetUser: any = {
-    name: '小兰花',
+    name: '紫霞仙子',
     avatar: '',
   };
-  msg: string = '';
+  text: string = '';
   list: any = {
     data: [
       {
@@ -74,116 +83,133 @@ export class ChatComponent implements OnInit {
   height: number = 0;
   showEmoji: boolean = false;
   showMore: boolean = false;
-  emojis: Array<any> = []
+  emojis: Array<any> = [];
+  isOpen: boolean = false;
+  currentScroll: number = 0; //滚动条位置
+  constructor(
+    private http: HttpClient,
+    public datePipe: DatePipe,
+    private modalController: ModalController,
+    public toastController: ToastController,
+    private loadingCtrl: LoadingController
+  ) {}
 
-  constructor(private http: HttpClient, public datePipe: DatePipe) {}
-
-  ngOnInit() {}
+  ngOnInit() {
+    this.initEmoji();
+  }
   initEmoji() {
     let emojiChar =
-      "☺-😋-😌-😍-😏-😜-😝-😞-😔-😪-😁-😂-😃-😅-😆-👿-😒-😓-😔-😏-😖-😘-😚-😒-😡-😢-😣-😤-😢-😨-😳-😵-😷-😸-😻-😼-😽-😾-😿-🙊-🙋-🙏-✈-🚇-🚃-🚌-🍄-🍅-🍆-🍇-🍈-🍉-🍑-🍒-🍓-🐔-🐶-🐷-👦-👧-👱-👩-👰-👨-👲-👳-💃-💄-💅-💆-💇-🌹-💑-💓-💘-🚲";
+      '☺-😋-😌-😍-😏-😜-😝-😞-😔-😪-😁-😂-😃-😅-😆-👿-😒-😓-😔-😏-😖-😘-😚-😒-😡-😢-😣-😤-😢-😨-😳-😵-😷-😸-😻-😼-😽-😾-😿-🙊-🙋-🙏-✈-🚇-🚃-🚌-🍄-🍅-🍆-🍇-🍈-🍉-🍑-🍒-🍓-🐔-🐶-🐷-👦-👧-👱-👩-👰-👨-👲-👳-💃-💄-💅-💆-💇-🌹-💑-💓-💘-🚲';
 
     let emojiKey = [
-      "60a",
-      "60b",
-      "60c",
-      "60d",
-      "60f",
-      "61b",
-      "61d",
-      "61e",
-      "61f",
-      "62a",
-      "62c",
-      "602",
-      "603",
-      "605",
-      "606",
-      "608",
-      "612",
-      "613",
-      "614",
-      "615",
-      "616",
-      "618",
-      "619",
-      "620",
-      "621",
-      "623",
-      "624",
-      "625",
-      "627",
-      "629",
-      "633",
-      "635",
-      "637",
-      "63a",
-      "63b",
-      "63c",
-      "63d",
-      "63e",
-      "63f",
-      "64a",
-      "64b",
-      "64f",
-      "681",
-      "68a",
-      "68b",
-      "68c",
-      "344",
-      "345",
-      "346",
-      "347",
-      "348",
-      "349",
-      "351",
-      "352",
-      "353",
-      "414",
-      "415",
-      "416",
-      "466",
-      "467",
-      "468",
-      "469",
-      "470",
-      "471",
-      "472",
-      "473",
-      "483",
-      "484",
-      "485",
-      "486",
-      "487",
-      "490",
-      "491",
-      "493",
-      "498",
-      "6b4",
+      '60a',
+      '60b',
+      '60c',
+      '60d',
+      '60f',
+      '61b',
+      '61d',
+      '61e',
+      '61f',
+      '62a',
+      '62c',
+      '602',
+      '603',
+      '605',
+      '606',
+      '608',
+      '612',
+      '613',
+      '614',
+      '615',
+      '616',
+      '618',
+      '619',
+      '620',
+      '621',
+      '623',
+      '624',
+      '625',
+      '627',
+      '629',
+      '633',
+      '635',
+      '637',
+      '63a',
+      '63b',
+      '63c',
+      '63d',
+      '63e',
+      '63f',
+      '64a',
+      '64b',
+      '64f',
+      '681',
+      '68a',
+      '68b',
+      '68c',
+      '344',
+      '345',
+      '346',
+      '347',
+      '348',
+      '349',
+      '351',
+      '352',
+      '353',
+      '414',
+      '415',
+      '416',
+      '466',
+      '467',
+      '468',
+      '469',
+      '470',
+      '471',
+      '472',
+      '473',
+      '483',
+      '484',
+      '485',
+      '486',
+      '487',
+      '490',
+      '491',
+      '493',
+      '498',
+      '6b4',
     ];
-    let emojis = []
-    let emojiCharArr = emojiChar.split("-");
+    let emojis = [];
+    let emojiCharArr = emojiChar.split('-');
     for (let i in emojiKey) {
       let em = {
         char: emojiCharArr[i],
-        emoji: "0x1f" + emojiKey[i],
+        emoji: '0x1f' + emojiKey[i],
       };
       emojis.push(em);
     }
-    this.emojis = emojis
+    this.emojis = emojis;
   }
   handleScrollStart() {
-    console.log('scroll start');
+    // console.log('scroll start');
   }
-
   handleScroll(ev: CustomEvent<ScrollDetail>) {
-    console.log('scroll', ev.detail);
-    let srcollop = ev.detail.startY;
-    console.log(srcollop);
+    // console.log('scroll', ev.detail);
+    let srcollop = ev.detail.scrollTop;
+    // console.log(srcollop);
+    this.currentScroll = srcollop;
   }
 
-  handleScrollEnd() {
-    console.log('scroll end');
+  async handleScrollEnd() {
+    // console.log('scroll end');
+    console.log(this.currentScroll);
+    if (this.currentScroll === 0){
+      const loading = await this.loadingCtrl.create({
+        message: '消息加载中',
+        duration: 1500,
+      });
+      loading.present();
+    }
   }
   //调起表情
   changeShowEmoji() {
@@ -193,11 +219,45 @@ export class ChatComponent implements OnInit {
   }
   //添加表情
   emojiChoose(value: any) {
-    this.msg = this.msg + value.char;
+    console.log(value);
+    this.text = this.text + value;
   }
   //删除表情
   delEmoji() {
-    this.msg = this.msg.substring(0, this.msg.length - 2);
+    this.text = this.text.substring(0, this.text.length - 2);
+  }
+  //发送文字
+  comfirmText(e?: any) {
+    if (e && e.keyCode != 13) {
+      return;
+    }
+    if (this.text == '' && this.text.trim() == '') {
+      this.presentToast('聊天内容不能为空');
+      return;
+    }
+    this.send({
+      msg_type: 'text',
+      content: this.text,
+    });
+    this.text = ''
+  }
+  async send(param: { msg_type: string; content: string }) {
+    let that = this;
+    // 2.开始发送消息
+    // let isLogin = JIMServ.checkLogin();
+    this.list.data.push({
+      is_self: true,
+      avatar:
+        'https://file-cloud.fmode.cn/Qje9D4bqol/20241109/2t1lp0032258601.png',
+      msg_type: param.msg_type,
+      content: param.content,
+      create_time: new Date(),
+      istoday: true,
+      timeStamp: new Date(),
+    })
+  }
+  dismiss(evt: any) {
+    this.isOpen = false;
   }
   predivimg<T>(value: string) {
     this.showPreView = true;
@@ -206,4 +266,12 @@ export class ChatComponent implements OnInit {
   onBack() {
     history.back();
   }
+  async presentToast(title: string, time?: number, color?: string) {
+    const toast = await this.toastController.create({
+      message: title,
+      duration: time || 1500,
+      color: color || 'danger',
+    });
+    toast.present();
+  }
 }

+ 6 - 0
projects/live-app/src/moduls/live/live.modules.routes.ts

@@ -1,11 +1,17 @@
 import { NgModule } from '@angular/core';
 import { RouterModule, Routes } from '@angular/router';
 import { ChatComponent } from './chat/chat.component';
+import { SearchComponent } from './search/search.component';
 const routes: Routes = [
   {
     path: 'chat',//聊天
     component: ChatComponent,
   },
+  {
+    path: 'search',//搜索
+    component: SearchComponent,
+  },
+  
 ]
 @NgModule({
   imports: [RouterModule.forChild(routes)],

+ 67 - 0
projects/live-app/src/moduls/live/search/search.component.html

@@ -0,0 +1,67 @@
+<nav title="搜索"></nav>
+<ion-content class="content">
+  <ion-searchbar
+    animated="true"
+    [(ngModel)]="value"
+    (keyup.enter)="toSearch()"
+    placeholder="搜索"
+    color="light"
+  ></ion-searchbar>
+  @if (roomList.length == 0) {
+  <div class="title">搜索历史</div>
+  <div class="history-data">
+    @for (item of Search; track $index) {
+    <div class="data-li" (click)="SearchHot(item)">
+      {{ item }}
+    </div>
+    }
+  </div>
+  <div class="title">热门搜索</div>
+  <div class="history-data">
+    @for (item of hots; track $index) {
+    <div class="data-item" (click)="SearchHot(item?.get('title'))">
+      {{ $index + 1 }}
+      <div class="date-li-name">.{{ item?.get("title") }}</div>
+    </div>
+    }
+  </div>
+  }@else {
+  <div class="room-list">
+    @for (item of roomList; track $index) {
+    <div
+      class="list-row"
+      [style.background-image]="'url(' + item?.get('cover') + ')'"
+    >
+      <div class="title-tag">在线聊天</div>
+      <div class="live-tag">
+        <!-- <span></span>  -->
+        <img src="/img/live.gif" alt="" />
+        直播中
+      </div>
+      <div class="room-footer">
+        <div class="user">
+          {{
+            item?.get("user")?.get("nickname") ||
+              item?.get("user")?.get("mobile")
+          }}
+        </div>
+        <div class="desc">{{ item?.get("title") }}</div>
+        <div class="city-block">
+          <div class="row-li">
+            <ion-icon name="location-outline"></ion-icon>
+            江西
+          </div>
+          <div class="row-li" style="margin-left: 4px">
+            <img
+              src="https://file-cloud.fmode.cn/Qje9D4bqol/20241109/pctmvt110807052.png"
+              alt=""
+            />
+            22
+          </div>
+        </div>
+      </div>
+    </div>
+    }
+  </div>
+  }
+</ion-content>

+ 140 - 0
projects/live-app/src/moduls/live/search/search.component.scss

@@ -0,0 +1,140 @@
+.content{
+  // --background: #171b24;
+  .title{
+    width: 100vw;
+    padding: 0 3.2vw;
+    font-size: 4.2667vw;
+    font-family: Source Han Sans CN;
+    font-weight: 500;
+    // color: #FFFFFF;
+    margin: 2.6667vw auto;
+  }
+  .history-data{
+    display: flex;
+    flex-wrap: wrap;
+    margin: 2.6667vw auto;
+    padding:0 3.2vw;
+    .data-li{
+      padding:1.0667vw 0 ;
+      min-width: 10.6667vw;
+      // background: #626262;
+      // color: #FFFFFF;
+      margin: 0 2.6667vw 2.6667vw 0;
+      border-radius: 5.3333vw;
+      font-size: 4.2667vw;
+      color: violet;
+    }
+    .data-item{
+      color: #f7931e;
+      margin: 0 5.3333vw 2.6667vw 0;
+      display: flex;
+      align-items: center;
+      font-size: 4.2667vw;
+      // .date-li-name{
+      //   color: #FFFFFF;
+      // }
+    }
+  }
+  .room-list {
+    display: grid;
+    grid-template-columns: repeat(2, 180px);
+    // grid-column-gap: 10px;
+    grid-row-gap: 10px;
+    padding: 10px;
+    justify-content: space-between;
+    font-size: 14px;
+    .list-row {
+      // width: 180px;
+      height: 250px;
+      background-size: 100% 100%;
+      position: relative;
+      color: white;
+      border-radius: 10px;
+      .title-tag {
+        background: linear-gradient(to bottom right, #9367fe, #d55bd9);
+        position: absolute;
+        top: 0;
+        left: 0;
+        border-radius: 10px 0;
+        padding: 4px 8px;
+      }
+      .live-tag {
+        position: absolute;
+        top: 4px;
+        right: 10px;
+        border-radius: 20px;
+        padding: 4px 10px;
+        font-size: 10px;
+        background: #1414147a;
+        display: flex;
+        align-items: center;
+        justify-content: space-evenly;
+        span {
+          height: 4px;
+          width: 4px;
+          border-radius: 50%;
+          background-color: #83f1dd;
+          margin-right: 4px;
+        }
+        img {
+          width: 12px;
+          height: 14px;
+        }
+      }
+      .room-footer {
+        position: absolute;
+        bottom: 0;
+        width: calc(100%);
+        padding: 4px 10px 10px;
+        max-height: 100px;
+        background: linear-gradient(to bottom, #ffffff00, #434343);
+        border-radius: 0 0 10px 10px;
+        .user {
+          font-size: 16px;
+        }
+        .desc {
+          margin: 4px 0;
+        }
+        .city-block {
+          display: flex;
+          background: linear-gradient(to right, #ff92e3f0, #ff6a93);
+          display: inline-flex;
+          padding: 2px 6px;
+          border-radius: 20px;
+          align-items: center;
+          .row-li {
+            display: flex;
+            align-content: center;
+            img {
+              width: 12px;
+              height: 12px;
+              margin-right: 2px;
+            }
+          }
+        }
+      }
+    }
+  }
+}
+.toolbar{
+  --background: #171b24;
+  --opacity: 1;
+  height: 16vw;
+  display: flex;
+  align-items: center;
+  .text{
+    font-size: 4.2667vw;
+    font-family: Source Han Sans CN;
+    font-weight: 500;
+    // color: #FFFFFF;
+    width: 10.6667vw;
+  }
+}
+.search{
+  --background: #353c4d;
+  padding: 0;
+  --cancel-button-color: #cccccc;
+  --color: #cccccc;
+  width: 74.6667vw;
+  height: 9.0667vw;
+}

+ 28 - 0
projects/live-app/src/moduls/live/search/search.component.spec.ts

@@ -0,0 +1,28 @@
+/* tslint:disable:no-unused-variable */
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+import { DebugElement } from '@angular/core';
+
+import { SearchComponent } from './search.component';
+
+describe('SearchComponent', () => {
+  let component: SearchComponent;
+  let fixture: ComponentFixture<SearchComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ SearchComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(SearchComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 109 - 0
projects/live-app/src/moduls/live/search/search.component.ts

@@ -0,0 +1,109 @@
+import { DatePipe } from '@angular/common';
+import { Component, OnInit } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+import { Router } from '@angular/router';
+import {
+  IonicModule,
+  LoadingController,
+  ToastController,
+} from '@ionic/angular';
+import * as Parse from 'parse';
+import { NavComponent } from '../../../app/components/nav/nav.component';
+
+@Component({
+  selector: 'app-search',
+  templateUrl: './search.component.html',
+  styleUrls: ['./search.component.scss'],
+  standalone: true,
+  imports: [IonicModule, FormsModule, DatePipe,NavComponent],
+  providers: [DatePipe],
+})
+export class SearchComponent implements OnInit {
+  roomList:any = []
+  company:string = Parse.User.current()?.get('company')
+  value:String|undefined
+  Search:any = []
+  hots:Array<Parse.Object> = []
+
+  constructor(
+    private router: Router,
+    public toastController: ToastController,
+  ) { }
+
+  async presentToast(message:string) {
+    const toast = await this.toastController.create({
+      message: message,
+      duration: 2000
+    });
+    toast.present();
+  }
+
+  ngOnInit() {
+    this.getLocalStorage()
+    this.getRoom()
+  }
+
+  // 热门搜索
+  async getRoom() {
+    let query = new Parse.Query("Room")
+    query.equalTo('company',this.company)
+    query.limit(5)
+    // query.descending("score")
+    let res = await query.find()
+    this.hots = res
+    // console.log(res);
+    // if (res && res.length > 0) {
+    //   res.forEach(item => {
+    //     games.push(item.get('title'))
+    //   })
+    //   this.hots = games
+    // }
+  }
+
+  getLocalStorage(){
+    let storage = localStorage.getItem("Search");
+    this.Search = storage && JSON.parse(storage)
+    console.log(this.Search);
+  }
+
+  SearchHot(value: String){
+    this.value = value
+    this.toSearch()
+  }
+  //搜索
+  toSearch(){
+    this.roomList = []
+    if(!this.value || this.value?.trim() === ''){
+      this.presentToast('请输入搜索内容')
+      return
+    }
+    this.getSearch()
+    let storage = localStorage.getItem("Search");
+    if(!storage){
+      let searchs = [
+        this.value,
+      ]
+      localStorage.setItem("Search",JSON.stringify(searchs));
+      return
+    }
+    console.log(storage);
+    let list = JSON.parse(storage)
+    list.splice(0,0,this.value)
+    let arr:any = new Set(list)
+    list = Array.from(arr)
+    if(list.length > 10){
+      list.splice(-1,1)
+    }
+    localStorage.setItem("Search",JSON.stringify(list));
+    this.Search = list
+  }
+  async getSearch(){
+    let query = new Parse.Query("Room")
+    query.equalTo('company',this.company)
+    query.equalTo('title',this.value)
+    query.notEqualTo('isDeleted',true)
+    let r = await query.find()
+    this.roomList = r
+    if(this.roomList.length == 0)this.presentToast('暂无搜索结果')
+  }
+}

+ 1 - 1
projects/live-app/src/moduls/tabs/home/home.component.html

@@ -29,7 +29,7 @@
       </ion-segment>
       <div class="more">
         <img src="/img/more.png" alt="" />
-        <img src="/img/search.png" alt="" />
+        <img src="/img/search.png" alt="" (click)="search()" />
       </div>
     </div>
   </div>

+ 3 - 0
projects/live-app/src/moduls/tabs/home/home.component.ts

@@ -73,4 +73,7 @@ export class HomeComponent implements OnInit {
   toSearchb() {
     this.router.navigate(['metapunk/searchbar']);
   }
+  search(){
+    this.router.navigate(['live/search']);
+  }
 }

+ 1 - 1
projects/live-app/src/moduls/tabs/my/my.component.html

@@ -37,7 +37,7 @@
             </div>
             <div class="id">ID:{{ user?.id }}</div>
           </div>
-          <div class="btn">个人主页</div>
+          <div class="btn" (click)="toUrl('user/profile')">个人主页</div>
         </div>
         <div class="user-footer">
           <div class="row">1.2W 粉丝</div>

+ 82 - 0
projects/live-app/src/moduls/user/profile/profile.component.html

@@ -0,0 +1,82 @@
+<nav title="主页信息"></nav>
+<ion-content [fullscreen]="true" class="content">
+  <div class="bg">
+    <img [src]="profile?.get('cover')" alt="" />
+    <div class="mask"></div>
+  </div>
+  <div class="header">
+    <div class="user-dateil">
+      <div class="pendant">
+        <div class="top">
+          <img
+            class="avatar"
+            [src]="profile?.get('user')?.get('avatar')"
+            alt=""
+          />
+          <div class="top-right-block">
+            <div class="top-left-title">{{ profile?.get("name") }}</div>
+            <div class="sex">
+              <ion-icon name="male-outline"></ion-icon>
+            </div>
+            <!-- }@else if (user?.get('sex') == '女') {
+              <div class="sex girl">
+                <ion-icon name="male-female-outline"></ion-icon>
+              </div>
+              } -->
+            <div class="age">
+              <img
+                src="https://file-cloud.fmode.cn/Qje9D4bqol/20241109/pctmvt110807052.png"
+                alt=""
+              />
+              23
+            </div>
+          </div>
+        </div>
+        <div class="user-status">
+          <span class="id">爱聊ID:1234456</span>
+          <span class="tag">·勿扰</span>
+        </div>
+      </div>
+      <div class="user-right">
+        <ion-icon name="heart-circle-sharp"></ion-icon>
+      </div>
+    </div>
+    <div class="user-fans">
+      <span>关注:99</span>
+      <span>粉丝:99</span>
+      <span>送出:99</span>
+    </div>
+    <div class="bar"></div>
+  </div>
+  <div class="user-data">
+    <div class="title-h2">资料</div>
+    <div class="user-data">
+      <div class="title-text">个人资料</div>
+      <div class="tags">
+        <span>生日:未知</span>
+        <span>星座:未知</span>
+        <span>城市:未知</span>
+      </div>
+      <div class="motto">忽悠古人心上过,回首山河已是秋。</div>
+    </div>
+    <div class="user-data">
+      <div class="title-text">个人相册</div>
+      <div class="album">
+        @for (item of profile?.get('album'); track $index) {
+        <img [src]="item" alt="" />
+        }
+      </div>
+    </div>
+    <div class="user-data">
+      <div class="title-text">礼物墙</div>
+    </div>
+  </div>
+</ion-content>
+<ion-footer class="footer">
+  <ion-toolbar class="footer-tool">
+    <div class="btns">
+      <div class="round">私信</div>
+      <div class="round">送礼</div>
+    </div>
+  </ion-toolbar>
+</ion-footer>

+ 134 - 0
projects/live-app/src/moduls/user/profile/profile.component.scss

@@ -0,0 +1,134 @@
+.content {
+  --padding-bottom: 100px;
+  --background: #ffffff;
+  .bg {
+    height: 160px;
+    width: 100%;
+    position: relative;
+    img {
+      width: 100%;
+      height: 100%;
+      object-fit: cover;
+    }
+    .mask {
+      position: absolute;
+      top: 0;
+      left: 0;
+      width: 100%;
+      height: 100%;
+      background: linear-gradient(to bottom, rgba(255, 255, 255, 0), #43434399);
+    }
+  }
+  .header {
+    width: 100%;
+    height: 100px;
+    padding: 6px 10px;
+    // background: white;
+    // border-radius: 0 0 6px 6px;
+    .user-dateil {
+      width: 100%;
+      display: flex;
+      justify-content: space-between;
+      .pendant {
+        .top {
+          display: flex;
+          align-items: self-end;
+          .avatar {
+            width: 60px;
+            height: 60px;
+            margin-top: -38px;
+            z-index: 1;
+          }
+          .top-right-block {
+            display: flex;
+            align-items: end;
+            .top-left-title{
+              font-size: 20px;
+              font-weight: 500;
+            }
+            .sex {
+              border-radius: 50%;
+              width: 20px;
+              height: 20px;
+              display: flex;
+              align-items: center;
+              justify-content: center;
+              box-shadow: rgba(0, 0, 0, 0.15) 0px 15px 25px,
+                rgba(0, 0, 0, 0.05) 0px 5px 10px;
+              background: linear-gradient(to right, #156bfd, #91baff);
+              margin: 0 6px;
+            }
+            .girl {
+              background: linear-gradient(to right, #fe454e, #f5a7ab);
+            }
+            .age {
+              background: linear-gradient(to right, #156bfd, #d3e4ff);
+              display: flex;
+              align-items: center;
+              height: 20px;
+              padding: 0 8px;
+              border-radius: 20px;
+              margin: 0 2px;
+              img {
+                width: 14px;
+                height: 14px;
+                margin-right: 4px;
+              }
+            }
+          }
+        }
+        .user-status {
+          margin: 10px 0;
+          display: flex;
+          align-items: center;
+          font-size: 12px;
+          .id{
+            color: #1e1e1e;
+          }
+          .tag{
+            color: white;
+            background: #fe454e;
+            padding: 2px 6px;
+            border-radius: 10px;
+            margin-left: 10px;
+          }
+        }
+      }
+      .user-right {
+        flex-shrink: 0;
+        ion-icon{
+          font-size: 40px;
+          color: #fe454e;
+        }
+      }
+    }
+    .user-fans{
+      font-size: 14px;
+      span{
+        margin-right: 10px;
+      }
+    }
+    .bar{
+      margin-top: 10px;
+      border-bottom: 1px solid #dbdbdb;
+      width: 100%;
+    }
+  }
+  .user-data{
+    width: 100%;
+    padding: 6px 10px;
+  }
+}
+.footer{
+  .btns{
+    display: flex;
+    justify-content: space-around;
+    .round{
+      background: #156bfd;
+      padding: 8px 40px;
+      border-radius: 20px;
+      color: white;
+      font-size: 14px;
+    }
+  }
+}

+ 28 - 0
projects/live-app/src/moduls/user/profile/profile.component.spec.ts

@@ -0,0 +1,28 @@
+/* tslint:disable:no-unused-variable */
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+import { DebugElement } from '@angular/core';
+
+import { ProfileComponent } from './profile.component';
+
+describe('ProfileComponent', () => {
+  let component: ProfileComponent;
+  let fixture: ComponentFixture<ProfileComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ ProfileComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(ProfileComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 42 - 0
projects/live-app/src/moduls/user/profile/profile.component.ts

@@ -0,0 +1,42 @@
+import { Component, OnInit } from '@angular/core';
+import { DatePipe } from '@angular/common';
+import { NavComponent } from '../../../app/components/nav/nav.component';
+import { Router } from '@angular/router';
+import {
+  IonicModule,
+  ToastController,
+} from '@ionic/angular';
+import * as Parse from 'parse';
+
+@Component({
+  selector: 'app-profile',
+  templateUrl: './profile.component.html',
+  styleUrls: ['./profile.component.scss'],
+  standalone: true,
+  imports: [IonicModule, DatePipe,NavComponent],
+  providers: [DatePipe],
+})
+export class ProfileComponent implements OnInit {
+  profile: Parse.Object | any = {
+    get: (e: string) => {
+      let jsonb:any = {
+        'cover': `https://file-cloud.fmode.cn/Qje9D4bqol/20241119/sd1upp041122290.jpg`,
+        'user':Parse.User.current(),
+        'name':'甜心宝贝',
+        '': '',
+      };
+      return jsonb[e];
+    },
+    set: () => {},
+    save: () => {},
+    destroy: () => {}, // 修复:添加方法体
+  };
+  constructor(
+    private router: Router,
+    public toastController: ToastController,
+  ) { }
+
+  ngOnInit() {
+  }
+
+}

+ 3 - 3
projects/live-app/src/moduls/user/user.modules.routes.ts

@@ -3,11 +3,11 @@ import { RouterModule, Routes } from '@angular/router';
 import { AlbumComponent } from './album/album.component';
 import { CertificationComponent } from './certification/certification.component';
 import { FeedbackComponent } from './feedback/feedback.component';
+import { ProfileComponent } from './profile/profile.component';
 const routes: Routes = [
   {
-    path: '',
-    redirectTo:'idcard',
-    pathMatch: "full",
+    path: 'profile',//实名
+    component: ProfileComponent,
   },
   {
     path: 'idcard',//实名