flowaaa 5 months ago
parent
commit
056c37171b
25 changed files with 327 additions and 26 deletions
  1. 47 0
      app-angular/package-lock.json
  2. 1 0
      app-angular/package.json
  3. 0 3
      app-angular/src/app/app.module.ts
  4. 3 1
      app-angular/src/app/tab1/tab1.page.html
  5. 4 0
      app-angular/src/app/tab1/tab1.page.scss
  6. 8 1
      app-angular/src/app/tab1/tab1.page.ts
  7. 1 1
      app-angular/src/app/tabs/tabs-routing.module.ts
  8. 7 7
      app-angular/src/app/tabs/tabs.page.html
  9. 1 1
      app-angular/src/global.scss
  10. 17 0
      app-angular/src/modules/contact/contact-detail/contact-detail-routing.module.ts
  11. 20 0
      app-angular/src/modules/contact/contact-detail/contact-detail.module.ts
  12. 13 0
      app-angular/src/modules/contact/contact-detail/contact-detail.page.html
  13. 0 0
      app-angular/src/modules/contact/contact-detail/contact-detail.page.scss
  14. 17 0
      app-angular/src/modules/contact/contact-detail/contact-detail.page.spec.ts
  15. 15 0
      app-angular/src/modules/contact/contact-detail/contact-detail.page.ts
  16. 17 0
      app-angular/src/modules/contact/contact-list/contact-list-routing.module.ts
  17. 20 0
      app-angular/src/modules/contact/contact-list/contact-list.module.ts
  18. 34 0
      app-angular/src/modules/contact/contact-list/contact-list.page.html
  19. 0 0
      app-angular/src/modules/contact/contact-list/contact-list.page.scss
  20. 17 0
      app-angular/src/modules/contact/contact-list/contact-list.page.spec.ts
  21. 42 0
      app-angular/src/modules/contact/contact-list/contact-list.page.ts
  22. 12 0
      app-angular/src/modules/contact/contact-routing.module.ts
  23. 14 0
      app-angular/src/modules/contact/contact.module.ts
  24. 8 6
      app-angular/src/modules/user/login/login.page.ts
  25. 9 6
      app-angular/src/modules/user/mine/mine.page.ts

+ 47 - 0
app-angular/package-lock.json

@@ -25,6 +25,7 @@
         "@types/parse": "^3.0.9",
         "ionicons": "^7.0.0",
         "parse": "^5.1.0",
+        "pinyin": "^4.0.0-alpha.0",
         "rxjs": "~7.8.0",
         "tslib": "^2.3.0",
         "zone.js": "~0.14.2"
@@ -11544,6 +11545,11 @@
         "node": ">=10"
       }
     },
+    "node_modules/keypress": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmmirror.com/keypress/-/keypress-0.1.0.tgz",
+      "integrity": "sha512-x0yf9PL/nx9Nw9oLL8ZVErFAk85/lslwEP7Vz7s5SI1ODXZIgit3C5qyWjw4DxOuO/3Hb4866SQh28a1V1d+WA=="
+    },
     "node_modules/keyv": {
       "version": "4.5.4",
       "resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz",
@@ -13646,6 +13652,47 @@
         "node": ">=6"
       }
     },
+    "node_modules/pinyin": {
+      "version": "4.0.0-alpha.0",
+      "resolved": "https://registry.npmmirror.com/pinyin/-/pinyin-4.0.0-alpha.0.tgz",
+      "integrity": "sha512-hdxO/2RuLWarhLaIcGKdXjkFZ0hFr3W/Yrvrd0YPxuIafixMZSAa4jvxskYLgYHE8OkOXkGsxMsEScwGzqKe3g==",
+      "dependencies": {
+        "commander": "~1.1.1"
+      },
+      "bin": {
+        "pinyin": "bin/pinyin"
+      },
+      "engines": {
+        "install-node": "^18.0.0"
+      },
+      "peerDependencies": {
+        "@node-rs/jieba": "^1.6.0",
+        "nodejieba": "2.5.2",
+        "segmentit": "^2.0.3"
+      },
+      "peerDependenciesMeta": {
+        "@node-rs/jieba": {
+          "optional": true
+        },
+        "nodejieba": {
+          "optional": true
+        },
+        "segmentit": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/pinyin/node_modules/commander": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmmirror.com/commander/-/commander-1.1.1.tgz",
+      "integrity": "sha512-71Rod2AhcH3JhkBikVpNd0pA+fWsmAaVoti6OR38T76chA7vE3pSerS0Jor4wDw+tOueD2zLVvFOw5H0Rcj7rA==",
+      "dependencies": {
+        "keypress": "0.1.x"
+      },
+      "engines": {
+        "node": ">= 0.6.x"
+      }
+    },
     "node_modules/piscina": {
       "version": "4.5.0",
       "resolved": "https://registry.npmmirror.com/piscina/-/piscina-4.5.0.tgz",

+ 1 - 0
app-angular/package.json

@@ -30,6 +30,7 @@
     "@types/parse": "^3.0.9",
     "ionicons": "^7.0.0",
     "parse": "^5.1.0",
+    "pinyin": "^4.0.0-alpha.0",
     "rxjs": "~7.8.0",
     "tslib": "^2.3.0",
     "zone.js": "~0.14.2"

+ 0 - 3
app-angular/src/app/app.module.ts

@@ -6,9 +6,6 @@ import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
 
 import { AppRoutingModule } from './app-routing.module';
 import { AppComponent } from './app.component';
-import * as Parse from "parse"
-(Parse as any).serverURL = "http://web2023.fmode.cn:9999/parse"
-Parse.initialize("dev")
 
 @NgModule({
   declarations: [AppComponent],

+ 3 - 1
app-angular/src/app/tab1/tab1.page.html

@@ -13,5 +13,7 @@
     </ion-toolbar>
   </ion-header>
 
-  
+  <div *ngIf="safeHTML" [innerHTML]="safeHTML"></div>
+  <!-- <ion-button expand="block" routerLink="/tabs/tab2">示例:通讯录列表</ion-button>
+  <ion-button expand="block" (click)="openGit()">代码:study-ng-contact</ion-button> -->
 </ion-content>

+ 4 - 0
app-angular/src/app/tab1/tab1.page.scss

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

+ 8 - 1
app-angular/src/app/tab1/tab1.page.ts

@@ -1,4 +1,5 @@
 import { Component } from '@angular/core';
+import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
 
 @Component({
   selector: 'app-tab1',
@@ -7,6 +8,12 @@ import { Component } from '@angular/core';
 })
 export class Tab1Page {
 
-  constructor() {}
+  safeHTML: SafeResourceUrl|undefined
+  constructor(private domSan:DomSanitizer) {
+    this.safeHTML = domSan.bypassSecurityTrustHtml(``)
+  }
+  openGit(){
+    window.open(`http://git.fmode.cn:3000/nkkj/study-ng-contact`,"_blank")
+  }
 
 }

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

@@ -13,7 +13,7 @@ const routes: Routes = [
       },
       {
         path: 'tab2',
-        loadChildren: () => import('../tab2/tab2.module').then(m => m.Tab2PageModule)
+        loadChildren: () => import('../../modules/contact/contact-list/contact-list.module').then(mod => mod.ContactListPageModule)
       },
       {
         path: 'tab3',

+ 7 - 7
app-angular/src/app/tabs/tabs.page.html

@@ -1,20 +1,20 @@
 <ion-tabs>
 
-  <ion-tab-bar slot="bottom">
-    <ion-tab-button tab="tab1" href="/tabs/tab1">
-      <ion-icon aria-hidden="true" name="triangle"></ion-icon>
-      <ion-label>说明</ion-label>
-    </ion-tab-button>
 
+  <ion-tab-bar slot="bottom">
     <ion-tab-button tab="tab2" href="/tabs/tab2">
       <ion-icon aria-hidden="true" name="ellipse"></ion-icon>
-      <ion-label>示例</ion-label>
+      <ion-label>人情圈</ion-label>
     </ion-tab-button>
 
     <ion-tab-button tab="tab3" href="/tabs/tab3">
-      <ion-icon aria-hidden="true" name="square"></ion-icon>
+      <ion-icon aria-hidden="true" name="person"></ion-icon>
       <ion-label>我的</ion-label>
     </ion-tab-button>
+    <!-- <ion-tab-button tab="tab1" href="/tabs/tab1">
+      <ion-icon aria-hidden="true" name="document"></ion-icon>
+      <ion-label>礼物</ion-label>
+    </ion-tab-button> -->
   </ion-tab-bar>
 
 </ion-tabs>

+ 1 - 1
app-angular/src/global.scss

@@ -34,4 +34,4 @@
 
 /* @import "@ionic/angular/css/palettes/dark.always.css"; */
 /* @import "@ionic/angular/css/palettes/dark.class.css"; */
-@import "@ionic/angular/css/palettes/dark.system.css";
+// @import "@ionic/angular/css/palettes/dark.system.css";

+ 17 - 0
app-angular/src/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
app-angular/src/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
app-angular/src/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
app-angular/src/modules/contact/contact-detail/contact-detail.page.scss


+ 17 - 0
app-angular/src/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
app-angular/src/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
app-angular/src/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
app-angular/src/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
app-angular/src/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
app-angular/src/modules/contact/contact-list/contact-list.page.scss


+ 17 - 0
app-angular/src/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
app-angular/src/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
app-angular/src/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
app-angular/src/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 { }

+ 8 - 6
app-angular/src/modules/user/login/login.page.ts

@@ -52,9 +52,9 @@ export class LoginPage implements OnInit {
       buttons: [{
         text: '好的',
         handler: () => {
-          // if (options.callback) {
-          //   options.callback();
-          // }
+          if (options.callback) {
+            options.callback();
+          }
         }
       }],
     });
@@ -73,9 +73,9 @@ async register(){
             header:"注册成功",
             subHeader:"恭喜您注册成功!",
             message:"您可以使用新账号登录了!",
-            callback: () => {
-              this.navCtrl.back();  
-            }
+            // callback: () => {
+            //   this.navCtrl.back();  
+            // }
           });
         }
         // Hooray! Let them use the app now.
@@ -95,6 +95,8 @@ async register(){
         })
     }
 }
+
+
   /**
    * 返回上级页面函数
    * @desc

+ 9 - 6
app-angular/src/modules/user/mine/mine.page.ts

@@ -8,15 +8,18 @@ import * as Parse from "parse"
 })
 export class MinePage implements OnInit {
 
-  // 由于Parse.User.current()是随着localStorage变化的属性
-  // 为了避免首次复制后用户状态变化,页面不同步,通过get方法实现实时获取
-  get user():Parse.User|undefined{
-    return Parse.User.current()
-  }
   constructor() {
+   
   }
 
-  ngOnInit() {
+  // 由于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();