Browse Source

feat:login

Midnight 3 weeks ago
parent
commit
e323a7171f

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

@@ -6,10 +6,7 @@ const routes: Routes = [
     path: '',
     loadChildren: () => import('./tabs/tabs.module').then(m => m.TabsPageModule)
   },
-  {
-    path: 'tab4',
-    loadChildren: () => import('./tab4/tab4.module').then( m => m.Tab4PageModule)
-  }
+
 ];
 @NgModule({
   imports: [

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

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

+ 0 - 20
myapp/src/app/tab4/tab4.module.ts

@@ -1,20 +0,0 @@
-import { NgModule } from '@angular/core';
-import { CommonModule } from '@angular/common';
-import { FormsModule } from '@angular/forms';
-
-import { IonicModule } from '@ionic/angular';
-
-import { Tab4PageRoutingModule } from './tab4-routing.module';
-
-import { Tab4Page } from './tab4.page';
-
-@NgModule({
-  imports: [
-    CommonModule,
-    FormsModule,
-    IonicModule,
-    Tab4PageRoutingModule
-  ],
-  declarations: [Tab4Page]
-})
-export class Tab4PageModule {}

+ 0 - 128
myapp/src/app/tab4/tab4.page.html

@@ -1,128 +0,0 @@
-<ion-header [translucent]="true">
-  <meta charset="UTF-8">
-    <meta name="viewport" content="width=device-width, initial-scale=1.0">
-    <title>明律通 - AI法律顾问</title>
-    <!-- 引入国内CDN资源 -->
-    <link href="https://cdn.bootcdn.net/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
-
-</ion-header>
-
-<ion-content [fullscreen]="true">
-  <div class="container">
-        <!-- 我的页面 -->
-        <div class="page" id="profile-page">
-            <!-- 个人资料区域 -->
-            <div class="profile-section">
-                <div class="profile-bg"></div>
-                <div class="profile-avatar">U</div>
-                <div class="profile-name">用户名</div>
-                <div class="profile-email">user&#64;example.com</div>
-            </div>
-            
-            <!-- 功能入口网格 -->
-            <div class="features-section">
-                <div class="section-title">
-                    常用功能
-                    <a href="#">管理</a>
-                </div>
-                <div class="features-grid">
-                    <div class="feature-card">
-                        <div class="feature-icon">
-                            <i class="fas fa-file-alt"></i>
-                        </div>
-                        <div class="feature-title">我的文书</div>
-                        <div class="feature-desc">查看和管理您的法律文书</div>
-                    </div>                   
-                    <div class="feature-card">
-                        <div class="feature-icon">
-                            <i class="fas fa-star"></i>
-                        </div>
-                        <div class="feature-title">收藏夹</div>
-                        <div class="feature-desc">您收藏的法律知识和案例</div>
-                    </div>
-                </div>
-            </div>
-            
-            
-            
-            <!-- 律师入驻区域 -->
-            <div class="lawyer-section">
-                <div class="lawyer-header">
-                    <div class="lawyer-title">律师入驻</div>
-                    <div class="lawyer-status" id="lawyer-status">未入驻</div>
-                </div>
-                <button class="lawyer-btn" id="apply-lawyer">
-                    立即申请入驻
-                </button>
-            </div>
-            
-            <!-- 设置区域 -->
-            <div class="settings-section">
-                <ul class="settings-list">
-                    <li class="setting-item">
-                        <div class="setting-icon">
-                            <i class="fas fa-user-shield"></i>
-                        </div>
-                        <div class="setting-content">
-                            <div class="setting-title">账户安全</div>
-                            <div class="setting-desc">修改密码、设置密保</div>
-                        </div>
-                        <div class="setting-arrow">
-                            <i class="fas fa-chevron-right"></i>
-                        </div>
-                    </li>
-                    <li class="setting-item">
-                        <div class="setting-icon">
-                            <i class="fas fa-bell"></i>
-                        </div>
-                        <div class="setting-content">
-                            <div class="setting-title">消息通知</div>
-                            <div class="setting-desc">设置接收通知类型</div>
-                        </div>
-                        <div class="setting-arrow">
-                            <i class="fas fa-chevron-right"></i>
-                        </div>
-                    </li>
-                    <li class="setting-item">
-                        <div class="setting-icon">
-                            <i class="fas fa-cog"></i>
-                        </div>
-                        <div class="setting-content">
-                            <div class="setting-title">通用设置</div>
-                            <div class="setting-desc">消息提醒、隐私设置</div>
-                        </div>
-                        <div class="setting-arrow">
-                            <i class="fas fa-chevron-right"></i>
-                        </div>
-                    </li>
-                    <li class="setting-item">
-                        <div class="setting-icon">
-                            <i class="fas fa-question-circle"></i>
-                        </div>
-                        <div class="setting-content">
-                            <div class="setting-title">帮助中心</div>
-                            <div class="setting-desc">常见问题与解答</div>
-                        </div>
-                        <div class="setting-arrow">
-                            <i class="fas fa-chevron-right"></i>
-                        </div>
-                    </li>
-                    <li class="setting-item">
-                        <div class="setting-icon">
-                            <i class="fas fa-sign-out-alt"></i>
-                        </div>
-                        <div class="setting-content">
-                            <div class="setting-title">退出登录</div>
-                            <div class="setting-desc">安全退出当前账号</div>
-                        </div>
-                        <div class="setting-arrow">
-                            <i class="fas fa-chevron-right"></i>
-                        </div>
-                    </li>
-                </ul>
-            </div>
-        </div>
-        
-        
-    </div>
-</ion-content>

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

@@ -1,251 +0,0 @@
-ion-content {
-    --background: linear-gradient(135deg, #F8F9FF, #E6F7FF);
-    background-size: cover;   
-    --padding-start: 16px;  
-    --padding-end: 16px; 
-     
-}
-
-        :root {
-            --primary: #3A5FE5;
-            --secondary: #00C4A1;
-            --danger: #FF4D4F;
-            --bg: #F8F9FF;
-            --text: #2D3748;
-            --card: #FFFFFF;
-            --border: #E2E8F0;
-            --gray: #94A3B8;
-        }
-        
-        * {
-            margin: 0;
-            padding: 0;
-            box-sizing: border-box;
-            font-family: "PingFang SC", "Microsoft YaHei", sans-serif;
-        }
-        
-        .container {
-            width: 100%;
-            max-width: 480px;
-            margin: 0 auto;
-            padding: 15px;
-            min-height: 100vh;
-            display: flex;
-            flex-direction: column;
-        }
-        
-        /* 顶部区域 */
-        .profile-section {
-            display: flex;
-            flex-direction: column;
-            align-items: center;
-            padding: 30px 0 20px;
-            background: linear-gradient(135deg, #6A8EFF, #3A5FE5);
-            border-radius: 0 0 30px 30px;
-            margin-bottom: 20px;
-            position: relative;
-            overflow: hidden;
-        }
-        
-        .profile-bg {
-            position: absolute;
-            top: -50%;
-            left: -50%;
-            width: 200%;
-            height: 200%;
-            background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><circle cx="50" cy="50" r="40" fill="none" stroke="rgba(255,255,255,0.2)" stroke-width="2"/></svg>');
-            background-size: 100px 100px;
-            animation: rotate 60s linear infinite;
-            z-index: 0;
-        }
-        
-        @keyframes rotate {
-            from { transform: rotate(0deg); }
-            to { transform: rotate(360deg); }
-        }
-        
-        .profile-avatar {
-            width: 80px;
-            height: 80px;
-            border-radius: 50%;
-            background-color: white;
-            display: flex;
-            align-items: center;
-            justify-content: center;
-            color:#3A5FE5;
-            font-size: 32px;
-            margin-bottom: 10px;
-            position: relative;
-            z-index: 1;
-            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
-        }
-        
-        .profile-name {
-            color: white;
-            font-size: 18px;
-            font-weight: bold;
-            margin-bottom: 5px;
-            z-index: 1;
-        }
-        
-        .profile-email {
-            color: rgba(255, 255, 255, 0.8);
-            font-size: 14px;
-            z-index: 1;
-        }
-        
-        /* 功能卡片区域 */
-        .features-section {
-            margin-bottom: 20px;
-        }
-        
-        .section-title {
-            font-size: 18px;
-            font-weight: bold;
-            margin-bottom: 15px;
-            display: flex;
-            justify-content: space-between;
-            align-items: center;
-            color: var(--text);
-        }
-        
-        .section-title a {
-            font-size: 14px;
-            font-weight: normal;
-            color:#3A5FE5;
-            text-decoration: none;
-        }
-        
-        .features-grid {
-            display: grid;
-            grid-template-columns: repeat(2, 1fr);
-            gap: 15px;
-        }
-        
-        .feature-card {
-            background: white;
-            border-radius: 12px;
-            padding: 20px;
-            display: flex;
-            flex-direction: column;
-            align-items: center;
-            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
-            transition: transform 0.3s, box-shadow 0.3s;
-        }
-        
-        .feature-card:hover {
-            transform: translateY(-5px);
-            box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);
-        }
-        
-        .feature-icon {
-            font-size: 28px;
-            color: #3A5FE5;
-            margin-bottom: 10px;
-        }
-        
-        .feature-title {
-            font-size: 14px;
-            color: var(--text);
-            text-align: center;
-            margin-bottom: 8px;
-        }
-        
-        .feature-desc {
-            font-size: 12px;
-            color: var(--gray);
-            text-align: center;
-            line-height: 1.4;
-        }
-        
-        /* 律师入驻区域 */
-        .lawyer-section {
-            background: white;
-            border-radius: 12px;
-            padding: 20px;
-            margin-bottom: 20px;
-            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
-        }
-        
-        .lawyer-header {
-            display: flex;
-            justify-content: space-between;
-            align-items: center;
-            margin-bottom: 15px;
-        }
-        
-        .lawyer-title {
-            font-size: 16px;
-            font-weight: bold;
-            color: var(--text);
-        }
-        
-        .lawyer-status {
-            font-size: 12px;
-            color: #3A5FE5;
-            padding: 3px 8px;
-            border-radius: 12px;
-            background: rgba(58, 95, 229, 0.1);
-        }
-        
-        .lawyer-btn {
-            width: 100%;
-            background: #3A5FE5;
-            color: white;
-            border: none;
-            padding: 12px;
-            border-radius: 8px;
-            font-size: 16px;
-            font-weight: bold;
-            cursor: pointer;
-            transition: background 0.3s;
-        }
-        
-        .lawyer-btn:hover {
-            background: #2A4BCF;
-        }
-        
-        /* 设置区域 */
-        .settings-section {
-            margin-bottom: 20px;
-        }
-        
-        .settings-list {
-            list-style: none;
-        }
-        
-        .setting-item {
-            display: flex;
-            align-items: center;
-            padding: 15px;
-            background: white;
-            border-radius: 10px;
-            margin-bottom: 10px;
-            box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
-        }
-        
-        .setting-icon {
-            font-size: 20px;
-            color: #3A5FE5;
-            margin-right: 15px;
-        }
-        
-        .setting-content {
-            flex: 1;
-        }
-        
-        .setting-title {
-            font-size: 16px;
-            color: var(--text);
-            margin-bottom: 4px;
-        }
-        
-        .setting-desc {
-            font-size: 12px;
-            color: #94A3B8;
-        }
-        
-        .setting-arrow {
-            font-size: 16px;
-            color: #94A3B8;
-        }

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

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

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

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

+ 3 - 2
myapp/src/app/tabs/tabs-routing.module.ts

@@ -20,8 +20,9 @@ const routes: Routes = [
         loadChildren: () => import('../tab3/tab3.module').then(m => m.Tab3PageModule)
       },
       {
-        path: 'tab4',
-        loadChildren: () => import('../tab4/tab4.module').then(m => m.Tab4PageModule)
+        path: 'mine',
+        loadComponent: () =>
+          import('../../lib/user/page-mine/page-mine.component').then((m) => m.PageMineComponent),
       },
       {
         path: '',

+ 3 - 2
myapp/src/app/tabs/tabs.page.html

@@ -16,10 +16,11 @@
       <ion-label>文书</ion-label>
     </ion-tab-button>
 
-    <ion-tab-button tab="tab4" href="/tabs/tab4">
-      <ion-icon aria-hidden="true" name="people-outline"></ion-icon>
+    <ion-tab-button tab="mine" href="/tabs/mine">
+      <ion-icon aria-hidden="true" name="person-outline"></ion-icon>
       <ion-label>我的</ion-label>
     </ion-tab-button>
+    
   </ion-tab-bar>
 
 </ion-tabs>

BIN
myapp/src/assets/user.jpg


+ 66 - 0
myapp/src/lib/user/modal-user-edit/modal-user-edit.component.html

@@ -0,0 +1,66 @@
+<ion-header>
+  <ion-toolbar color="primary">
+    <ion-title>编辑资料</ion-title>
+    <ion-buttons slot="end">
+      <ion-button (click)="cancel()">
+        <ion-icon name="close-outline" slot="icon-only"></ion-icon>
+      </ion-button>
+    </ion-buttons>
+  </ion-toolbar>
+</ion-header>
+
+<ion-content class="ion-padding">
+  <ion-list>
+    <ion-item>
+      <ion-icon name="person-outline" slot="start"></ion-icon>
+      <ion-input [value]="userData['username']" (ionChange)="userDataChange('username',$event)" label="用户名"
+        label-placement="floating" placeholder="请输入用户名">
+      </ion-input>
+    </ion-item>
+
+    <ion-item>
+      <ion-icon name="id-card-outline" slot="start"></ion-icon>
+      <ion-input [value]="userData['realname']" (ionChange)="userDataChange('realname',$event)" label="真实姓名"
+        label-placement="floating" placeholder="请输入真实姓名">
+      </ion-input>
+    </ion-item>
+
+    <ion-item>
+      <ion-icon name="calendar-outline" slot="start"></ion-icon>
+      <ion-input type="number" [value]="userData['age']" (ionChange)="userDataChange('age',$event)" label="年龄"
+        label-placement="floating" placeholder="请输入年龄">
+      </ion-input>
+    </ion-item>
+
+    <ion-item>
+      <ion-icon name="transgender-outline" slot="start"></ion-icon>
+      <ion-label>性别</ion-label>
+      <ion-segment [value]="userData['gender']" (ionChange)="userDataChange('gender', $event)">
+        <ion-segment-button value="男">
+          <ion-label>男</ion-label>
+        </ion-segment-button>
+        <ion-segment-button value="女">
+          <ion-label>女</ion-label>
+        </ion-segment-button>
+      </ion-segment>
+    </ion-item>
+
+    <ion-item>
+      <ion-icon name="image-outline" slot="start"></ion-icon>
+      <ion-input [value]="userData['avatar']" (ionChange)="userDataChange('avatar',$event)" label="头像URL"
+        label-placement="floating" placeholder="请输入头像URL地址">
+      </ion-input>
+    </ion-item>
+  </ion-list>
+
+  <div class="action-buttons">
+    <ion-button expand="block" (click)="save()" color="primary" shape="round">
+      <ion-icon name="save-outline" slot="start"></ion-icon>
+      保存
+    </ion-button>
+    <ion-button expand="block" (click)="cancel()" color="medium" fill="outline" shape="round">
+      <ion-icon name="close-outline" slot="start"></ion-icon>
+      取消
+    </ion-button>
+  </div>
+</ion-content>

+ 27 - 0
myapp/src/lib/user/modal-user-edit/modal-user-edit.component.scss

@@ -0,0 +1,27 @@
+/* modal-user-edit.component.scss */
+ion-content {
+    --padding-bottom: 80px;
+}
+
+.action-buttons {
+    margin-top: 32px;
+
+    ion-button {
+        margin-bottom: 16px;
+    }
+}
+
+ion-segment {
+    width: 100%;
+    max-width: 200px;
+    margin-left: auto;
+}
+
+ion-item {
+    --padding-start: 0;
+
+    ion-icon {
+        margin-right: 16px;
+        color: var(--ion-color-medium);
+    }
+}

+ 22 - 0
myapp/src/lib/user/modal-user-edit/modal-user-edit.component.spec.ts

@@ -0,0 +1,22 @@
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+
+import { ModalUserEditComponent } from './modal-user-edit.component';
+
+describe('ModalUserEditComponent', () => {
+  let component: ModalUserEditComponent;
+  let fixture: ComponentFixture<ModalUserEditComponent>;
+
+  beforeEach(waitForAsync(() => {
+    TestBed.configureTestingModule({
+      imports: [ModalUserEditComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(ModalUserEditComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  }));
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 65 - 0
myapp/src/lib/user/modal-user-edit/modal-user-edit.component.ts

@@ -0,0 +1,65 @@
+import { Component, OnInit } from '@angular/core';
+import {
+  IonHeader, IonToolbar, IonTitle, IonContent,
+  IonButton, IonInput, IonItem, IonList, IonIcon,
+  IonSegment, IonSegmentButton, IonLabel, IonButtons
+} from '@ionic/angular/standalone';
+import { ModalController } from '@ionic/angular/standalone';
+import { CloudUser } from 'src/lib/ncloud';
+import { addIcons } from 'ionicons';
+import {
+  closeOutline, saveOutline, personOutline,
+  idCardOutline, calendarOutline, transgenderOutline,
+  imageOutline
+} from 'ionicons/icons';
+
+@Component({
+  selector: 'app-modal-user-edit',
+  templateUrl: './modal-user-edit.component.html',
+  styleUrls: ['./modal-user-edit.component.scss'],
+  standalone: true,
+  imports: [
+    IonHeader, IonToolbar, IonTitle, IonContent,
+    IonButton, IonInput, IonItem, IonList, IonIcon,
+    IonSegment, IonSegmentButton, IonLabel, IonButtons
+  ],
+})
+export class ModalUserEditComponent implements OnInit {
+  currentUser: CloudUser | undefined;
+  userData: any = {};
+
+  constructor(private modalCtrl: ModalController) {
+    this.currentUser = new CloudUser();
+    this.userData = { ...this.currentUser.data };
+    addIcons({
+      closeOutline, saveOutline, personOutline,
+      idCardOutline, calendarOutline, transgenderOutline,
+      imageOutline
+    });
+  }
+
+  userDataChange(key: string, ev: any) {
+    let value = ev?.detail?.value;
+    if (value) {
+      this.userData[key] = value;
+    }
+  }
+
+  ngOnInit() { }
+
+  async save() {
+    Object.keys(this.userData).forEach(key => {
+      if (key == "age") {
+        this.userData[key] = Number(this.userData[key]);
+      }
+    });
+
+    this.currentUser?.set(this.userData);
+    await this.currentUser?.save();
+    this.modalCtrl.dismiss(this.currentUser, "confirm");
+  }
+
+  cancel() {
+    this.modalCtrl.dismiss(null, "cancel");
+  }
+}

+ 36 - 0
myapp/src/lib/user/modal-user-login/modal-user-login.component.html

@@ -0,0 +1,36 @@
+<!-- 用户登录状态 -->
+<ion-card>
+  <ion-card-header>
+    <ion-card-title>
+      <ion-segment [value]="type" (ionChange)="typeChange($event)">
+        <ion-segment-button value="login">
+          <ion-label>登录</ion-label>
+        </ion-segment-button>
+        <ion-segment-button value="signup">
+          <ion-label>注册</ion-label>
+        </ion-segment-button>
+      </ion-segment>
+    </ion-card-title>
+    <ion-card-subtitle>请输入账号密码</ion-card-subtitle>
+  </ion-card-header>
+  <ion-card-content>
+    <ion-item>
+      <ion-input [value]="username" (ionChange)="usernameChange($event)" label="账号" placeholder="请您输入账号/手机号"></ion-input>
+    </ion-item>
+    <ion-item>
+      <ion-input [value]="password" (ionChange)="passwordChange($event)" label="密码" type="password" value="password"></ion-input>
+    </ion-item>
+
+    @if(type=="signup"){
+      <ion-item>
+        <ion-input [value]="password2" (ionChange)="password2Change($event)" label="密码二次" type="password" value="password"></ion-input>
+      </ion-item>
+    }
+    @if(type=="login"){
+      <ion-button expand="block" (click)="login()">登录</ion-button>
+    }
+    @if(type=="signup"){
+      <ion-button expand="block" (click)="signup()">注册</ion-button>
+    }
+  </ion-card-content>
+</ion-card>

+ 0 - 0
myapp/src/lib/user/modal-user-login/modal-user-login.component.scss


+ 22 - 0
myapp/src/lib/user/modal-user-login/modal-user-login.component.spec.ts

@@ -0,0 +1,22 @@
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+
+import { ModalUserLoginComponent } from './modal-user-login.component';
+
+describe('ModalUserLoginComponent', () => {
+  let component: ModalUserLoginComponent;
+  let fixture: ComponentFixture<ModalUserLoginComponent>;
+
+  beforeEach(waitForAsync(() => {
+    TestBed.configureTestingModule({
+      imports: [ModalUserLoginComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(ModalUserLoginComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  }));
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 92 - 0
myapp/src/lib/user/modal-user-login/modal-user-login.component.ts

@@ -0,0 +1,92 @@
+import { Input, OnInit } from '@angular/core';
+import { Component } from '@angular/core';
+import { IonHeader, IonToolbar, IonTitle, IonContent, IonCard, IonCardContent, IonButton, IonCardHeader, IonCardTitle, IonCardSubtitle, ModalController, IonInput, IonItem, IonSegment, IonSegmentButton, IonLabel } from '@ionic/angular/standalone';
+import { CloudUser } from 'src/lib/ncloud';
+
+@Component({
+  selector: 'app-modal-user-login',
+  templateUrl: './modal-user-login.component.html',
+  styleUrls: ['./modal-user-login.component.scss'],
+  standalone: true,
+  imports: [IonHeader, IonToolbar, IonTitle, IonContent, 
+    IonCard,IonCardContent,IonButton,IonCardHeader,IonCardTitle,IonCardSubtitle,
+    IonInput,IonItem,
+    IonSegment,IonSegmentButton,IonLabel
+  ],
+})
+export class ModalUserLoginComponent  implements OnInit {
+  @Input()
+  type:"login"|"signup" = "login"
+  typeChange(ev:any){
+    this.type = ev?.detail?.value || ev?.value || 'login'
+  }
+  username:string = ""
+  usernameChange(ev:any){
+    console.log(ev)
+    this.username = ev?.detail?.value
+  }
+  password:string = ""
+  passwordChange(ev:any){
+    this.password = ev?.detail?.value
+  }
+  password2:string = ""
+  password2Change(ev:any){
+    this.password2 = ev?.detail?.value
+  }
+  constructor(private modalCtrl:ModalController) { }
+
+  ngOnInit() {}
+
+  async login(){
+    if(!this.username || !this.password){
+      console.log("请输入完整")
+      return
+    }
+    let user:any = new CloudUser();
+    user = await user.login(this.username,this.password);
+    if(user?.id){
+       this.modalCtrl.dismiss(user,"confirm")
+    }else{
+      console.log("登录失败")
+    }
+  }
+
+  async signup(){
+    if(!this.username || !this.password || !this.password2){
+      console.log("请输入完整")
+      return
+    }
+    if(this.password!=this.password2){
+      console.log("两次密码不符,请修改")
+      return
+    }
+
+    let user:any = new CloudUser();
+    user = await user.signUp(this.username,this.password);
+    if(user){
+      this.type = "login"
+      console.log("注册成功请登录")
+    }
+  }
+
+}
+
+
+export async function openUserLoginModal(modalCtrl:ModalController,type:"login"|"signup"="login"):Promise<CloudUser|null>{
+  const modal = await modalCtrl.create({
+    component: ModalUserLoginComponent,
+    componentProps:{
+      type:type
+    },
+    breakpoints:[0.5,0.7],
+    initialBreakpoint:0.5
+  });
+  modal.present();
+
+  const { data, role } = await modal.onWillDismiss();
+
+  if (role === 'confirm') {
+    return data;
+  }
+  return null
+}

+ 135 - 0
myapp/src/lib/user/page-mine/page-mine.component.html

@@ -0,0 +1,135 @@
+<ion-content [fullscreen]="true" class="ion-padding profile-content">
+  <div class="container">
+    <!-- 顶部个人资料区域 -->
+    <div class="profile-section">
+      <div class="profile-bg"></div>
+      <ion-avatar class="profile-avatar">
+        <img [src]="currentUser?.get('avatar') || 'assets/icon/avatar-default.png'" />
+      </ion-avatar>
+      
+      <ion-text class="profile-name">
+        @if(currentUser?.id) {
+          {{currentUser?.get("username")}}
+        } @else {
+          欢迎使用明律通
+        }
+      </ion-text>
+      
+      <ion-text class="profile-email">
+        @if(currentUser?.id) {
+          {{currentUser?.get('email') || currentUser?.get('username') + '@example.com'}}
+        } @else {
+          AI法律顾问平台
+        }
+      </ion-text>
+      
+      <!-- 登录状态显示 -->
+      @if(currentUser?.id) {
+      <div class="user-actions">
+        <ion-button fill="outline" class="btn-outline" (click)="edit()">
+          编辑资料
+        </ion-button>
+      </div>
+      }
+      
+      <!-- 未登录状态显示 -->
+      @if(!currentUser?.id) {
+      <ion-button class="btn-primary" (click)="login()">
+        登入用户 abc 1234
+      </ion-button>
+      }
+    </div>
+    
+    <!-- 功能入口网格 (登录后显示) -->
+    @if(currentUser?.id) {
+    <div class="features-section">
+      <div class="section-title">
+        <ion-text>常用功能</ion-text>
+        <ion-button fill="clear" size="small">管理</ion-button>
+      </div>
+      <div class="features-grid">
+        <ion-card class="feature-card">
+          <ion-icon name="document-text-outline" class="feature-icon"></ion-icon>
+          <ion-text class="feature-title">我的文书</ion-text>
+          <ion-text class="feature-desc">查看和管理您的法律文书</ion-text>
+        </ion-card>
+        
+        <ion-card class="feature-card">
+          <ion-icon name="star-outline" class="feature-icon"></ion-icon>
+          <ion-text class="feature-title">收藏夹</ion-text>
+          <ion-text class="feature-desc">您收藏的法律知识和案例</ion-text>
+        </ion-card>
+      </div>
+    </div>
+    }
+    
+    <!-- 律师入驻区域 (登录后显示) -->
+    @if(currentUser?.id) {
+    <ion-card class="lawyer-section">
+      <div class="lawyer-header">
+        <ion-text class="lawyer-title">律师入驻</ion-text>
+        <ion-badge class="lawyer-status" color="primary">未入驻</ion-badge>      
+      </div> 
+      <ion-button class="lawyer-btn" id="apply-lawyer">
+         立即申请入驻
+      </ion-button>    
+    </ion-card>
+    }
+    
+    <!-- 设置区域 (登录后显示) -->
+    @if(currentUser?.id) {
+    <div class="settings-section">
+      <ion-list class="settings-list">
+        <ion-item class="setting-item" button detail>
+          <ion-icon name="shield-checkmark-outline" slot="start" class="setting-icon"></ion-icon>
+          <ion-label class="setting-content">
+            <h3 class="setting-title">账户安全</h3>
+            <p class="setting-desc">修改密码、设置密保</p>
+          </ion-label>
+          <ion-icon name="chevron-forward-outline" slot="end" class="setting-arrow"></ion-icon>
+        </ion-item>
+        
+        <ion-item class="setting-item" button detail>
+          <ion-icon name="notifications-outline" slot="start" class="setting-icon"></ion-icon>
+          <ion-label class="setting-content">
+            <h3 class="setting-title">消息通知</h3>
+            <p class="setting-desc">设置接收通知类型</p>
+          </ion-label>
+          <ion-icon name="chevron-forward-outline" slot="end" class="setting-arrow"></ion-icon>
+        </ion-item>
+        
+        <ion-item class="setting-item" button detail>
+          <ion-icon name="settings-outline" slot="start" class="setting-icon"></ion-icon>
+          <ion-label class="setting-content">
+            <h3 class="setting-title">通用设置</h3>
+            <p class="setting-desc">消息提醒、隐私设置</p>
+          </ion-label>
+          <ion-icon name="chevron-forward-outline" slot="end" class="setting-arrow"></ion-icon>
+        </ion-item>
+        
+        <ion-item class="setting-item" button detail>
+          <ion-icon name="help-circle-outline" slot="start" class="setting-icon"></ion-icon>
+          <ion-label class="setting-content">
+            <h3 class="setting-title">帮助中心</h3>
+            <p class="setting-desc">常见问题与解答</p>
+          </ion-label>
+          <ion-icon name="chevron-forward-outline" slot="end" class="setting-arrow"></ion-icon>
+        </ion-item>
+        
+        <ion-item class="setting-item" button detail (click)="logout()">
+          <ion-icon name="log-out-outline" slot="start" class="setting-icon"></ion-icon>
+          <ion-label class="setting-content">
+            <h3 class="setting-title">退出登录</h3>
+            <p class="setting-desc">安全退出当前账号</p>
+          </ion-label>
+          <ion-icon name="chevron-forward-outline" slot="end" class="setting-arrow"></ion-icon>
+        </ion-item>
+      </ion-list>
+    </div>
+    }
+    
+    <div class="footer">
+      <ion-text>© 2023 明律通 - AI法律顾问平台</ion-text>
+    </div>
+  </div>
+</ion-content>

+ 284 - 0
myapp/src/lib/user/page-mine/page-mine.component.scss

@@ -0,0 +1,284 @@
+/* 在对应的SCSS文件中添加以下样式 */
+.profile-content {
+  --background: linear-gradient(135deg, #F8F9FF, #E6F7FF);
+  
+  .container {
+    width: 100%;
+    max-width: 480px;
+    margin: 0 auto;
+    background-color: white;
+    border-radius: 20px;
+    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
+    overflow: hidden;
+  }
+  
+  /* 顶部区域 */
+  .profile-section {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    padding: 40px 20px 30px;
+    background: linear-gradient(135deg, #6A8EFF, #3A5FE5);
+    position: relative;
+    overflow: hidden;
+  }
+  
+  .profile-bg {
+    position: absolute;
+    top: -50%;
+    left: -50%;
+    width: 200%;
+    height: 200%;
+    background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><circle cx="50" cy="50" r="40" fill="none" stroke="rgba(255,255,255,0.2)" stroke-width="2"/></svg>');
+    background-size: 100px 100px;
+    animation: rotate 60s linear infinite;
+    z-index: 0;
+  }
+  
+  @keyframes rotate {
+    from { transform: rotate(0deg); }
+    to { transform: rotate(360deg); }
+  }
+  
+  .profile-avatar {
+    width: 100px;
+    height: 100px;
+    border-radius: 50%;
+    background-color: white;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    color: #3A5FE5;
+    font-size: 40px;
+    margin-bottom: 15px;
+    position: relative;
+    z-index: 1;
+    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+    
+    img {
+      width: 100%;
+      height: 100%;
+      object-fit: cover;
+    }
+  }
+  
+  .profile-name {
+    color: white;
+    font-size: 22px;
+    font-weight: bold;
+    margin-bottom: 5px;
+    z-index: 1;
+  }
+  
+  .profile-email {
+    color: rgba(255, 255, 255, 0.8);
+    font-size: 14px;
+    z-index: 1;
+    margin-bottom: 15px;
+  }
+  
+  /* 按钮样式 */
+  .btn-primary {
+    --background: white;
+    --color: #3A5FE5;
+    --border-radius: 8px;
+    --padding-start: 24px;
+    --padding-end: 24px;
+    height: 48px;
+    font-weight: bold;
+    z-index: 1;
+    position: relative;
+    
+    &:hover {
+      --background: #f0f0f0;
+    }
+  }
+  
+  .btn-outline {
+    --background: transparent;
+    --color: white;
+    --border-color: white;
+    --border-width: 2px;
+    --border-radius: 8px;
+    --padding-start: 24px;
+    --padding-end: 24px;
+    height: 48px;
+    font-weight: bold;
+    z-index: 1;
+    position: relative;
+    margin: 5px;
+    
+    &:hover {
+      --background: rgba(255, 255, 255, 0.1);
+    }
+  }
+  
+  .user-actions {
+    display: flex;
+    justify-content: center;
+    margin-top: 20px;
+  }
+  
+  /* 功能入口网格 */
+  .features-section {
+    padding: 20px;
+    margin-bottom: 20px;
+  }
+  
+  .section-title {
+    font-size: 18px;
+    font-weight: bold;
+    margin-bottom: 15px;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    color: #2D3748;
+    
+    ion-button {
+      --color: #3A5FE5;
+      font-size: 14px;
+      font-weight: normal;
+    }
+  }
+  
+  .features-grid {
+    display: grid;
+    grid-template-columns: repeat(2, 1fr);
+    gap: 15px;
+  }
+  
+  .feature-card {
+    background: white;
+    border-radius: 12px;
+    padding: 20px;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
+    transition: transform 0.3s, box-shadow 0.3s;
+    border: 1px solid #E2E8F0;
+    margin: 0;
+    
+    &:hover {
+      transform: translateY(-5px);
+      box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);
+    }
+  }
+  
+  .feature-icon {
+    font-size: 28px;
+    color: #3A5FE5;
+    margin-bottom: 10px;
+  }
+  
+  .feature-title {
+    font-size: 14px;
+    color: #2D3748;
+    text-align: center;
+    margin-bottom: 8px;
+  }
+  
+  .feature-desc {
+    font-size: 12px;
+    color: #94A3B8;
+    text-align: center;
+    line-height: 1.4;
+  }
+  
+  /* 律师入驻区域 */
+  .lawyer-section {
+    background: white;
+    border-radius: 12px;
+    padding: 20px;
+    margin: 0 20px 20px;
+    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
+    border: 1px solid #E2E8F0;
+  }
+  
+  .lawyer-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 15px;
+  }
+  
+  .lawyer-title {
+    font-size: 16px;
+    font-weight: bold;
+    color: #2D3748;
+  }
+  
+  .lawyer-status {
+    font-size: 12px;
+    padding: 3px 8px;
+    border-radius: 12px;
+  }
+  
+  .lawyer-btn {
+            width: 100%;
+            color: white;
+            border: none;           
+            border-radius: 8px;
+            font-size: 16px;
+            font-weight: bold;
+            cursor: pointer;
+        }
+        
+        .lawyer-btn:hover {
+            background: #2A4BCF;
+        }
+
+  
+  
+  /* 设置区域 */
+  .settings-section {
+    padding: 0 20px 20px;
+    margin-bottom: 20px;
+  }
+  
+  .settings-list {
+    list-style: none;
+    padding: 0;
+  }
+  
+  .setting-item {
+    --padding-start: 15px;
+    --padding-end: 15px;
+    --inner-padding-end: 0;
+    --border-radius: 10px;
+    --background: white;
+    margin-bottom: 10px;
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
+    border: 1px solid #E2E8F0;
+  }
+  
+  .setting-icon {
+    font-size: 20px;
+    color: #3A5FE5;
+    margin-right: 15px;
+  }
+  
+  .setting-title {
+    font-size: 16px;
+    color: #2D3748;
+    margin-bottom: 4px;
+  }
+  
+  .setting-desc {
+    font-size: 12px;
+    color: #94A3B8;
+  }
+  
+  .setting-arrow {
+    font-size: 16px;
+    color: #94A3B8;
+  }
+  
+  /* 底部信息 */
+  .footer {
+    text-align: center;
+    padding: 20px;
+    color: #94A3B8;
+    font-size: 12px;
+  }
+}

+ 22 - 0
myapp/src/lib/user/page-mine/page-mine.component.spec.ts

@@ -0,0 +1,22 @@
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+
+import { PageMineComponent } from './page-mine.component';
+
+describe('PageMineComponent', () => {
+  let component: PageMineComponent;
+  let fixture: ComponentFixture<PageMineComponent>;
+
+  beforeEach(waitForAsync(() => {
+    TestBed.configureTestingModule({
+      imports: [PageMineComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(PageMineComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  }));
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 66 - 0
myapp/src/lib/user/page-mine/page-mine.component.ts

@@ -0,0 +1,66 @@
+import { Component, OnInit } from '@angular/core';
+import { IonAvatar, 
+  IonText, 
+  IonButton, 
+  IonIcon, 
+  IonCard, 
+  IonList, 
+  IonItem, 
+  IonLabel, 
+  IonBadge ,IonContent, AlertController,ModalController } from '@ionic/angular/standalone';
+import { CloudUser } from 'src/lib/ncloud';
+import { ModalUserEditComponent } from '../modal-user-edit/modal-user-edit.component';
+import { FormsModule } from '@angular/forms';
+
+@Component({
+  selector: 'app-page-mine',
+  templateUrl: './page-mine.component.html',
+  styleUrls: ['./page-mine.component.scss'],
+  standalone: true,
+  imports: [
+    IonContent, 
+  IonAvatar, 
+  IonText, 
+  IonButton, 
+  IonIcon, 
+  IonCard, 
+  IonList, 
+  IonItem, 
+  IonLabel, 
+  IonBadge,
+  ]
+  
+})
+export class PageMineComponent  implements OnInit {
+  currentUser: CloudUser | undefined;
+
+  constructor(private modalCtrl: ModalController) {
+    this.currentUser = new CloudUser();
+  }
+
+  async edit() {
+    const modal = await this.modalCtrl.create({
+      component: ModalUserEditComponent,
+    });
+    modal.present();
+
+    const { data, role } = await modal.onWillDismiss();
+  }
+
+
+  async login() {
+    let user: any = new CloudUser();
+    user = await user?.login("Stan", "1234");
+    if (user?.id) {
+      this.currentUser = user;
+    }
+  }
+
+  logout() {
+    this.currentUser?.logout();
+    this.currentUser = undefined;
+  }
+
+  ngOnInit() {}
+
+}