浏览代码

feat: new routes

0235971 7 月之前
父节点
当前提交
3ea36f1915

+ 34 - 2
package-lock.json

@@ -12,6 +12,7 @@
         "@angular/compiler": "^20.0.0",
         "@angular/core": "^20.0.0",
         "@angular/forms": "^20.0.0",
+        "@angular/material": "^20.0.4",
         "@angular/platform-browser": "^20.0.0",
         "@angular/router": "^20.0.0",
         "rxjs": "~7.8.0",
@@ -208,6 +209,22 @@
         }
       }
     },
+    "node_modules/@angular/cdk": {
+      "version": "20.0.4",
+      "resolved": "https://registry.npmmirror.com/@angular/cdk/-/cdk-20.0.4.tgz",
+      "integrity": "sha512-NCUuw0qQXwawLsT14JHApNB9or3XGs7D1pWXlOIix/fKqzHVfi4un9xHmpjH2Q1uCiwonuak7fDof8B+IXhbug==",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "parse5": "^7.1.2",
+        "tslib": "^2.3.0"
+      },
+      "peerDependencies": {
+        "@angular/common": "^20.0.0 || ^21.0.0",
+        "@angular/core": "^20.0.0 || ^21.0.0",
+        "rxjs": "^6.5.3 || ^7.4.0"
+      }
+    },
     "node_modules/@angular/cli": {
       "version": "20.0.4",
       "resolved": "https://registry.npmmirror.com/@angular/cli/-/cli-20.0.4.tgz",
@@ -454,6 +471,23 @@
         "rxjs": "^6.5.3 || ^7.4.0"
       }
     },
+    "node_modules/@angular/material": {
+      "version": "20.0.4",
+      "resolved": "https://registry.npmmirror.com/@angular/material/-/material-20.0.4.tgz",
+      "integrity": "sha512-ET+znnyOVjBezHsjy7U42/88JPl9Mhumvf01gMBN8mNcaoSpeM4cc2uKBg30/3YzykKIsjXtvUJj/PaTujmJAQ==",
+      "license": "MIT",
+      "dependencies": {
+        "tslib": "^2.3.0"
+      },
+      "peerDependencies": {
+        "@angular/cdk": "20.0.4",
+        "@angular/common": "^20.0.0 || ^21.0.0",
+        "@angular/core": "^20.0.0 || ^21.0.0",
+        "@angular/forms": "^20.0.0 || ^21.0.0",
+        "@angular/platform-browser": "^20.0.0 || ^21.0.0",
+        "rxjs": "^6.5.3 || ^7.4.0"
+      }
+    },
     "node_modules/@angular/platform-browser": {
       "version": "20.0.5",
       "resolved": "https://registry.npmmirror.com/@angular/platform-browser/-/platform-browser-20.0.5.tgz",
@@ -7018,7 +7052,6 @@
       "version": "7.3.0",
       "resolved": "https://registry.npmmirror.com/parse5/-/parse5-7.3.0.tgz",
       "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
-      "dev": true,
       "license": "MIT",
       "dependencies": {
         "entities": "^6.0.0"
@@ -7072,7 +7105,6 @@
       "version": "6.0.1",
       "resolved": "https://registry.npmmirror.com/entities/-/entities-6.0.1.tgz",
       "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
-      "dev": true,
       "license": "BSD-2-Clause",
       "engines": {
         "node": ">=0.12"

+ 1 - 0
package.json

@@ -24,6 +24,7 @@
     "@angular/compiler": "^20.0.0",
     "@angular/core": "^20.0.0",
     "@angular/forms": "^20.0.0",
+    "@angular/material": "^20.0.4",
     "@angular/platform-browser": "^20.0.0",
     "@angular/router": "^20.0.0",
     "rxjs": "~7.8.0",

+ 2 - 2
src/app/app.config.ts

@@ -1,12 +1,12 @@
 import { ApplicationConfig, provideBrowserGlobalErrorListeners, provideZoneChangeDetection } from '@angular/core';
 import { provideRouter } from '@angular/router';
 
-import { routes } from './app.routes';
+import { APP_ROUTES } from './app.routes';
 
 export const appConfig: ApplicationConfig = {
   providers: [
     provideBrowserGlobalErrorListeners(),
     provideZoneChangeDetection({ eventCoalescing: true }),
-    provideRouter(routes)
+    provideRouter(APP_ROUTES)
   ]
 };

文件差异内容过多而无法显示
+ 0 - 194
src/app/app.html


+ 15 - 0
src/app/app.module.ts

@@ -0,0 +1,15 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { RouterModule } from '@angular/router';
+import { MOBILE_ROUTES } from '../modules/hr/mobile/mobile.routes';
+
+@NgModule({
+  declarations: [
+    // 你的组件
+  ],
+  imports: [
+    CommonModule,
+    RouterModule.forChild(MOBILE_ROUTES)
+  ]
+})
+export class MobileModule {}

+ 16 - 1
src/app/app.routes.ts

@@ -1,3 +1,18 @@
 import { Routes } from '@angular/router';
 
-export const routes: Routes = [];
+export const APP_ROUTES: Routes = [
+  // 其他路由...
+  
+  {
+    path: 'mobile',
+    loadChildren: () => import('../modules/hr/mobile/mobile.routes').then(m => m.MOBILE_ROUTES)
+  },
+
+  {
+    path: "interviews",
+    pathMatch:"full",
+    redirectTo:"/mobile/interviews"
+
+  }
+  // 默认路由或重定向...
+];

+ 1 - 0
src/app/app.ts

@@ -3,6 +3,7 @@ import { RouterOutlet } from '@angular/router';
 
 @Component({
   selector: 'app-root',
+  standalone: true,
   imports: [RouterOutlet],
   templateUrl: './app.html',
   styleUrl: './app.scss'

+ 35 - 0
src/modules/hr/mobile/candidate-tabs/candidate-tabs.html

@@ -0,0 +1,35 @@
+<div class="tabs-container">
+      <!-- Router outlet for tab content -->
+      <div class="tab-content">
+        <router-outlet></router-outlet>
+      </div>
+      
+      <!-- Tab navigation -->
+      <nav class="tabs-nav">
+        <a 
+          routerLink="interviews" 
+          routerLinkActive="active"
+          [routerLinkActiveOptions]="{ exact: false }"
+          class="tab-item"
+        >
+          <span class="tab-icon">📅</span>
+          <span class="tab-label">Interviews</span>
+        </a>
+        <a 
+          routerLink="preparation" 
+          routerLinkActive="active"
+          class="tab-item"
+        >
+          <span class="tab-icon">📚</span>
+          <span class="tab-label">Preparation</span>
+        </a>
+        <a 
+          routerLink="profile" 
+          routerLinkActive="active"
+          class="tab-item"
+        >
+          <span class="tab-icon">👤</span>
+          <span class="tab-label">Profile</span>
+        </a>
+      </nav>
+    </div>

+ 38 - 0
src/modules/hr/mobile/candidate-tabs/candidate-tabs.scss

@@ -0,0 +1,38 @@
+/* modules/hr/mobile/candidate-tabs/candidate-tabs.scss */
+.tabs-container {
+  position: fixed;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  display: flex;
+  justify-content: space-around;
+  background: #fff;
+  box-shadow: 0 -2px 10px rgba(0,0,0,0.1);
+  padding: 8px 0;
+  z-index: 100;
+
+  .tab-item {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    font-size: 12px;
+    color: #666;
+    cursor: pointer;
+
+    ion-icon {
+      font-size: 24px;
+      margin-bottom: 4px;
+    }
+
+    &.active {
+      color: #2563eb;
+      font-weight: 500;
+    }
+  }
+}
+
+/* 为路由内容预留空间 */
+router-outlet + * {
+  margin-bottom: 60px;
+  display: block;
+}

+ 35 - 0
src/modules/hr/mobile/candidate-tabs/candidate-tabs.spec.ts

@@ -0,0 +1,35 @@
+// candidate-tabs.spec.ts
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { Router } from '@angular/router';
+import { CandidateTabsComponent } from './candidate-tabs';
+import { RouterTestingModule } from '@angular/router/testing';
+import { By } from '@angular/platform-browser'; 
+
+describe('CandidateTabsComponent', () => {
+  let component: CandidateTabsComponent;
+  let fixture: ComponentFixture<CandidateTabsComponent>;
+  let router: Router;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [
+        CandidateTabsComponent,
+        RouterTestingModule.withRoutes([]) // 添加路由测试模块
+      ]
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(CandidateTabsComponent);
+    component = fixture.componentInstance;
+    router = TestBed.inject(Router); // 正确获取Router实例
+    fixture.detectChanges();
+  });
+
+  it('应该正确导航', () => {
+    const navigateSpy = spyOn(router, 'navigate'); // 使用已注入的router
+    
+    const button = fixture.debugElement.queryAll(By.css('.tab-button'))[1];
+    button.triggerEventHandler('click', null);
+    
+    expect(navigateSpy).toHaveBeenCalledWith(['/mobile/candidate/interviews']);
+  });
+});

+ 54 - 0
src/modules/hr/mobile/candidate-tabs/candidate-tabs.ts

@@ -0,0 +1,54 @@
+// candidate-tabs.component.ts
+import { Component } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { RouterLink, RouterLinkActive, RouterOutlet } from '@angular/router';
+
+@Component({
+  selector: 'app-candidate-tabs',
+  standalone: true,
+  imports: [CommonModule, RouterOutlet, RouterLink, RouterLinkActive],
+  templateUrl:"candidate-tabs.html",
+  styles: [`
+    .tabs-container {
+      display: flex;
+      flex-direction: column;
+      height: 100vh;
+    }
+    
+    .tab-content {
+      flex: 1;
+      overflow-y: auto;
+    }
+    
+    .tabs-nav {
+      display: flex;
+      justify-content: space-around;
+      padding: 10px 0;
+      background-color: #f8f9fa;
+      border-top: 1px solid #dee2e6;
+    }
+    
+    .tab-item {
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      text-decoration: none;
+      color: #495057;
+      padding: 5px 10px;
+    }
+    
+    .tab-item.active {
+      color: #0d6efd;
+    }
+    
+    .tab-icon {
+      font-size: 1.5rem;
+      margin-bottom: 4px;
+    }
+    
+    .tab-label {
+      font-size: 0.8rem;
+    }
+  `]
+})
+export class CandidateTabsComponent {}

+ 1 - 0
src/modules/hr/mobile/interviews/interviews.html

@@ -0,0 +1 @@
+<p>interviews works!</p>

+ 0 - 0
src/modules/hr/mobile/interviews/interviews.scss


+ 11 - 0
src/modules/hr/mobile/interviews/interviews.ts

@@ -0,0 +1,11 @@
+import { Component } from '@angular/core';
+
+@Component({
+  selector: 'app-interviews',
+  imports: [],
+  templateUrl: './interviews.html',
+  styleUrl: './interviews.scss'
+})
+export class Interviews {
+
+}

+ 34 - 0
src/modules/hr/mobile/mobile.routes.ts

@@ -0,0 +1,34 @@
+import { Routes } from '@angular/router';
+import { CandidateTabsComponent } from './candidate-tabs/candidate-tabs';
+
+export const MOBILE_ROUTES: Routes = [
+  {
+    path: '',
+    component: CandidateTabsComponent,
+    children: [
+      {
+        path: 'interviews',
+        loadComponent: () => 
+          import('./interviews/interviews').then(m => m.Interviews),
+        data: { title: 'Interviews' }
+      },
+      {
+        path: 'preparation',
+        loadComponent: () => 
+          import('./preparation/preparation').then(m => m.Preparation),
+        data: { title: 'Preparation' }
+      },
+      {
+        path: 'profile',
+        loadComponent: () => 
+          import('./profile/profile').then(m => m.Profile),
+        data: { title: 'Profile' }
+      },
+      {
+        path: '',
+        redirectTo: 'interviews',
+        pathMatch: 'full'
+      }
+    ]
+  }
+];

+ 1 - 0
src/modules/hr/mobile/preparation/preparation.html

@@ -0,0 +1 @@
+<p>preparation works!</p>

+ 0 - 0
src/modules/hr/mobile/preparation/preparation.scss


+ 11 - 0
src/modules/hr/mobile/preparation/preparation.ts

@@ -0,0 +1,11 @@
+import { Component } from '@angular/core';
+
+@Component({
+  selector: 'app-preparation',
+  imports: [],
+  templateUrl: './preparation.html',
+  styleUrl: './preparation.scss'
+})
+export class Preparation {
+
+}

+ 1 - 0
src/modules/hr/mobile/profile/profile.html

@@ -0,0 +1 @@
+<p>profile works!</p>

+ 0 - 0
src/modules/hr/mobile/profile/profile.scss


+ 11 - 0
src/modules/hr/mobile/profile/profile.ts

@@ -0,0 +1,11 @@
+import { Component } from '@angular/core';
+
+@Component({
+  selector: 'app-profile',
+  imports: [],
+  templateUrl: './profile.html',
+  styleUrl: './profile.scss'
+})
+export class Profile {
+
+}

+ 1 - 0
src/modules/hr/mobile/recruiter-tabs/recruiter-tabs.html

@@ -0,0 +1 @@
+<p>recruiter-tabs works!</p>

+ 0 - 0
src/modules/hr/mobile/recruiter-tabs/recruiter-tabs.scss


+ 23 - 0
src/modules/hr/mobile/recruiter-tabs/recruiter-tabs.spec.ts

@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { RecruiterTabs } from './recruiter-tabs';
+
+describe('RecruiterTabs', () => {
+  let component: RecruiterTabs;
+  let fixture: ComponentFixture<RecruiterTabs>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [RecruiterTabs]
+    })
+    .compileComponents();
+
+    fixture = TestBed.createComponent(RecruiterTabs);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 11 - 0
src/modules/hr/mobile/recruiter-tabs/recruiter-tabs.ts

@@ -0,0 +1,11 @@
+import { Component } from '@angular/core';
+
+@Component({
+  selector: 'app-recruiter-tabs',
+  imports: [],
+  templateUrl: './recruiter-tabs.html',
+  styleUrl: './recruiter-tabs.scss'
+})
+export class RecruiterTabs {
+
+}

部分文件因为文件数量过多而无法显示