0210185 4 달 전
부모
커밋
4a69ceab9e

+ 4 - 0
app/app-routing.module.ts

@@ -9,6 +9,10 @@ const routes: Routes = [
   {
     path: 'user',
     loadChildren: () => import('../modules/user/user.module').then(m => m.UserModule)
+  },
+  {
+    path: 'contact',
+    loadChildren: () => import('../modules/contact/contact.module').then(m => m.ContactModule)
   }
 ];
 @NgModule({

+ 0 - 19
app/tab4/tab1.page.html

@@ -1,19 +0,0 @@
-<ion-header [translucent]="true">
-  <ion-toolbar>
-    <ion-title>
-      使用说明
-    </ion-title>
-  </ion-toolbar>
-</ion-header>
-
-<ion-content [fullscreen]="true">
-  <ion-header collapse="condense">
-    <ion-toolbar>
-      <ion-title size="large">使用说明</ion-title>
-    </ion-toolbar>
-  </ion-header>
-
-  <div *ngIf="safeHTML" [innerHTML]="safeHTML"></div>
-  <ion-button expand="block" routerLink="/tabs/tab3">示例:我的页面</ion-button>
-  <ion-button expand="block" (click)="openGit()">代码:study-ng-user</ion-button>
-</ion-content>

+ 0 - 4
app/tab4/tab1.page.scss

@@ -1,4 +0,0 @@
-iframe{
-    width:100%;
-    height:100%;
-}

+ 0 - 19
app/tab4/tab1.page.ts

@@ -1,19 +0,0 @@
-import { Component } from '@angular/core';
-import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
-
-@Component({
-  selector: 'app-tab1',
-  templateUrl: 'tab1.page.html',
-  styleUrls: ['tab1.page.scss']
-})
-export class Tab1Page {
-
-  safeHTML: SafeResourceUrl|undefined
-  constructor(private domSan:DomSanitizer) {
-    this.safeHTML = domSan.bypassSecurityTrustHtml(``)
-  }
-  openGit(){
-    window.open(`http://git.fmode.cn:3000/nkkj/study-ng-user`,"_blank")
-  }
-
-}

+ 3 - 3
app/tab4/tab1-routing.module.ts → app/tab4/tab4-routing.module.ts

@@ -1,11 +1,11 @@
 import { NgModule } from '@angular/core';
 import { RouterModule, Routes } from '@angular/router';
-import { Tab1Page } from './tab1.page';
+import { Tab4Page } from './tab4.page';
 
 const routes: Routes = [
   {
     path: '',
-    component: Tab1Page,
+    component: Tab4Page,
   }
 ];
 
@@ -13,4 +13,4 @@ const routes: Routes = [
   imports: [RouterModule.forChild(routes)],
   exports: [RouterModule]
 })
-export class Tab1PageRoutingModule {}
+export class Tab4PageRoutingModule {}

+ 5 - 5
app/tab4/tab1.module.ts → app/tab4/tab4.module.ts

@@ -2,10 +2,10 @@ import { IonicModule } from '@ionic/angular';
 import { NgModule } from '@angular/core';
 import { CommonModule } from '@angular/common';
 import { FormsModule } from '@angular/forms';
-import { Tab1Page } from './tab1.page';
+import { Tab4Page } from './tab4.page';
 import { ExploreContainerComponentModule } from '../explore-container/explore-container.module';
 
-import { Tab1PageRoutingModule } from './tab1-routing.module';
+import { Tab4PageRoutingModule } from './tab4-routing.module';
 
 @NgModule({
   imports: [
@@ -13,8 +13,8 @@ import { Tab1PageRoutingModule } from './tab1-routing.module';
     CommonModule,
     FormsModule,
     ExploreContainerComponentModule,
-    Tab1PageRoutingModule
+    Tab4PageRoutingModule
   ],
-  declarations: [Tab1Page]
+  declarations: [Tab4Page]
 })
-export class Tab1PageModule {}
+export class Tab4PageModule {}

+ 17 - 0
app/tab4/tab4.page.html

@@ -0,0 +1,17 @@
+<ion-header [translucent]="true">
+  <ion-toolbar>
+    <ion-title>
+      Tab 4
+    </ion-title>
+  </ion-toolbar>
+</ion-header>
+
+<ion-content [fullscreen]="true">
+  <ion-header collapse="condense">
+    <ion-toolbar>
+      <ion-title size="large">Tab 4</ion-title>
+    </ion-toolbar>
+  </ion-header>
+
+  <app-explore-container name="Tab 4 page"></app-explore-container>
+</ion-content>

+ 0 - 0
app/tab4/tab4.page.scss


+ 6 - 6
app/tab4/tab1.page.spec.ts → app/tab4/tab4.page.spec.ts

@@ -3,19 +3,19 @@ import { IonicModule } from '@ionic/angular';
 
 import { ExploreContainerComponentModule } from '../explore-container/explore-container.module';
 
-import { Tab1Page } from './tab1.page';
+import { Tab4Page } from './tab4.page';
 
-describe('Tab1Page', () => {
-  let component: Tab1Page;
-  let fixture: ComponentFixture<Tab1Page>;
+describe('Tab4Page', () => {
+  let component: Tab4Page;
+  let fixture: ComponentFixture<Tab4Page>;
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [Tab1Page],
+      declarations: [Tab4Page],
       imports: [IonicModule.forRoot(), ExploreContainerComponentModule]
     }).compileComponents();
 
-    fixture = TestBed.createComponent(Tab1Page);
+    fixture = TestBed.createComponent(Tab4Page);
     component = fixture.componentInstance;
     fixture.detectChanges();
   });

+ 12 - 0
app/tab4/tab4.page.ts

@@ -0,0 +1,12 @@
+import { Component } from '@angular/core';
+
+@Component({
+  selector: 'app-tab4',
+  templateUrl: 'tab4.page.html',
+  styleUrls: ['tab4.page.scss']
+})
+export class Tab4Page {
+
+  constructor() {}
+
+}

+ 4 - 0
app/tabs/tabs-routing.module.ts

@@ -19,6 +19,10 @@ const routes: Routes = [
         path: 'tab3',
         loadChildren: () => import('../../modules/user/mine/mine.module').then(mod => mod.MinePageModule)
       },
+      {
+        path: 'tab4',
+        loadChildren: () => import('../../modules/contact/contact-list/contact-list.module').then(mod => mod.ContactListPageModule)
+      },
       {
         path: '',
         redirectTo: '/tabs/tab1',

+ 8 - 7
app/tabs/tabs.page.html

@@ -10,10 +10,11 @@
       <ion-label>动态</ion-label>
     </ion-tab-button>
 
-    <ion-tab-button class="placeholder-tab-button"></ion-tab-button>
+    <!-- 占位符,用于保持加号按钮的位置居中 -->
+    <ion-tab-button disabled class="placeholder-tab-button"></ion-tab-button>
 
-    <ion-tab-button tab="tab4" class="custom-tab-button">
-      <ion-icon name="people"></ion-icon>
+    <ion-tab-button tab="tab4" class="custom-tab-button" href="/tabs/tab4">
+      <ion-icon aria-hidden="true" name="people"></ion-icon>
       <ion-label>联系人</ion-label>
     </ion-tab-button>
 
@@ -25,13 +26,13 @@
 
   <!-- 加号按钮,点击展开更多选项 -->
   <ion-fab vertical="bottom" horizontal="center" slot="fixed" class="custom-fab">
-    <ion-fab-button (click)="toggleOptions()">
+     <ion-fab-button (click)="toggleOptions()">
       <ion-icon name="add"></ion-icon>
     </ion-fab-button>
     <ion-fab-list side="top" *ngIf="optionsVisible">
-      <ion-fab-button (click)="selectOption('option1')">选项1</ion-fab-button>
-      <ion-fab-button (click)="selectOption('option2')">选项2</ion-fab-button>
-      <ion-fab-button (click)="selectOption('option3')">选项3</ion-fab-button>
+      <ion-fab-button (click)="selectOption('option1')">发布</ion-fab-button>
+      <ion-fab-button (click)="selectOption('option2')">上传</ion-fab-button>
+      <ion-fab-button (click)="selectOption('option3')">收藏</ion-fab-button>
     </ion-fab-list>
   </ion-fab>
 </ion-tabs>

+ 15 - 10
app/tabs/tabs.page.scss

@@ -1,6 +1,6 @@
 .custom-tab-bar {
   display: grid;
-  grid-template-columns: repeat(5, 1fr); /* 创建五个等宽的列 */
+  grid-template-columns: repeat(5, 1fr);
   position: relative;
 }
 
@@ -12,23 +12,28 @@
 }
 
 .placeholder-tab-button {
-  opacity: 0; /* 隐藏占位按钮 */
-  pointer-events: none; /* 禁止点击 */
+  opacity: 0;
+  pointer-events: none;
 }
 
 .custom-fab {
   position: absolute;
-  bottom: 20px; /* 调整底部间距,根据需求修改 */
-  left: calc(50% - 25px); /* 计算使按钮水平居中 */
-  z-index: 10; /* 确保加号按钮位于其他元素之上 */
+  bottom: 20px;
+  left: 50%;
+  transform: translateX(-180%);
+  z-index: 10;
 }
 
 ion-fab-list {
   position: absolute;
-  bottom: 60px; /* 确保拓展选项列表不会与底部标签栏重叠 */
-  z-index: 11; /* 确保拓展选项列表位于加号按钮之上 */
+  bottom: 20px;
+  z-index: 11;
 }
 
-ion-fab {
-  --ion-color-primary: #3880ff; /* 加号按钮的颜色 */
+ion-fab-button.rotate {
+  transition: transform 0.01ms ease; /* 添加过渡效果 */
+}
+
+ion-fab-button.rotate.rotate180 {
+  transform: rotate(45deg); /* 旋转180度 */
 }

+ 17 - 0
modules/contact/contact-detail/contact-detail-routing.module.ts

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

+ 20 - 0
modules/contact/contact-detail/contact-detail.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 { ContactDetailPageRoutingModule } from './contact-detail-routing.module';
+
+import { ContactDetailPage } from './contact-detail.page';
+
+@NgModule({
+  imports: [
+    CommonModule,
+    FormsModule,
+    IonicModule,
+    ContactDetailPageRoutingModule
+  ],
+  declarations: [ContactDetailPage]
+})
+export class ContactDetailPageModule {}

+ 13 - 0
modules/contact/contact-detail/contact-detail.page.html

@@ -0,0 +1,13 @@
+<ion-header [translucent]="true">
+  <ion-toolbar>
+    <ion-title>contact-detail</ion-title>
+  </ion-toolbar>
+</ion-header>
+
+<ion-content [fullscreen]="true">
+  <ion-header collapse="condense">
+    <ion-toolbar>
+      <ion-title size="large">contact-detail</ion-title>
+    </ion-toolbar>
+  </ion-header>
+</ion-content>

+ 0 - 0
modules/contact/contact-detail/contact-detail.page.scss


+ 17 - 0
modules/contact/contact-detail/contact-detail.page.spec.ts

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

+ 15 - 0
modules/contact/contact-detail/contact-detail.page.ts

@@ -0,0 +1,15 @@
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+  selector: 'app-contact-detail',
+  templateUrl: './contact-detail.page.html',
+  styleUrls: ['./contact-detail.page.scss'],
+})
+export class ContactDetailPage implements OnInit {
+
+  constructor() { }
+
+  ngOnInit() {
+  }
+
+}

+ 17 - 0
modules/contact/contact-list/contact-list-routing.module.ts

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

+ 20 - 0
modules/contact/contact-list/contact-list.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 { ContactListPageRoutingModule } from './contact-list-routing.module';
+
+import { ContactListPage } from './contact-list.page';
+
+@NgModule({
+  imports: [
+    CommonModule,
+    FormsModule,
+    IonicModule,
+    ContactListPageRoutingModule
+  ],
+  declarations: [ContactListPage]
+})
+export class ContactListPageModule {}

+ 34 - 0
modules/contact/contact-list/contact-list.page.html

@@ -0,0 +1,34 @@
+<ion-header [translucent]="true">
+  <ion-toolbar>
+    <ion-title>通讯录</ion-title>
+  </ion-toolbar>
+</ion-header>
+
+<ion-content [fullscreen]="true">
+  <ion-header collapse="condense">
+    <ion-toolbar>
+      <ion-title size="large">通讯录</ion-title>
+    </ion-toolbar>
+  </ion-header>
+  
+  <ion-searchbar [(ngModel)]="searchName" (ionInput)="search()"></ion-searchbar>
+
+  <ion-list>
+    <ng-container *ngFor="let contact of contactList;let index = index;">
+      <!-- 分组:根据下标首个出现的元素显示分组分隔符 -->
+      <ion-item-divider *ngIf="charGroupIndex[contact.get('firstChar')] == index">
+        <ion-label>{{contact.get('firstChar')}}</ion-label>
+      </ion-item-divider>
+      <ion-item lines="none">
+        <ion-avatar slot="start">
+          <img [src]="contact.get('avatarUrl') || 'https://ionicframework.com/docs/img/demos/avatar.svg'">
+        </ion-avatar>
+        <ion-label>
+          <h2>{{ contact.get('name') }}</h2>
+          <p>性别: {{ contact.get('gender') }}</p>
+          <p>手机: {{ contact.get('mobile') }}</p>
+        </ion-label>
+      </ion-item>
+    </ng-container>
+  </ion-list>
+</ion-content>

+ 0 - 0
modules/contact/contact-list/contact-list.page.scss


+ 17 - 0
modules/contact/contact-list/contact-list.page.spec.ts

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

+ 42 - 0
modules/contact/contact-list/contact-list.page.ts

@@ -0,0 +1,42 @@
+import { Component, OnInit } from '@angular/core';
+import * as Parse from "parse";
+@Component({
+  selector: 'app-contact-list',
+  templateUrl: './contact-list.page.html',
+  styleUrls: ['./contact-list.page.scss'],
+})
+export class ContactListPage implements OnInit {
+  searchName: string = '';
+  contactList: Array<Parse.Object> = [];
+
+  ngOnInit() {
+    this.loadContact();
+  }
+
+  charGroupIndex:any = {}
+  loadContact() {
+    const Contact = Parse.Object.extend('Contact');
+    const query = new Parse.Query(Contact);
+    query.ascending('firstChar');
+
+    if (this.searchName) {
+      query.contains('name', this.searchName);
+    }
+
+    query.find().then((results) => {
+      this.contactList = results;
+      this.contactList.forEach((contact,index)=>{
+        if(this.charGroupIndex[contact.get("firstChar")] == undefined){
+          this.charGroupIndex[contact.get("firstChar")] = index
+        }
+      })
+    }, (error) => {
+      console.error('Error while fetching contacts', error);
+    });
+  }
+
+  search() {
+    this.loadContact();
+  }
+
+}

+ 12 - 0
modules/contact/contact-routing.module.ts

@@ -0,0 +1,12 @@
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+
+const routes: Routes = [
+  {path: 'list', loadChildren: () => import('./contact-list/contact-list.module').then(mod => mod.ContactListPageModule)},
+  {path: 'detail/:id', loadChildren: () => import('./contact-detail/contact-detail.module').then(mod => mod.ContactDetailPageModule)},
+];
+@NgModule({
+  imports: [RouterModule.forChild(routes)],
+  exports: [RouterModule]
+})
+export class ContactRoutingModule { }

+ 14 - 0
modules/contact/contact.module.ts

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