Browse Source

fit:login

0225304 3 days ago
parent
commit
59b6f05c96

+ 7 - 4
myapp/src/app/app-routing.module.ts

@@ -1,19 +1,22 @@
 import { NgModule } from '@angular/core';
 import { PreloadAllModules, RouterModule, Routes } from '@angular/router';
+import { AuthGuard } from '../app/tabs/auth.guard';
 
 const routes: Routes = [
+  {
+    path: 'login',
+    loadChildren: () => import('./tab4/login/login.module').then(m => m.LoginPageModule)
+  },
   {
     path: '',
     loadChildren: () => import('./tabs/tabs.module').then(m => m.TabsPageModule)
+    
   },
   {
     path: 'tab4',
     loadChildren: () => import('./tab4/tab4.module').then( m => m.Tab4PageModule)
   },
-  {
-    path: 'tab4',
-    loadChildren: () => import('./tab4/tab4.module').then( m => m.Tab4PageModule)
-  }
+
 ];
 @NgModule({
   imports: [

+ 75 - 0
myapp/src/app/login/login.page.ts

@@ -0,0 +1,75 @@
+// login.page.ts
+import { Component } from '@angular/core';
+import { AuthService } from '../services/auth.service';
+import { Router } from '@angular/router';
+import { ToastController } from '@ionic/angular';
+
+@Component({
+  selector: 'app-login',
+  templateUrl: './login.page.html',
+  styleUrls: ['./login.page.scss'],
+  standalone:false,
+})
+export class LoginPage {
+  username = '';
+  password = '';
+  isLogin = true; // 切换登录/注册模式
+  email = ''; // 注册时使用
+
+  constructor(
+    private authService: AuthService,
+    private router: Router,
+    private toastCtrl: ToastController
+  ) {}
+
+  async submit() {
+    if (this.isLogin) {
+      await this.handleLogin();
+    } else {
+      await this.handleRegister();
+    }
+  }
+
+  private async handleLogin() {
+    if (!this.username || !this.password) {
+      this.showToast('请输入用户名和密码');
+      return;
+    }
+
+    const success = await this.authService.login(this.username, this.password);
+    if (success) {
+      this.showToast('登录成功');
+      this.router.navigate(['/tabs/tab1']);
+    } else {
+      this.showToast('登录失败,请检查用户名和密码');
+    }
+  }
+
+  private async handleRegister() {
+    if (!this.username || !this.password) {
+      this.showToast('请输入用户名和密码');
+      return;
+    }
+
+    const success = await this.authService.register(this.username, this.password, this.email);
+    if (success) {
+      this.showToast('注册成功,已自动登录');
+      this.router.navigate(['/tabs/tab1']);
+    } else {
+      this.showToast('注册失败,用户名可能已被使用');
+    }
+  }
+
+  toggleMode() {
+    this.isLogin = !this.isLogin;
+  }
+
+  private async showToast(message: string) {
+    const toast = await this.toastCtrl.create({
+      message,
+      duration: 2000,
+      position: 'top'
+    });
+    await toast.present();
+  }
+}

+ 73 - 0
myapp/src/app/services/auth.service.ts

@@ -0,0 +1,73 @@
+// auth.service.ts
+import { Injectable } from '@angular/core';
+import { CloudUser } from 'src/lib/ncloud';
+import { Router } from '@angular/router';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class AuthService {
+  private currentUser: CloudUser | null = null;
+
+  constructor(private router: Router) {
+    this.initializeUser();
+  }
+
+  private initializeUser() {
+    this.currentUser = new CloudUser();
+  }
+
+  // 获取当前用户
+  async getCurrentUser() {
+    if (!this.currentUser) {
+      this.initializeUser();
+    }
+    return await this.currentUser?.current();
+  }
+
+  // 用户登录
+  async login(username: string, password: string): Promise<boolean> {
+    try {
+      const user = await this.currentUser?.login(username, password);
+      if (user) {
+        return true;
+      }
+      return false;
+    } catch (error) {
+      console.error('登录失败:', error);
+      return false;
+    }
+  }
+
+  // 用户注册
+  async register(username: string, password: string, email?: string): Promise<boolean> {
+    try {
+      const additionalData = email ? { email } : {};
+      const user = await this.currentUser?.signUp(username, password, additionalData);
+      return !!user;
+    } catch (error) {
+      console.error('注册失败:', error);
+      return false;
+    }
+  }
+
+  // 用户登出
+  async logout(): Promise<boolean> {
+    try {
+      const success = await this.currentUser?.logout();
+      if (success) {
+        this.currentUser = null;
+        this.router.navigate(['/login']);
+      }
+      return !!success;
+    } catch (error) {
+      console.error('登出失败:', error);
+      return false;
+    }
+  }
+
+  // 检查是否已登录
+  isAuthenticated(): boolean {
+    return !!this.currentUser?.sessionToken;
+  }
+}

+ 1 - 1
myapp/src/app/tab1/edit/edit.module.ts

@@ -15,6 +15,6 @@ import { EditPage } from './edit.page';
     IonicModule,
     EditPageRoutingModule
   ],
-  declarations: [EditPage]
+  declarations: [EditPage],
 })
 export class EditPageModule {}

+ 53 - 8
myapp/src/app/tab1/edit/edit.page.html

@@ -1,13 +1,58 @@
-<ion-header [translucent]="true">
+<ion-header>
   <ion-toolbar>
-    <ion-title>edit</ion-title>
+    <ion-buttons slot="start">
+      <ion-button (click)="navCtrl.back()">取消</ion-button>
+    </ion-buttons>
+    <ion-title>{{action}}日记</ion-title>
+    <ion-buttons slot="end">
+      <ion-button (click)="saveDiary()">保存</ion-button>
+    </ion-buttons>
   </ion-toolbar>
 </ion-header>
 
-<ion-content [fullscreen]="true">
-  <ion-header collapse="condense">
-    <ion-toolbar>
-      <ion-title size="large">edit</ion-title>
-    </ion-toolbar>
-  </ion-header>
+<ion-content>
+  <ion-list>
+    <ion-item>
+      <ion-label>日期</ion-label>
+      <ion-text>{{diary.date}}日 {{diary.weekday}} {{diary.time}}</ion-text>
+    </ion-item>
+    
+    <ion-item>
+      <ion-label>天气</ion-label>
+      <ion-select [(ngModel)]="diary.weather" interface="popover">
+        <ion-select-option value="晴">晴</ion-select-option>
+        <ion-select-option value="多云">多云</ion-select-option>
+        <ion-select-option value="阴">阴</ion-select-option>
+        <ion-select-option value="雨">雨</ion-select-option>
+        <ion-select-option value="雪">雪</ion-select-option>
+      </ion-select>
+    </ion-item>
+    
+    <ion-item>
+      <ion-label>心情</ion-label>
+      <ion-select [(ngModel)]="diary.mood" interface="popover">
+        <ion-select-option value="😊">😊 开心</ion-select-option>
+        <ion-select-option value="😌">😌 平静</ion-select-option>
+        <ion-select-option value="🥰">🥰 幸福</ion-select-option>
+        <ion-select-option value="😄">😄 大笑</ion-select-option>
+        <ion-select-option value="😺">😺 调皮</ion-select-option>
+        <ion-select-option value="🍂">🍂 怀旧</ion-select-option>
+        <ion-select-option value="📖">📖 思考</ion-select-option>
+      </ion-select>
+    </ion-item>
+  </ion-list>
+
+  <ion-textarea
+    [(ngModel)]="diary.content"
+    placeholder="写下你的日记..."
+    autoGrow="true"
+    rows="10"
+    style="padding: 10px;"
+  ></ion-textarea>
+
+  <ion-fab vertical="bottom" horizontal="end" slot="fixed" *ngIf="action === '查看'">
+    <ion-fab-button (click)="deleteDiary()" color="danger">
+      <ion-icon name="trash"></ion-icon>
+    </ion-fab-button>
+  </ion-fab>
 </ion-content>

+ 83 - 6
myapp/src/app/tab1/edit/edit.page.ts

@@ -1,16 +1,93 @@
-import { Component, OnInit } from '@angular/core';
+import { Component } from '@angular/core';
+import { NavController, NavParams } from '@ionic/angular';
+import { CloudObject } from 'src/lib/ncloud';
 
 @Component({
   selector: 'app-edit',
-  templateUrl: './edit.page.html',
-  styleUrls: ['./edit.page.scss'],
+  templateUrl: 'edit.page.html',
+  styleUrls: ['edit.page.scss'],
   standalone:false,
 })
+export class EditPage {
+  action: string = '新建';
+  diary: any = {
+    date: new Date().getDate().toString(),
+    weekday: this.getWeekday(new Date()),
+    time: this.getCurrentTime(),
+    content: '',
+    weather: '晴',
+    mood: '😊'
+  };
 
-export class EditPage implements OnInit {
-  constructor() { }
+  constructor(
+    public navCtrl: NavController,
+    private navParams: NavParams
+  ) {
+    const params = this.navParams.get('queryParams');
+    this.action = params?.action || '新建';
+    
+    if (params?.diary) {
+      this.diary = JSON.parse(params.diary);
+    }
+  }
+
+  // 获取星期几
+  private getWeekday(date: Date): string {
+    const weekdays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
+    return weekdays[date.getDay()];
+  }
+
+  // 获取当前时间
+  private getCurrentTime(): string {
+    const now = new Date();
+    const hours = now.getHours().toString().padStart(2, '0');
+    const minutes = now.getMinutes().toString().padStart(2, '0');
+    return `${hours}:${minutes}`;
+  }
+
+  // 保存日记
+  async saveDiary() {
+    if (!this.diary.content) {
+      console.error('日记内容不能为空');
+      return;
+    }
+
+    const diaryObj = new CloudObject('Diary');
+    
+    // 如果是编辑现有日记
+    if (this.diary.objectId) {
+      diaryObj.id = this.diary.objectId;
+    }
+    
+    // 设置日记数据
+    diaryObj.set({
+      ...this.diary,
+      updatedAt: new Date().toISOString()
+    });
+
+    try {
+      await diaryObj.save();
+      this.navCtrl.back(); // 返回上一页
+    } catch (error) {
+      console.error('保存日记失败:', error);
+    }
+  }
 
-  ngOnInit() {
+  // 删除日记
+  async deleteDiary() {
+    if (!this.diary.objectId) {
+      console.error('无法删除未保存的日记');
+      return;
+    }
 
+    const diaryObj = new CloudObject('Diary');
+    diaryObj.id = this.diary.objectId;
+    
+    try {
+      await diaryObj.destroy();
+      this.navCtrl.back(); // 返回上一页
+    } catch (error) {
+      console.error('删除日记失败:', error);
+    }
   }
 }

+ 5 - 1
myapp/src/app/tab1/tab1.page.html

@@ -10,9 +10,12 @@
         <div class="header-title">日记本</div>
         
         <ion-buttons slot="end">
-        <ion-fab-button (click)="goToEditPage()" size="small">
+        <ion-fab-button (click)="goToEditPage('新建')" size="small">
             <ion-icon name="add"></ion-icon>
         </ion-fab-button>
+         <ion-button (click)="logout('登出')">
+            <ion-icon slot="icon-only" name="log-out-outline"></ion-icon>
+        </ion-button>
         </ion-buttons>
     </div>
 
@@ -36,4 +39,5 @@
         </div>
         }
     </div>
+    
 </ion-content>

+ 238 - 88
myapp/src/app/tab1/tab1.page.ts

@@ -1,108 +1,258 @@
-import { Component } from '@angular/core';
+import { Component, OnInit } from '@angular/core';
 import { NavController } from '@ionic/angular';
 
 import { addIcons } from 'ionicons';
 import { add } from 'ionicons/icons';
-import { CloudObject, CloudQuery } from 'src/lib/ncloud';
-
+import { CloudObject, CloudQuery,CloudUser } from 'src/lib/ncloud';
+import { AuthService } from '../services/auth.service';
 @Component({
   selector: 'app-tab1',
   templateUrl: 'tab1.page.html',
   styleUrls: ['tab1.page.scss'],
   standalone: false,
 })
-export class Tab1Page {
+export class Tab1Page implements OnInit{
+  router: any;
+   
+  async ngOnInit(){
+    await this.loadDiaries();
+  }
+
+  // 加载日记列表
+  async loadDiaries() {
+    const query = new CloudQuery('Diary');
+    query.equalTo('owner', (await this.getCurrentUser())?.id);
+    const diaries = await query.find();
+    this.messageList = diaries.map(diary => diary.data).sort((a, b) => {
+      return new Date(b['createdAt']).getTime() - new Date(a['createdAt']).getTime();
+    });
+  }
+
+  // 获取当前用户
+  async getCurrentUser() {
+    const user = new CloudUser();
+    return await user.current();
+  }
 
+  // 跳转到编辑页面
+  async goToEditPage(action: string, diary?: any) {
+    const result = await this.navCtrl.navigateForward(['tabs', 'tab1', 'edit'], {
+      queryParams: {
+        action,
+        diary: diary ? JSON.stringify(diary) : null
+      }
+    });
+    
+    // 如果是从编辑页面返回,刷新列表
+    if (result !== false) {
+      await this.loadDiaries();
+    }
+  }
+
+  // 批量导入静态数据
+  async importSampleDiaries() {
+    const user = await this.getCurrentUser();
+    if (!user) {
+      console.error('请先登录');
+      return;
+    }
+
+    const sampleDiaries = [
+      
+      {
+        "id": 1,
+        "date": "15",
+        "weekday": "周三",
+        "time": "14:30",
+        "content": "今天阳光明媚,去公园散步时看到樱花开了。粉色的花瓣随风飘落,美得像一幅画。坐在长椅上读了一会儿书,感觉心情特别平静。",
+        "weather": "晴",
+        "mood": "😊"
+      },
+      {
+        "id": 2,
+        "date": "14",
+        "weekday": "周二",
+        "time": "21:15",
+        "content": "项目终于告一段落,加班到很晚但很有成就感。回家的路上买了杯热奶茶犒劳自己,发现常去的那家奶茶店换了新包装,杯子上画着可爱的小兔子。",
+        "weather": "多云",
+        "mood": "😌"
+      },
+      {
+        "id": 3,
+        "date": "12",
+        "weekday": "周日",
+        "time": "09:45",
+        "content": "周末尝试做了新的菜谱 - 番茄牛腩。虽然炖的时间比预期长,但结果非常美味!下午窝在沙发上看了一部老电影,窗外下着小雨,这种慵懒的周末真是太棒了。",
+        "weather": "小雨",
+        "mood": "🥰"
+      },
+      {
+        "id": 4,
+        "date": "18",
+        "weekday": "周五",
+        "time": "18:20",
+        "content": "参加了公司的团队建设活动,第一次体验了攀岩项目。虽然爬到一半有些害怕,但在同事的鼓励下成功登顶,突破自我的感觉真好!",
+        "weather": "阴",
+        "mood": "😄"
+      },
+      {
+        "id": 5,
+        "date": "20",
+        "weekday": "周六",
+        "time": "15:10",
+        "content": "和朋友去了新开的猫咖,有十几只不同品种的猫咪。最喜欢那只胖乎乎的橘猫,它居然在我腿上睡了一下午,治愈了连日的疲惫。",
+        "weather": "晴",
+        "mood": "😺"
+      },
+      {
+        "id": 6,
+        "date": "22",
+        "weekday": "周一",
+        "time": "08:05",
+        "content": "早起晨跑时发现小区里的桂花开了,空气里都是甜甜的香气。顺手拍了张晨光中的花枝,设为手机壁纸后整天都有好心情。",
+        "weather": "雾",
+        "mood": "🌼"
+      },
+      {
+        "id": 7,
+        "date": "25",
+        "weekday": "周四",
+        "time": "19:40",
+        "content": "下班路上遇到卖糖炒栗子的小摊,热乎乎的栗子捧在手里,边走边吃仿佛回到学生时代。突然想念大学的林荫道和图书馆了。",
+        "weather": "微风",
+        "mood": "🍂"
+      },
+      {
+        "id": 8,
+        "date": "28",
+        "weekday": "周日",
+        "time": "22:30",
+        "content": "整理旧物时发现了高中时期的同学录,翻看那些青涩的留言和夸张的贴纸,忍不住笑出声。那些以为忘记的回忆突然都鲜活起来。",
+        "weather": "晴",
+        "mood": "📖"
+      }
+      // 其他日记数据...
+    ];
+
+    for (const diary of sampleDiaries) {
+      const diaryObj = new CloudObject('Diary');
+      diaryObj.set({
+        ...diary,
+        owner: user.id // 关联当前用户
+      });
+      await diaryObj.save();
+    }
+
+    await this.loadDiaries(); // 导入后刷新列表
+  }
+
+  messageList:any[]=[
+  // {
+  //   "id": 1,
+  //   "date": "15",
+  //   "weekday": "周三",
+  //   "time": "14:30",
+  //   "content": "今天阳光明媚,去公园散步时看到樱花开了。粉色的花瓣随风飘落,美得像一幅画。坐在长椅上读了一会儿书,感觉心情特别平静。",
+  //   "weather": "晴",
+  //   "mood": "😊"
+  // },
+  // {
+  //   "id": 2,
+  //   "date": "14",
+  //   "weekday": "周二",
+  //   "time": "21:15",
+  //   "content": "项目终于告一段落,加班到很晚但很有成就感。回家的路上买了杯热奶茶犒劳自己,发现常去的那家奶茶店换了新包装,杯子上画着可爱的小兔子。",
+  //   "weather": "多云",
+  //   "mood": "😌"
+  // },
+  // {
+  //   "id": 3,
+  //   "date": "12",
+  //   "weekday": "周日",
+  //   "time": "09:45",
+  //   "content": "周末尝试做了新的菜谱 - 番茄牛腩。虽然炖的时间比预期长,但结果非常美味!下午窝在沙发上看了一部老电影,窗外下着小雨,这种慵懒的周末真是太棒了。",
+  //   "weather": "小雨",
+  //   "mood": "🥰"
+  // },
+  // {
+  //   "id": 4,
+  //   "date": "18",
+  //   "weekday": "周五",
+  //   "time": "18:20",
+  //   "content": "参加了公司的团队建设活动,第一次体验了攀岩项目。虽然爬到一半有些害怕,但在同事的鼓励下成功登顶,突破自我的感觉真好!",
+  //   "weather": "阴",
+  //   "mood": "😄"
+  // },
+  // {
+  //   "id": 5,
+  //   "date": "20",
+  //   "weekday": "周六",
+  //   "time": "15:10",
+  //   "content": "和朋友去了新开的猫咖,有十几只不同品种的猫咪。最喜欢那只胖乎乎的橘猫,它居然在我腿上睡了一下午,治愈了连日的疲惫。",
+  //   "weather": "晴",
+  //   "mood": "😺"
+  // },
+  // {
+  //   "id": 6,
+  //   "date": "22",
+  //   "weekday": "周一",
+  //   "time": "08:05",
+  //   "content": "早起晨跑时发现小区里的桂花开了,空气里都是甜甜的香气。顺手拍了张晨光中的花枝,设为手机壁纸后整天都有好心情。",
+  //   "weather": "雾",
+  //   "mood": "🌼"
+  // },
+  // {
+  //   "id": 7,
+  //   "date": "25",
+  //   "weekday": "周四",
+  //   "time": "19:40",
+  //   "content": "下班路上遇到卖糖炒栗子的小摊,热乎乎的栗子捧在手里,边走边吃仿佛回到学生时代。突然想念大学的林荫道和图书馆了。",
+  //   "weather": "微风",
+  //   "mood": "🍂"
+  // },
+  // {
+  //   "id": 8,
+  //   "date": "28",
+  //   "weekday": "周日",
+  //   "time": "22:30",
+  //   "content": "整理旧物时发现了高中时期的同学录,翻看那些青涩的留言和夸张的贴纸,忍不住笑出声。那些以为忘记的回忆突然都鲜活起来。",
+  //   "weather": "晴",
+  //   "mood": "📖"
+  // }
+  ];
+  private diaryQuery = new CloudQuery("Diary");
+  
   constructor(
-    private navCtrl:NavController
+    private navCtrl:NavController,
+    private authService: AuthService,
   ) {
     addIcons({ add, });
   }
-  
-  messageList:any[]=[
-  {
-    "id": 1,
-    "date": "15",
-    "weekday": "周三",
-    "time": "14:30",
-    "content": "今天阳光明媚,去公园散步时看到樱花开了。粉色的花瓣随风飘落,美得像一幅画。坐在长椅上读了一会儿书,感觉心情特别平静。",
-    "weather": "晴",
-    "mood": "😊"
-  },
-  {
-    "id": 2,
-    "date": "14",
-    "weekday": "周二",
-    "time": "21:15",
-    "content": "项目终于告一段落,加班到很晚但很有成就感。回家的路上买了杯热奶茶犒劳自己,发现常去的那家奶茶店换了新包装,杯子上画着可爱的小兔子。",
-    "weather": "多云",
-    "mood": "😌"
-  },
-  {
-    "id": 3,
-    "date": "12",
-    "weekday": "周日",
-    "time": "09:45",
-    "content": "周末尝试做了新的菜谱 - 番茄牛腩。虽然炖的时间比预期长,但结果非常美味!下午窝在沙发上看了一部老电影,窗外下着小雨,这种慵懒的周末真是太棒了。",
-    "weather": "小雨",
-    "mood": "🥰"
-  },
-  {
-    "id": 4,
-    "date": "18",
-    "weekday": "周五",
-    "time": "18:20",
-    "content": "参加了公司的团队建设活动,第一次体验了攀岩项目。虽然爬到一半有些害怕,但在同事的鼓励下成功登顶,突破自我的感觉真好!",
-    "weather": "阴",
-    "mood": "😄"
-  },
-  {
-    "id": 5,
-    "date": "20",
-    "weekday": "周六",
-    "time": "15:10",
-    "content": "和朋友去了新开的猫咖,有十几只不同品种的猫咪。最喜欢那只胖乎乎的橘猫,它居然在我腿上睡了一下午,治愈了连日的疲惫。",
-    "weather": "晴",
-    "mood": "😺"
-  },
-  {
-    "id": 6,
-    "date": "22",
-    "weekday": "周一",
-    "time": "08:05",
-    "content": "早起晨跑时发现小区里的桂花开了,空气里都是甜甜的香气。顺手拍了张晨光中的花枝,设为手机壁纸后整天都有好心情。",
-    "weather": "雾",
-    "mood": "🌼"
-  },
-  {
-    "id": 7,
-    "date": "25",
-    "weekday": "周四",
-    "time": "19:40",
-    "content": "下班路上遇到卖糖炒栗子的小摊,热乎乎的栗子捧在手里,边走边吃仿佛回到学生时代。突然想念大学的林荫道和图书馆了。",
-    "weather": "微风",
-    "mood": "🍂"
-  },
-  {
-    "id": 8,
-    "date": "28",
-    "weekday": "周日",
-    "time": "22:30",
-    "content": "整理旧物时发现了高中时期的同学录,翻看那些青涩的留言和夸张的贴纸,忍不住笑出声。那些以为忘记的回忆突然都鲜活起来。",
-    "weather": "晴",
-    "mood": "📖"
+
+   // 查看日记详情
+  async goMessage(message: any) {
+    await this.goToEditPage('查看', message);
   }
-]
-  goMessage(message?:any){
-    console.log(message),
-    this.navCtrl.navigateForward(["tabs","tab1","message"],{
-      queryParams:message
-    })
-    return
+
+  // goMessage(message?:any){
+  //   console.log(message),
+  //   this.navCtrl.navigateForward(["tabs","tab1","message"],{
+  //     queryParams:message
+  //   })
+  //   return
+  // }
+
+  async logout(login?:string) {
+    await this.authService.logout();
+    this.router.navigate(['/login']);
   }
   
   //前往日记创建页面
-  goToEditPage(edit?:string){
-    this.navCtrl.navigateForward(["tabs","tab1","edit"]);
-  }
+  // goToEditPage(diary?:string){
+  //   this.navCtrl.navigateForward(["tabs","tab1","edit"],{
+  //     queryParams: { mode: 'create' }
+  //   });
+  
+  // }
+
 }

+ 4 - 4
myapp/src/app/tab2/thanks-cloud/thanks-cloud.page.ts

@@ -142,9 +142,9 @@ export class ThanksCloudPage implements OnInit {
     console.log("所有清单数据处理完成");
   }
   
-  addNewThanks() {
-    // 添加新感恩记录的逻辑
-    console.log('添加新记录');
-  }  
+  addNewThanks(){
+    console.log("添加清单")
+  }
+    
     
 }

+ 17 - 0
myapp/src/app/tab4/login/login-routing.module.ts

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

+ 20 - 0
myapp/src/app/tab4/login/login.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 { LoginPageRoutingModule } from './login-routing.module';
+
+import { LoginPage } from './login.page';
+
+@NgModule({
+  imports: [
+    CommonModule,
+    FormsModule,
+    IonicModule,
+    LoginPageRoutingModule
+  ],
+  declarations: [LoginPage]
+})
+export class LoginPageModule {}

+ 36 - 0
myapp/src/app/tab4/login/login.page.html

@@ -0,0 +1,36 @@
+<!-- login.page.html -->
+<ion-header>
+  <ion-toolbar>
+    <ion-buttons slot="start">
+      <ion-back-button defaultHref="/tabs/tab4"></ion-back-button>
+    </ion-buttons>
+    <ion-title>{{ isLogin ? '登录' : '注册' }}</ion-title>
+  </ion-toolbar>
+</ion-header>
+
+<ion-content class="ion-padding">
+  <div class="auth-container">
+    <ion-item>
+      <ion-label position="floating">用户名</ion-label>
+      <ion-input [(ngModel)]="username" type="text"></ion-input>
+    </ion-item>
+
+    <ion-item>
+      <ion-label position="floating">密码</ion-label>
+      <ion-input [(ngModel)]="password" type="password"></ion-input>
+    </ion-item>
+
+    <ion-item *ngIf="!isLogin">
+      <ion-label position="floating">邮箱 (可选)</ion-label>
+      <ion-input [(ngModel)]="email" type="email"></ion-input>
+    </ion-item>
+
+    <ion-button expand="block" (click)="submit()" class="ion-margin-top">
+      {{ isLogin ? '登录' : '注册' }}
+    </ion-button>
+
+    <ion-button expand="block" fill="clear" (click)="toggleMode()">
+      {{ isLogin ? '没有账号?立即注册' : '已有账号?立即登录' }}
+    </ion-button>
+  </div>
+</ion-content>

+ 0 - 0
myapp/src/app/tab4/login/login.page.scss


+ 17 - 0
myapp/src/app/tab4/login/login.page.spec.ts

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

+ 75 - 0
myapp/src/app/tab4/login/login.page.ts

@@ -0,0 +1,75 @@
+// login.page.ts
+import { Component } from '@angular/core';
+import { AuthService } from 'src/app/services/auth.service';
+import { Router } from '@angular/router';
+import { ToastController } from '@ionic/angular';
+
+@Component({
+  selector: 'app-login',
+  templateUrl: './login.page.html',
+  styleUrls: ['./login.page.scss'],
+  standalone:false,
+})
+export class LoginPage {
+  username = '';
+  password = '';
+  isLogin = true; // 切换登录/注册模式
+  email = ''; // 注册时使用
+
+  constructor(
+    private authService: AuthService,
+    private router: Router,
+    private toastCtrl: ToastController
+  ) {}
+
+  async submit() {
+    if (this.isLogin) {
+      await this.handleLogin();
+    } else {
+      await this.handleRegister();
+    }
+  }
+
+  private async handleLogin() {
+    if (!this.username || !this.password) {
+      this.showToast('请输入用户名和密码');
+      return;
+    }
+
+    const success = await this.authService.login(this.username, this.password);
+    if (success) {
+      this.showToast('登录成功');
+      this.router.navigate(['/tabs/tab1']);
+    } else {
+      this.showToast('登录失败,请检查用户名和密码');
+    }
+  }
+
+  private async handleRegister() {
+    if (!this.username || !this.password) {
+      this.showToast('请输入用户名和密码');
+      return;
+    }
+
+    const success = await this.authService.register(this.username, this.password, this.email);
+    if (success) {
+      this.showToast('注册成功,已自动登录');
+      this.router.navigate(['/tabs/tab1']);
+    } else {
+      this.showToast('注册失败,用户名可能已被使用');
+    }
+  }
+
+  toggleMode() {
+    this.isLogin = !this.isLogin;
+  }
+
+  private async showToast(message: string) {
+    const toast = await this.toastCtrl.create({
+      message,
+      duration: 2000,
+      position: 'top'
+    });
+    await toast.present();
+  }
+}

+ 5 - 0
myapp/src/app/tab4/tab4-routing.module.ts

@@ -11,8 +11,13 @@ const routes: Routes = [
   {
     path: 'diary',
     loadChildren: () => import('./owner-diary/owner-diary.module').then( m => m.OwnerDiaryPageModule)
+  },
+  {
+    path: 'login',
+    loadChildren: () => import('./login/login.module').then( m => m.LoginPageModule)
   }
 
+
 ];
 
 @NgModule({

+ 1 - 1
myapp/src/app/tab4/tab4.page.html

@@ -12,7 +12,7 @@
     <!-- 顶部信息栏 -->
     <div class="profile-header">
         <div class="user-info">
-            <div>
+            <div (click)="goLogin('登录')">
                 <div class="user-name">匿名兔ffe</div>
                 <div class="user-id">UID:a15143bcf10c4d...</div>
             </div>

+ 4 - 0
myapp/src/app/tab4/tab4.page.ts

@@ -20,4 +20,8 @@ export class Tab4Page implements OnInit {
 
     this.navCtrl.navigateForward(["tabs","tab4","diary"])
   }
+
+  goLogin(user?:string){
+    this.navCtrl.navigateForward(["tabs","tab4","login"])
+  }
 }

+ 20 - 0
myapp/src/app/tabs/auth.guard.ts

@@ -0,0 +1,20 @@
+// auth.guard.ts
+import { Injectable } from '@angular/core';
+import { CanActivate, Router } from '@angular/router';
+import { AuthService } from 'src/app/services/auth.service';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class AuthGuard implements CanActivate {
+  constructor(private authService: AuthService, private router: Router) {}
+
+  async canActivate(): Promise<boolean> {
+    const isAuthenticated = this.authService.isAuthenticated();
+    if (!isAuthenticated) {
+      this.router.navigate(['/login']);
+      return false;
+    }
+    return true;
+  }
+}

+ 1 - 1
myapp/user-server/test/test-auth.js

@@ -3,7 +3,7 @@ async function testAuthFlow() {
     const testUsername = `testuser_${Math.floor(Math.random() * 10000)}`;
     const testPassword = 'testpassword123';
 
-    console.log(`测试用户: ${testUsername}`);
+    console.log(`测试用户: ${testUsername}`);8
 
     try {
         // 尝试登录(预期失败)