Browse Source

Merge branch 'master' of http://git.fmode.cn:3000/yuebuzu/s202226701018

未来全栈 3 months ago
parent
commit
c9bbdcd5d7
100 changed files with 4536 additions and 895 deletions
  1. BIN
      MY-WEB/.DS_Store
  2. 7 1
      README.md
  3. 71 4
      wisdom-app/angular.json
  4. 18 0
      wisdom-app/deploy.ps1
  5. 28 0
      wisdom-app/package-lock.json
  6. 3 1
      wisdom-app/package.json
  7. 1 0
      wisdom-app/src/agent/agent-user-input/agent-user-input.component.ts
  8. 29 0
      wisdom-app/src/app/all-products-modal/all-products-modal.component.html
  9. 66 0
      wisdom-app/src/app/all-products-modal/all-products-modal.component.scss
  10. 6 6
      wisdom-app/src/app/all-products-modal/all-products-modal.component.spec.ts
  11. 38 0
      wisdom-app/src/app/all-products-modal/all-products-modal.component.ts
  12. 5 0
      wisdom-app/src/app/app.routes.ts
  13. 1 1
      wisdom-app/src/app/component/article-card/article-card.component.html
  14. 1 1
      wisdom-app/src/app/component/edit-tag/edit-tag.component.html
  15. 26 0
      wisdom-app/src/app/detail-modal/detail-modal.component.html
  16. 30 0
      wisdom-app/src/app/detail-modal/detail-modal.component.scss
  17. 6 6
      wisdom-app/src/app/detail-modal/detail-modal.component.spec.ts
  18. 25 0
      wisdom-app/src/app/detail-modal/detail-modal.component.ts
  19. 31 0
      wisdom-app/src/app/drug-category/drug-category.page.html
  20. 67 0
      wisdom-app/src/app/drug-category/drug-category.page.scss
  21. 17 0
      wisdom-app/src/app/drug-category/drug-category.page.spec.ts
  22. 58 0
      wisdom-app/src/app/drug-category/drug-category.page.ts
  23. 17 0
      wisdom-app/src/app/page/data-modal/data-modal.component.html
  24. 0 0
      wisdom-app/src/app/page/data-modal/data-modal.component.scss
  25. 22 0
      wisdom-app/src/app/page/data-modal/data-modal.component.spec.ts
  26. 49 0
      wisdom-app/src/app/page/data-modal/data-modal.component.ts
  27. 177 21
      wisdom-app/src/app/page/inquiry-human/inquiry-human.component.html
  28. 287 0
      wisdom-app/src/app/page/inquiry-human/inquiry-human.component.scss
  29. 199 3
      wisdom-app/src/app/page/inquiry-human/inquiry-human.component.ts
  30. 45 0
      wisdom-app/src/app/page/page-ai-knowledge/page-ai-knowledge.component.html
  31. 0 0
      wisdom-app/src/app/page/page-ai-knowledge/page-ai-knowledge.component.scss
  32. 22 0
      wisdom-app/src/app/page/page-ai-knowledge/page-ai-knowledge.component.spec.ts
  33. 111 0
      wisdom-app/src/app/page/page-ai-knowledge/page-ai-knowledge.component.ts
  34. 0 7
      wisdom-app/src/app/page/page-authority-experts/page-authority-experts.component.html
  35. 0 22
      wisdom-app/src/app/page/page-authority-experts/page-authority-experts.component.spec.ts
  36. 0 26
      wisdom-app/src/app/page/page-authority-experts/page-authority-experts.component.ts
  37. 85 0
      wisdom-app/src/app/page/page-create-agent/page-create-agent.component.html
  38. 0 0
      wisdom-app/src/app/page/page-create-agent/page-create-agent.component.scss
  39. 22 0
      wisdom-app/src/app/page/page-create-agent/page-create-agent.component.spec.ts
  40. 313 0
      wisdom-app/src/app/page/page-create-agent/page-create-agent.component.ts
  41. 0 7
      wisdom-app/src/app/page/page-drug-purchase/page-drug-purchase.component.html
  42. 0 26
      wisdom-app/src/app/page/page-drug-purchase/page-drug-purchase.component.ts
  43. 0 7
      wisdom-app/src/app/page/page-health-information/page-health-information.component.html
  44. 0 22
      wisdom-app/src/app/page/page-health-information/page-health-information.component.spec.ts
  45. 0 26
      wisdom-app/src/app/page/page-health-information/page-health-information.component.ts
  46. 0 7
      wisdom-app/src/app/page/page-health-records/page-health-records.component.html
  47. 0 0
      wisdom-app/src/app/page/page-health-records/page-health-records.component.scss
  48. 0 22
      wisdom-app/src/app/page/page-health-records/page-health-records.component.spec.ts
  49. 0 26
      wisdom-app/src/app/page/page-health-records/page-health-records.component.ts
  50. 56 4
      wisdom-app/src/app/page/page-inquiry/page-inquiry.component.html
  51. 52 0
      wisdom-app/src/app/page/page-inquiry/page-inquiry.component.scss
  52. 77 10
      wisdom-app/src/app/page/page-inquiry/page-inquiry.component.ts
  53. 58 6
      wisdom-app/src/app/page/page-my-health/page-my-health.component.html
  54. 97 0
      wisdom-app/src/app/page/page-my-health/page-my-health.component.scss
  55. 140 13
      wisdom-app/src/app/page/page-my-health/page-my-health.component.ts
  56. 0 7
      wisdom-app/src/app/page/page-phone-inquiry/page-phone-inquiry.component.html
  57. 0 0
      wisdom-app/src/app/page/page-phone-inquiry/page-phone-inquiry.component.scss
  58. 0 26
      wisdom-app/src/app/page/page-phone-inquiry/page-phone-inquiry.component.ts
  59. 0 11
      wisdom-app/src/app/page/page-smart-community/page-smart-community.component.html
  60. 0 0
      wisdom-app/src/app/page/page-smart-community/page-smart-community.component.scss
  61. 0 22
      wisdom-app/src/app/page/page-smart-community/page-smart-community.component.spec.ts
  62. 0 29
      wisdom-app/src/app/page/page-smart-community/page-smart-community.component.ts
  63. 20 16
      wisdom-app/src/app/poem-picture/poem-picture.component.html
  64. 93 0
      wisdom-app/src/app/poem-picture/poem-picture.component.scss
  65. 14 7
      wisdom-app/src/app/poem-picture/poem-picture.component.ts
  66. 216 0
      wisdom-app/src/app/tab1/schema.md
  67. 138 81
      wisdom-app/src/app/tab1/tab1.page.html
  68. 291 41
      wisdom-app/src/app/tab1/tab1.page.scss
  69. 166 60
      wisdom-app/src/app/tab1/tab1.page.ts
  70. 197 43
      wisdom-app/src/app/tab2/tab2.page.html
  71. 121 28
      wisdom-app/src/app/tab2/tab2.page.scss
  72. 140 44
      wisdom-app/src/app/tab2/tab2.page.ts
  73. 137 36
      wisdom-app/src/app/tab3/tab3.page.html
  74. 179 50
      wisdom-app/src/app/tab3/tab3.page.scss
  75. 132 36
      wisdom-app/src/app/tab3/tab3.page.ts
  76. 136 43
      wisdom-app/src/app/tab4/tab4.page.html
  77. 99 1
      wisdom-app/src/app/tab4/tab4.page.scss
  78. 37 4
      wisdom-app/src/app/tab4/tab4.page.ts
  79. 4 4
      wisdom-app/src/app/tabs/tabs.page.html
  80. 25 4
      wisdom-app/src/app/tabs/tabs.page.ts
  81. 28 27
      wisdom-app/src/app/tabs/tabs.routes.ts
  82. BIN
      wisdom-app/src/assets/image/background.png
  83. BIN
      wisdom-app/src/assets/image/doctor10.png
  84. BIN
      wisdom-app/src/assets/image/doctor11.png
  85. BIN
      wisdom-app/src/assets/image/doctor12.png
  86. BIN
      wisdom-app/src/assets/image/doctor8.png
  87. BIN
      wisdom-app/src/assets/image/doctor9.png
  88. BIN
      wisdom-app/src/assets/image/logo.png
  89. BIN
      wisdom-app/src/assets/image/yao1.png
  90. BIN
      wisdom-app/src/assets/image/yao10.png
  91. BIN
      wisdom-app/src/assets/image/yao11.png
  92. BIN
      wisdom-app/src/assets/image/yao12.png
  93. BIN
      wisdom-app/src/assets/image/yao2.png
  94. BIN
      wisdom-app/src/assets/image/yao3.png
  95. BIN
      wisdom-app/src/assets/image/yao4.png
  96. BIN
      wisdom-app/src/assets/image/yao5.png
  97. BIN
      wisdom-app/src/assets/image/yao6.png
  98. BIN
      wisdom-app/src/assets/image/yao7.png
  99. BIN
      wisdom-app/src/assets/image/yao8.jpg
  100. BIN
      wisdom-app/src/assets/image/yao9.png

BIN
MY-WEB/.DS_Store


+ 7 - 1
README.md

@@ -1,4 +1,10 @@
 # 智养人生仓库
 
 - wisdom-app 前端代码
-- wisdom-prod 产品文档
+- wisdom-prod 产品文档
+
+上传:obsutil cp logo.png obs://nova-cloud/dev/jxnu/202226701019/logo.png -f -i=XSUWJSVMZNHLWFAINRZ1 -k=P4TyfwfDovVNqz08tI1IXoLWXyEOSTKJRVlsGcV6 -e="obs.cn-south-1.myhuaweicloud.com"
+
+访问: https://app.fmode.cn/dev/jxnu/202226701019/logo.png
+
+打包地址:https://app.fmode.cn/dev/jxnu/202226701018/

+ 71 - 4
wisdom-app/angular.json

@@ -31,7 +31,43 @@
                 "output": "assets"
               }
             ],
-            "styles": ["src/global.scss", "src/theme/variables.scss"],
+            "styles": [
+              "src/global.scss",
+              "src/theme/variables.scss",
+              {
+                "input": "node_modules/@ionic/angular/css/core.css"
+              },
+              {
+                "input": "node_modules/@ionic/angular/css/normalize.css"
+              },
+              {
+                "input": "node_modules/@ionic/angular/css/structure.css"
+              },
+              {
+                "input": "node_modules/@ionic/angular/css/typography.css"
+              },
+              {
+                "input": "node_modules/@ionic/angular/css/display.css"
+              },
+              {
+                "input": "node_modules/@ionic/angular/css/padding.css"
+              },
+              {
+                "input": "node_modules/@ionic/angular/css/float-elements.css"
+              },
+              {
+                "input": "node_modules/@ionic/angular/css/text-alignment.css"
+              },
+              {
+                "input": "node_modules/@ionic/angular/css/text-transformation.css"
+              },
+              {
+                "input": "node_modules/@ionic/angular/css/flex-utils.css"
+              },
+              {
+                "input": "src/theme/variables.css"
+              }
+            ],
             "scripts": []
           },
           "configurations": {
@@ -106,7 +142,10 @@
                 "output": "assets"
               }
             ],
-            "styles": ["src/global.scss", "src/theme/variables.scss"],
+            "styles": [
+              "src/global.scss",
+              "src/theme/variables.scss"
+            ],
             "scripts": []
           },
           "configurations": {
@@ -119,7 +158,34 @@
         "lint": {
           "builder": "@angular-eslint/builder:lint",
           "options": {
-            "lintFilePatterns": ["src/**/*.ts", "src/**/*.html"]
+            "lintFilePatterns": [
+              "src/**/*.ts",
+              "src/**/*.html"
+            ]
+          }
+        },
+        "ionic-cordova-serve": {
+          "builder": "@ionic/angular-toolkit:cordova-serve",
+          "options": {
+            "cordovaBuildTarget": "app:ionic-cordova-build",
+            "devServerTarget": "app:serve"
+          },
+          "configurations": {
+            "production": {
+              "cordovaBuildTarget": "app:ionic-cordova-build:production",
+              "devServerTarget": "app:serve:production"
+            }
+          }
+        },
+        "ionic-cordova-build": {
+          "builder": "@ionic/angular-toolkit:cordova-build",
+          "options": {
+            "browserTarget": "app:build"
+          },
+          "configurations": {
+            "production": {
+              "browserTarget": "app:build:production"
+            }
           }
         }
       }
@@ -127,6 +193,7 @@
   },
   "cli": {
     "schematicCollections": [
+      "@ionic/angular-toolkit",
       "@ionic/angular-toolkit"
     ],
     "analytics": false
@@ -145,4 +212,4 @@
       "setParserOptionsProject": true
     }
   }
-}
+}

+ 18 - 0
wisdom-app/deploy.ps1

@@ -0,0 +1,18 @@
+# 打包项目,携带应用前缀(index.html中相对路径将自动修复为/dev/jxnu/<学号>前缀)
+# /dev/ 项目测试版上传路径
+# /dev/jxnu/<学号> nova-crm项目预留路径
+set NODE_OPTIONS=–max_old_space_size=16000 
+node ./node_modules/@angular/cli/bin/ng build --base-href="/dev/jxnu/202226701018/"
+
+# 清空旧文件目录
+obsutil rm obs://nova-cloud/dev/jxnu/202226701018 -r -f -i=XSUWJSVMZNHLWFAINRZ1 -k=P4TyfwfDovVNqz08tI1IXoLWXyEOSTKJRVlsGcV6 -e="obs.cn-south-1.myhuaweicloud.com"
+
+# 同步文件目录
+obsutil sync ./www obs://nova-cloud/dev/jxnu/202226701018  -i=XSUWJSVMZNHLWFAINRZ1 -k=P4TyfwfDovVNqz08tI1IXoLWXyEOSTKJRVlsGcV6 -e="obs.cn-south-1.myhuaweicloud.com" -acl=public-read
+
+
+# 授权公开可读
+obsutil chattri obs://nova-cloud/dev/jxnu/202226701018 -r -f -i=XSUWJSVMZNHLWFAINRZ1 -k=P4TyfwfDovVNqz08tI1IXoLWXyEOSTKJRVlsGcV6 -e="obs.cn-south-1.myhuaweicloud.com" -acl=public-read
+
+# 列举对象
+obsutil ls obs://nova-cloud/dev/jxnu/202226701018  -i=XSUWJSVMZNHLWFAINRZ1 -k=P4TyfwfDovVNqz08tI1IXoLWXyEOSTKJRVlsGcV6 -e="obs.cn-south-1.myhuaweicloud.com"

+ 28 - 0
wisdom-app/package-lock.json

@@ -24,6 +24,7 @@
         "@ionic/angular": "^8.0.0",
         "fmode-ng": "^0.0.63",
         "ionicons": "^7.2.1",
+        "ngx-amap": "^3.0.5",
         "rxjs": "~7.8.0",
         "tslib": "^2.3.0",
         "zone.js": "~0.14.2"
@@ -40,6 +41,7 @@
         "@angular/language-service": "^18.0.0",
         "@capacitor/cli": "6.2.0",
         "@ionic/angular-toolkit": "^11.0.1",
+        "@types/amap-js-api": "^1.4.16",
         "@types/jasmine": "~5.1.0",
         "@typescript-eslint/eslint-plugin": "^6.0.0",
         "@typescript-eslint/parser": "^6.0.0",
@@ -5826,6 +5828,13 @@
         "url": "https://github.com/sponsors/isaacs"
       }
     },
+    "node_modules/@types/amap-js-api": {
+      "version": "1.4.16",
+      "resolved": "https://registry.npmmirror.com/@types/amap-js-api/-/amap-js-api-1.4.16.tgz",
+      "integrity": "sha512-gfcEswuU4GNRdGAh74FhxfLlU6qxmVIJYPf3HV0uKucCWQ9iSr8TonDhqBvHVmmQEY60K+UAeIh0YLwKo/jpFQ==",
+      "dev": true,
+      "license": "MIT"
+    },
     "node_modules/@types/body-parser": {
       "version": "1.19.5",
       "resolved": "https://registry.npmmirror.com/@types/body-parser/-/body-parser-1.19.5.tgz",
@@ -14086,6 +14095,25 @@
         "@angular/router": "^18.0.0"
       }
     },
+    "node_modules/ngx-amap": {
+      "version": "3.0.5",
+      "resolved": "https://registry.npmmirror.com/ngx-amap/-/ngx-amap-3.0.5.tgz",
+      "integrity": "sha512-gLoNLVHWcYiXYojNOX7VaR+nlRwA3zCzvOQrjFk9g4athPn5GnyDGVoPyYBmL7o2M1kHORMTrqqMqp+OjdlRwg==",
+      "license": "MIT",
+      "dependencies": {
+        "tslib": "^1.9.0"
+      },
+      "peerDependencies": {
+        "@angular/common": "^6.0.0-rc.0 || >=6.0.0",
+        "@angular/core": "^6.0.0-rc.0 || >=6.0.0"
+      }
+    },
+    "node_modules/ngx-amap/node_modules/tslib": {
+      "version": "1.14.1",
+      "resolved": "https://registry.npmmirror.com/tslib/-/tslib-1.14.1.tgz",
+      "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+      "license": "0BSD"
+    },
     "node_modules/nice-napi": {
       "version": "1.0.2",
       "resolved": "https://registry.npmmirror.com/nice-napi/-/nice-napi-1.0.2.tgz",

+ 3 - 1
wisdom-app/package.json

@@ -29,6 +29,7 @@
     "@ionic/angular": "^8.0.0",
     "fmode-ng": "^0.0.63",
     "ionicons": "^7.2.1",
+    "ngx-amap": "^3.0.5",
     "rxjs": "~7.8.0",
     "tslib": "^2.3.0",
     "zone.js": "~0.14.2"
@@ -45,6 +46,7 @@
     "@angular/language-service": "^18.0.0",
     "@capacitor/cli": "6.2.0",
     "@ionic/angular-toolkit": "^11.0.1",
+    "@types/amap-js-api": "^1.4.16",
     "@types/jasmine": "~5.1.0",
     "@typescript-eslint/eslint-plugin": "^6.0.0",
     "@typescript-eslint/parser": "^6.0.0",
@@ -62,4 +64,4 @@
     "typescript": "~5.4.0"
   },
   "description": "An Ionic project"
-}
+}

+ 1 - 0
wisdom-app/src/agent/agent-user-input/agent-user-input.component.ts

@@ -1,6 +1,7 @@
 import { Component, OnInit, Input } from '@angular/core';
 import { ModalController, IonHeader, IonContent, IonInput, IonToolbar, IonItem, IonButtons, IonButton, IonTitle } from '@ionic/angular/standalone';
 import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+
 export interface AgentUserInputField{
   name:string, // 字段名称
   type:string, // 输入类型

+ 29 - 0
wisdom-app/src/app/all-products-modal/all-products-modal.component.html

@@ -0,0 +1,29 @@
+<ion-header>
+  <ion-toolbar>
+    <ion-title>{{ title }}</ion-title>
+    <ion-buttons slot="end">
+      <ion-button fill="clear" (click)="dismiss()">
+        <ion-icon name="close"></ion-icon>
+      </ion-button>
+    </ion-buttons>
+  </ion-toolbar>
+</ion-header>
+
+<ion-content>
+  <div class="modal-content">
+    <ion-card *ngFor="let product of products" class="product-card" (click)="openDetailModal(product)">
+      <ion-card-header class="product-card-header">
+        <div class="product-tag">{{ product.get('title') || '药品详情' }}</div>
+      </ion-card-header>
+      <ion-card-content class="product-card-content">
+        <div class="product-image-wrapper">
+          <img [src]="product.get('image')" alt="{{product.get('name')}}" class="product-image">
+        </div>
+        <div class="product-info">
+          <h3 class="product-name">{{ product.get('name') }}</h3>
+          <div class="product-price">{{ product.get('price') }}</div>
+        </div>
+      </ion-card-content>
+    </ion-card>
+  </div>
+</ion-content>

+ 66 - 0
wisdom-app/src/app/all-products-modal/all-products-modal.component.scss

@@ -0,0 +1,66 @@
+.modal-content {
+    padding: 16px;
+  }
+  
+  .product-card {
+    border-radius: 12px;
+    box-shadow: 0 2px 8px rgba(0,0,0,0.08);
+    margin-bottom: 16px;
+  }
+  
+  .product-card-header {
+    background: #ffeb3b;
+    border-top-left-radius: 12px;
+    border-top-right-radius: 12px;
+    display: flex;
+    align-items: center;
+    padding: 8px 12px;
+  }
+  
+  .product-tag {
+    font-size: 14px;
+    font-weight: bold;
+    color: #333;
+  }
+  
+  .product-card-content {
+    display: flex;
+    align-items: center;
+    padding: 12px;
+  }
+  
+  .product-image-wrapper {
+    width: 80px;
+    height: 80px;
+    border-radius: 8px;
+    overflow: hidden;
+    margin-right: 12px;
+  }
+  
+  .product-image {
+    width: 100%;
+    height: 100%;
+    object-fit: cover;
+  }
+  
+  .product-info {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+  }
+  
+  .product-name {
+    font-size: 16px;
+    font-weight: bold;
+    color: #333;
+    white-space: normal;
+    word-break: break-all;
+    margin-bottom: 4px;
+  }
+  
+  .product-price {
+    font-size: 14px;
+    color: #e53935;
+    font-weight: bold;
+  }

+ 6 - 6
wisdom-app/src/app/page/page-drug-purchase/page-drug-purchase.component.spec.ts → wisdom-app/src/app/all-products-modal/all-products-modal.component.spec.ts

@@ -1,17 +1,17 @@
 import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
 
-import { PageDrugPurchaseComponent } from './page-drug-purchase.component';
+import { AllProductsModalComponent } from './all-products-modal.component';
 
-describe('PageDrugPurchaseComponent', () => {
-  let component: PageDrugPurchaseComponent;
-  let fixture: ComponentFixture<PageDrugPurchaseComponent>;
+describe('AllProductsModalComponent', () => {
+  let component: AllProductsModalComponent;
+  let fixture: ComponentFixture<AllProductsModalComponent>;
 
   beforeEach(waitForAsync(() => {
     TestBed.configureTestingModule({
-      imports: [PageDrugPurchaseComponent],
+      imports: [AllProductsModalComponent],
     }).compileComponents();
 
-    fixture = TestBed.createComponent(PageDrugPurchaseComponent);
+    fixture = TestBed.createComponent(AllProductsModalComponent);
     component = fixture.componentInstance;
     fixture.detectChanges();
   }));

+ 38 - 0
wisdom-app/src/app/all-products-modal/all-products-modal.component.ts

@@ -0,0 +1,38 @@
+import { Component, Input } from '@angular/core';
+import { ModalController, IonicModule } from '@ionic/angular';
+import { CommonModule } from '@angular/common';
+import { CloudObject } from 'src/lib/ncloud';
+import { DetailModalComponent } from '../detail-modal/detail-modal.component'; // 确保路径正确
+
+@Component({
+  selector: 'app-all-products-modal',
+  templateUrl: './all-products-modal.component.html',
+  styleUrls: ['./all-products-modal.component.scss'],
+  standalone: true,
+  imports: [
+    IonicModule,
+    CommonModule,
+    DetailModalComponent
+  ]
+})
+export class AllProductsModalComponent {
+  @Input() products: Array<CloudObject> = [];
+  @Input() title: string = '';
+
+  constructor(private modalCtrl: ModalController) {}
+
+  // 关闭模态窗口
+  dismiss() {
+    this.modalCtrl.dismiss();
+  }
+
+  // 打开药品详情模态窗口
+  async openDetailModal(product: any) {
+    const modal = await this.modalCtrl.create({
+      component: DetailModalComponent, // 确保 DetailModalComponent 已创建
+      componentProps: { product: product },
+      cssClass: 'bottom-modal'
+    });
+    return await modal.present();
+  }
+}

+ 5 - 0
wisdom-app/src/app/app.routes.ts

@@ -1,3 +1,4 @@
+import { NgModule } from '@angular/core';
 import { Routes } from '@angular/router';
 
 export const routes: Routes = [
@@ -21,4 +22,8 @@ export const routes: Routes = [
     redirectTo: '/chat/session/chat/:chatId',
     pathMatch: 'full'
   },
+  {
+    path: 'drug-category',
+    loadComponent: () => import('./drug-category/drug-category.page').then( m => m.DrugCategoryPage)
+  },
 ];

+ 1 - 1
wisdom-app/src/app/component/article-card/article-card.component.html

@@ -1,5 +1,5 @@
 <div class="card">
-  <img [src]="card.get('image')" alt="Image">
+  <img [src]="card.get('image')[0]" alt="Image">
   <div class="content">
     <h3>{{ card.get('title') }}</h3>
     <p>{{ card.get('topic') }} &nbsp; {{ card.get('date') }}</p>

+ 1 - 1
wisdom-app/src/app/component/edit-tag/edit-tag.component.html

@@ -1,5 +1,5 @@
 
-<ion-input [value]="userInput" (ionInput)="onInput($event)" type="text" placeholder="请输入标签名称"></ion-input>
+<ion-input [value]="userInput" (ionInput)="onInput($event)" type="text" placeholder="请输入标签名称(点击生成的标签即可删除)"></ion-input>
 <!-- <p>当前输入: {{userInput}}</p>  -->
 <ion-button (click)="addTag()" expand="block" color="success">添加标签</ion-button>
 <div>

+ 26 - 0
wisdom-app/src/app/detail-modal/detail-modal.component.html

@@ -0,0 +1,26 @@
+<ion-header>
+  <ion-toolbar>
+    <ion-title>{{ product?.get('name') || '药品详情' }}</ion-title>
+    <ion-buttons slot="end">
+      <ion-button fill="clear" (click)="dismiss()">
+        <ion-icon name="close"></ion-icon>
+      </ion-button>
+    </ion-buttons>
+  </ion-toolbar>
+</ion-header>
+
+<ion-content>
+  <div class="modal-content" *ngIf="product">
+    <div class="image-container">
+      <img [src]="product.get('image')" alt="{{product.get('name')}}" class="medicine-image">
+    </div>
+    <h2 class="product-name">{{ product.get('name') }}</h2>
+    <p><strong>价格:</strong>{{ product.get('price') }}</p>
+    <p><strong>是否处方药:</strong>{{ product.get('prescription') ? '是' : '否' }}</p>
+    <p><strong>用法用量:</strong>{{ product.get('usage') }}</p>
+    <p><strong>主治功能:</strong>{{ product.get('function') }}</p>
+    <p><strong>规格:</strong>{{ product.get('spec') }}</p>
+    <p><strong>成分:</strong>{{ product.get('composition') }}</p>
+    <p><strong>禁忌:</strong>{{ product.get('taboo') }}</p>
+  </div>
+</ion-content>

+ 30 - 0
wisdom-app/src/app/detail-modal/detail-modal.component.scss

@@ -0,0 +1,30 @@
+.modal-content {
+    padding: 16px;
+  }
+  
+  .image-container {
+    width: 100%;
+    text-align: center;
+    margin-bottom: 16px;
+  }
+  
+  .medicine-image {
+    width: 150px;
+    height: 150px;
+    object-fit: cover;
+    border-radius: 8px;
+  }
+  
+  .product-name {
+    font-size: 20px;
+    font-weight: bold;
+    color: #333;
+    text-align: center;
+    margin-bottom: 8px;
+  }
+  
+  p {
+    font-size: 16px;
+    color: #555;
+    margin-bottom: 4px;
+  }

+ 6 - 6
wisdom-app/src/app/page/page-phone-inquiry/page-phone-inquiry.component.spec.ts → wisdom-app/src/app/detail-modal/detail-modal.component.spec.ts

@@ -1,17 +1,17 @@
 import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
 
-import { PagePhoneInquiryComponent } from './page-phone-inquiry.component';
+import { DetailModalComponent } from './detail-modal.component';
 
-describe('PagePhoneInquiryComponent', () => {
-  let component: PagePhoneInquiryComponent;
-  let fixture: ComponentFixture<PagePhoneInquiryComponent>;
+describe('DetailModalComponent', () => {
+  let component: DetailModalComponent;
+  let fixture: ComponentFixture<DetailModalComponent>;
 
   beforeEach(waitForAsync(() => {
     TestBed.configureTestingModule({
-      imports: [PagePhoneInquiryComponent],
+      imports: [DetailModalComponent],
     }).compileComponents();
 
-    fixture = TestBed.createComponent(PagePhoneInquiryComponent);
+    fixture = TestBed.createComponent(DetailModalComponent);
     component = fixture.componentInstance;
     fixture.detectChanges();
   }));

+ 25 - 0
wisdom-app/src/app/detail-modal/detail-modal.component.ts

@@ -0,0 +1,25 @@
+import { Component, Input } from '@angular/core';
+import { ModalController, IonicModule } from '@ionic/angular';
+import { CommonModule } from '@angular/common';
+import { CloudObject } from 'src/lib/ncloud';
+
+@Component({
+  selector: 'app-detail-modal',
+  templateUrl: './detail-modal.component.html',
+  styleUrls: ['./detail-modal.component.scss'],
+  standalone: true,
+  imports: [
+    IonicModule,
+    CommonModule
+  ]
+})
+export class DetailModalComponent {
+  @Input() product: CloudObject | undefined;
+
+  constructor(private modalCtrl: ModalController) {}
+
+  // 关闭模态窗口
+  dismiss() {
+    this.modalCtrl.dismiss();
+  }
+}

+ 31 - 0
wisdom-app/src/app/drug-category/drug-category.page.html

@@ -0,0 +1,31 @@
+<ion-header>
+  <ion-toolbar>
+    <ion-buttons slot="start">
+      <ion-button (click)="dismiss()">
+        <ion-icon name="arrow-back"></ion-icon>
+      </ion-button>
+    </ion-buttons>
+    <ion-title>{{ categoryName }}</ion-title>
+  </ion-toolbar>
+</ion-header>
+
+<ion-content>
+  <div class="product-container">
+    <ng-container *ngFor="let product of products">
+      <ion-card class="product-card" (click)="openDetailModal(product)">
+        <ion-card-header class="product-card-header">
+          <div class="product-tag">{{ product.get('title') || '药品详情' }}</div>
+        </ion-card-header>
+        <ion-card-content class="product-card-content">
+          <div class="product-image-wrapper">
+            <img [src]="product.get('image')" alt="{{product.get('name')}}" class="product-image">
+          </div>
+          <div class="product-info">
+            <h3 class="product-name">{{ product.get('name') }}</h3>
+            <div class="product-price">{{ product.get('price') }}</div>
+          </div>
+        </ion-card-content>
+      </ion-card>
+    </ng-container>
+  </div>
+</ion-content>

+ 67 - 0
wisdom-app/src/app/drug-category/drug-category.page.scss

@@ -0,0 +1,67 @@
+.product-container {
+    padding: 0 16px;
+    margin-top: 16px;
+  }
+  
+  .product-card {
+    border-radius: 12px;
+    box-shadow: 0 2px 8px rgba(0,0,0,0.08);
+    margin-bottom: 16px;
+  }
+  
+  .product-card-header {
+    background: #ffeb3b;
+    border-top-left-radius: 12px;
+    border-top-right-radius: 12px;
+    display: flex;
+    align-items: center;
+    padding: 8px 12px;
+  }
+  
+  .product-tag {
+    font-size: 14px;
+    font-weight: bold;
+    color: #333;
+  }
+  
+  .product-card-content {
+    display: flex;
+    align-items: center;
+    padding: 12px;
+  }
+  
+  .product-image-wrapper {
+    width: 80px;
+    height: 80px;
+    border-radius: 8px;
+    overflow: hidden;
+    margin-right: 12px;
+  }
+  
+  .product-image {
+    width: 100%;
+    height: 100%;
+    object-fit: cover;
+  }
+  
+  .product-info {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+  }
+  
+  .product-name {
+    font-size: 16px;
+    font-weight: bold;
+    color: #333;
+    white-space: normal;
+    word-break: break-all;
+    margin-bottom: 4px;
+  }
+  
+  .product-price {
+    font-size: 14px;
+    color: #e53935;
+    font-weight: bold;
+  }

+ 17 - 0
wisdom-app/src/app/drug-category/drug-category.page.spec.ts

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

+ 58 - 0
wisdom-app/src/app/drug-category/drug-category.page.ts

@@ -0,0 +1,58 @@
+import { Component, OnInit } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+import { CloudObject, CloudQuery } from 'src/lib/ncloud';
+import { ModalController } from '@ionic/angular';
+import { AllProductsModalComponent } from '../all-products-modal/all-products-modal.component';
+import { IonicModule } from '@ionic/angular';
+import { CommonModule } from '@angular/common';
+
+@Component({
+  selector: 'app-drug-category',
+  templateUrl: './drug-category.page.html',
+  styleUrls: ['./drug-category.page.scss'],
+  standalone: true,
+  imports: [
+    IonicModule,
+    CommonModule,
+    AllProductsModalComponent
+  ]
+})
+export class DrugCategoryPage implements OnInit {
+  categoryName: string = '';
+  products: Array<CloudObject> = [];
+
+  constructor(
+    private route: ActivatedRoute,
+    private modalCtrl: ModalController
+  ) {}
+
+  async ngOnInit() {
+    this.route.paramMap.subscribe(async params => {
+      this.categoryName = params.get('name') || '';
+      await this.loadProducts();
+    });
+  }
+
+  async loadProducts() {
+    try {
+      const query = new CloudQuery('Drug');
+      query.equalTo('category', this.categoryName);
+      this.products = await query.find();
+    } catch (error) {
+      console.error('加载分类药品数据失败', error);
+    }
+  }
+
+  async openDetailModal(product: any) {
+    const modal = await this.modalCtrl.create({
+      component: AllProductsModalComponent, // 确保存在此组件
+      componentProps: { product: product },
+      cssClass: 'bottom-modal'
+    });
+    return await modal.present();
+  }
+
+  dismiss() {
+    window.history.back();
+  }
+}

+ 17 - 0
wisdom-app/src/app/page/data-modal/data-modal.component.html

@@ -0,0 +1,17 @@
+
+<ion-header>
+  <ion-toolbar>
+    <ion-buttons slot="start">
+      <ion-button color="medium" (click)="cancel()">取消</ion-button>
+    </ion-buttons>
+    <ion-title>用户输入</ion-title>
+    <ion-buttons slot="end">
+      <ion-button (click)="confirm()" [strong]="true">确认</ion-button>
+    </ion-buttons>
+  </ion-toolbar>
+</ion-header>
+<ion-content class="ion-padding">
+    <ion-item>
+      <ion-input labelPlacement="stacked" placeholder=""></ion-input>
+    </ion-item>
+</ion-content>

+ 0 - 0
wisdom-app/src/app/page/page-authority-experts/page-authority-experts.component.scss → wisdom-app/src/app/page/data-modal/data-modal.component.scss


+ 22 - 0
wisdom-app/src/app/page/data-modal/data-modal.component.spec.ts

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

+ 49 - 0
wisdom-app/src/app/page/data-modal/data-modal.component.ts

@@ -0,0 +1,49 @@
+import { Component, OnInit, Input,} from '@angular/core';
+import { ModalController, IonHeader, IonContent, IonInput, IonToolbar, IonItem, IonButtons, IonButton, IonTitle } from '@ionic/angular/standalone';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { IonicModule } from '@ionic/angular';
+import { CloudObject } from 'src/lib/ncloud';
+
+@Component({
+  selector: 'app-data-modal',
+  templateUrl: './data-modal.component.html',
+  styleUrls: ['./data-modal.component.scss'],
+  standalone: true,
+  imports: [
+    IonicModule,IonHeader,IonContent,IonInput,IonToolbar,IonItem,IonButtons,IonButton,
+    IonTitle,FormsModule,ReactiveFormsModule,
+  ]
+})
+
+export class DataModalComponent  implements OnInit {
+  name: string = '';
+
+  constructor(private modalCtrl: ModalController) {
+  }
+
+  ngOnInit(){
+  }
+
+  cancel() {
+    return this.modalCtrl.dismiss(null, 'cancel');
+  }
+
+  confirm() {
+    return this.modalCtrl.dismiss(this.name, 'confirm');
+  }
+}
+
+export async function cardDisplay(modalCtrl:ModalController){
+    const modal = await modalCtrl.create({
+        component: DataModalComponent,
+        breakpoints:[0.5,0.7],
+        initialBreakpoint:0.5
+    });
+    modal.present(); // 展示模态框
+    const { role, data } = await modal.onDidDismiss(); // 等待用户关闭模态框并获取返回的数据
+    console.log(data); // 打印返回的数据
+    if (role === 'confirm') {
+        console.log('User confirmed the action');
+        return data;
+    }
+}

+ 177 - 21
wisdom-app/src/app/page/inquiry-human/inquiry-human.component.html

@@ -3,37 +3,193 @@
     <div>
       <ion-button (click)="backhome()" color="primary" slot="start">{{back}}</ion-button>
     </div>
+    <ion-segment [(ngModel)]="selectedSegment" (ionChange)="segmentChanged($event)">
+      <ion-segment-button *ngFor="let segment of segments" [value]="segment">
+        {{segment}}
+      </ion-segment-button>
+    </ion-segment>
   </ion-toolbar>
 </ion-header>
 
 <ion-content>
   <div>
-    <ion-list>
-      <ion-item>
-        <ion-avatar aria-hidden="true" slot="start">
-          <img alt="" src="https://ionicframework.com/docs/img/demos/avatar.svg" />
+    <ion-card class="ioncard" *ngFor="let doctor of doctors" (click)="openDetailModal(doctor)">
+      <ion-item lines="none">
+        <ion-avatar slot="start">
+          <img [src]="doctor.avatar" alt="医生头像">
         </ion-avatar>
-        <ion-label>Huey</ion-label>
+        
+        <ion-label>
+          <div class="doctor-header">
+            <h2>{{doctor.name}}</h2>
+            <span>{{doctor.title}}</span>
+            <span>{{doctor.department}}</span>
+            <ion-badge color="primary">可开处方</ion-badge>
+          </div>
+          
+          <div class="hospital-info">
+            <span>{{doctor.hospital}}</span>
+            <ion-badge color="success">{{doctor.hospitalLevel}}</ion-badge>
+            <ion-badge color="warning">{{doctor.hospitalType}}</ion-badge>
+          </div>
+        </ion-label>
       </ion-item>
-      <ion-item>
-        <ion-avatar aria-hidden="true" slot="start">
-          <img alt="" src="https://ionicframework.com/docs/img/demos/avatar.svg" />
-        </ion-avatar>
-        <ion-label>Dewey</ion-label>
+    
+      <ion-item lines="none">
+        <ion-text color="medium" class="expertise">
+          {{doctor.expertise}}
+        </ion-text>
       </ion-item>
-      <ion-item>
-        <ion-avatar aria-hidden="true" slot="start">
-          <img alt="" src="https://ionicframework.com/docs/img/demos/avatar.svg" />
-        </ion-avatar>
-        <ion-label>Louie</ion-label>
+    
+      <ion-item lines="none">
+        <div class="stats">
+          <div>
+            <ion-text color="warning">{{doctor.rating}}</ion-text>
+            <ion-icon name="star" color="warning"></ion-icon>
+          </div>
+          <div>接诊量 {{doctor.consultations}}</div>
+          <div>同行认可 {{doctor.recommendations}}</div>
+        </div>
       </ion-item>
-      <ion-item>
-        <ion-avatar aria-hidden="true" slot="start">
-          <img alt="" src="https://ionicframework.com/docs/img/demos/avatar.svg" />
-        </ion-avatar>
-        <ion-label>Fooie</ion-label>
+    
+      <ion-item lines="none">
+        <div class="consultation-types">
+          <ion-button fill="outline">图文 ¥{{doctor.prices.text}}</ion-button>
+          <ion-button fill="outline">电话 ¥{{doctor.prices.voice}}</ion-button>
+          <ion-button fill="outline">视频 ¥{{doctor.prices.video}}</ion-button>
+          <ion-button color="success">年度好医生</ion-button>
+        </div>
       </ion-item>
-    </ion-list>    
+    </ion-card>
   </div>
+  
+
+  <!-- 底部弹出模态 -->
+  <ion-modal [isOpen]="isModalOpen" cssClass="bottom-modal">
+    <ng-template>
+      <ion-header>
+        <ion-toolbar>
+          <ion-buttons slot="start">
+            <ion-button (click)="closeDetailModal()">关闭</ion-button>
+          </ion-buttons>
+          <!-- <ion-title>{{}}</ion-title> -->
+          <ion-buttons slot="end">
+            <ion-button>分享</ion-button>
+          </ion-buttons>
+        </ion-toolbar>
+      </ion-header>
+
+      <ion-content class="ion-padding">
+        <div >
+          <ion-card class="first" >
+            <div class="doctor-header1" style="display: flex; background-color: rgb(213, 205, 144); border-radius: 5px;">
+              <div class="verification-badge" *ngIf="doctor.isVerified">
+                <ion-icon name="checkmark-circle"></ion-icon>
+                已通过实名认证
+              </div>
+              <div class="qualification-badge">
+                执业资质已审核通过
+              </div>
+            </div>
+          
+            <div class="doctor-info1">
+              <div class="left-section">
+                <div class="name-title">
+                  <h2>{{doctor.name}}</h2>
+                  <ion-badge *ngIf="doctor.isExpert" color="warning">知名专家</ion-badge>
+                </div>
+                
+                <div class="position">
+                  <span>{{doctor.department}}</span>
+                  <span>{{doctor.title}}</span>
+                </div>
+                
+                <div class="hospital">
+                  <span>{{doctor.hospital}}</span>
+                  <ion-badge color="success">{{doctor.hospitalLevel}}</ion-badge>
+                </div>
+          
+                <div class="stats">
+                  <div class="rating">
+                    <span class="number">{{doctor.rating}}</span>
+                    <ion-icon name="star" color="warning"></ion-icon>
+                  </div>
+                  <div class="consult">
+                    <span>接诊量 {{doctor.consultations}}</span>
+                  </div>
+                  <div class="service">
+                    <!-- <span>{{doctor.rating}}</span> -->
+                    <span>服务态度好</span>
+                  </div>
+                </div>
+              </div>
+          
+              <div class="right-section">
+                <ion-avatar>
+                  <img [src]="doctor.avatar" alt="医生头像">
+                </ion-avatar>
+                <ion-button style="color: rgb(0, 255, 0);" fill="outline" size="small">
+                  + 关注
+                </ion-button>
+              </div>
+            </div>
+            <div>
+              <div class="tags">
+                <ion-chip style="color: blue; border-radius: 10px; background-color: rgba(230, 230, 243, 0.671);" *ngFor="let tag of doctor.tags" outline>
+                  {{tag}}
+                </ion-chip>
+              </div>
+            </div>
+          </ion-card>
+        </div>
+        <div class="aa"  style="display: flex;">
+          <p class="aaa">保证医生真实</p>
+          <p class="aaa">未使用随时退</p>
+          <p class="aaa">不满意可申诉</p>
+        </div>
+        <div class="consult-options" >
+          <div class="option-grid">
+            <div class="option-item" 
+                 *ngFor="let option of options"
+                 [class.selected]="option.isSelected"
+                 [class.disabled]="!option.isAvailable"
+                 (click)="selectOption(option)">
+              
+              <div class="option-content">
+                <div class="icon-wrapper">
+                  <ion-icon [name]="option.icon"></ion-icon>
+                  <ion-icon *ngIf="option.isSelected" 
+                            name="checkmark-circle" 
+                            class="check-icon">
+                  </ion-icon>
+                </div>
+                
+                <div class="title1">{{option.title}}</div>
+                
+                <div class="price" *ngIf="option.price > 0">
+                  ¥{{option.price}}/{{option.unit}}
+                </div>
+                <div class="status" *ngIf="!option.isAvailable">
+                  暂未开通
+                </div>
+              </div>
+              
+            </div>
+          </div>
+        </div>
+        <div class="info" style="margin:0 20px;box-shadow: 1px 1px 1px 0px rgba(0, 0, 0, 0.163), -1px -1px 1px 0px rgba(0, 0, 0, 0.148);">
+          <div style="margin: 5px 10px;">
+            <h1 >擅长与简介</h1>
+          </div>
+          <div style="margin: 5px 10px;">
+            <p style="color: grey;"> {{doctor.expertise}}</p>
+          </div>
+        </div>
+      </ion-content>
+      <ion-footer>
+        <ion-button style="border-radius: 10px;" expand="block" color="success" (click)="openConsult()">立即咨询(¥120/次)</ion-button>
+      </ion-footer>
+    </ng-template>
+  </ion-modal>
 </ion-content>>
 

+ 287 - 0
wisdom-app/src/app/page/inquiry-human/inquiry-human.component.scss

@@ -0,0 +1,287 @@
+.ioncard {
+    margin: 16px;
+    box-shadow: none;
+    border: 1px solid #eee;
+  }
+  
+  .doctor-header {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+    
+    h2 {
+      margin: 0;
+      font-size: 18px;
+      font-weight: bold;
+    }
+  }
+  
+  .doctor-info {
+    margin: 4px 0;
+    font-size: 14px;
+    color: #666;
+    
+    span {
+      margin-right: 8px;
+    }
+  }
+  
+  .hospital-info {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+    font-size: 14px;
+    color: #666;
+  }
+  
+  .expertise {
+    font-size: 14px;
+    display: -webkit-box;
+    // -webkit-line-clamp: 2;
+    -webkit-box-orient: vertical;
+    overflow: hidden;
+  }
+  
+  .stats {
+    display: flex;
+    gap: 16px;
+    font-size: 14px;
+    
+    div {
+      display: flex;
+      align-items: center;
+      gap: 4px;
+    }
+  }
+  
+  .consultation-types {
+    display: flex;
+    gap: 8px;
+    overflow-x: auto;
+    
+    ion-button {
+      --padding-start: 16px;
+      --padding-end: 16px;
+      height: 32px;
+      font-size: 14px;
+    }
+  }
+
+
+
+
+  .first {
+    margin: 5px 16px;
+    padding: 12px;
+    box-shadow: none;
+    border: 1px solid #eee;
+  }
+  
+  .doctor-header1 {
+    display: flex;
+    justify-content: space-between;
+    margin-bottom: 12px;
+    font-size: 12px;
+    color: #666;
+  
+    .verification-badge {
+      display: flex;
+      align-items: center;
+      gap: 4px;
+      
+      ion-icon {
+        color: #52c41a;
+      }
+    }
+  }
+  
+  .doctor-info1 {
+    display: flex;
+    justify-content: space-between;
+    
+    .left-section {
+      flex: 1;
+      
+      .name-title {
+        display: flex;
+        align-items: center;
+        gap: 8px;
+        margin-bottom: 8px;
+  
+        h2 {
+          margin: 0;
+          font-size: 16px;
+          font-weight: 500;
+        }
+  
+        ion-badge {
+          --padding-start: 4px;
+          --padding-end: 4px;
+        }
+      }
+  
+      .position, .hospital {
+        display: flex;
+        align-items: center;
+        gap: 8px;
+        margin-bottom: 6px;
+        color: #666;
+        font-size: 14px;
+      }
+  
+      .stats {
+        display: flex;
+        align-items: center;
+        gap: 16px;
+        margin: 8px 0;
+        font-size: 14px;
+  
+        .rating {
+          display: flex;
+          align-items: center;
+          gap: 4px;
+          
+          .number {
+            color: #f90;
+            font-weight: 500;
+          }
+        }
+      }
+  
+      .tags {
+        color: blue;
+        display: flex;
+        flex-wrap: wrap;
+        gap: 8px;
+        
+        ion-chip {
+          margin: 0;
+          height: 24px;
+          --background: rgb(0, 255, 0);
+          --color: #666;
+        }
+      }
+    }
+  
+    .right-section {
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      gap: 8px;
+      margin-left: 16px;
+  
+      ion-avatar {
+        width: 64px;
+        height: 64px;
+      }
+  
+      ion-button {
+        --border-color: #666;
+        --color: #666;
+        font-size: 12px;
+      }
+    }
+  }
+  .aa{
+    margin: 2px auto;
+    padding: 0;
+  }
+  .aaa{
+    font-size: 12px;
+    color: gray;
+    margin-top: 0px;
+    margin-right: 15px;
+    margin-left: 35px;
+  }
+
+  .consult-options {
+    padding: 16px;
+    background: #fff;
+    margin: 0 10px
+  }
+  
+  .option-grid {
+    display: grid;
+    grid-template-columns: repeat(5, 1fr);
+    gap: 12px;
+  }
+  
+  .option-item {
+    position: relative;
+    border: 1px solid #e8e8e8;
+    border-radius: 8px;
+    padding: 12px;
+    cursor: pointer;
+    transition: all 0.3s;
+  
+    &.selected {
+      border-color: var(--ion-color-primary);
+      background-color: var(--ion-color-primary-tint);
+  
+      .icon-wrapper {
+        ion-icon {
+          color: var(--ion-color-primary);
+        }
+      }
+  
+      .title {
+        color: var(--ion-color-primary);
+      }
+    }
+  
+    &.disabled {
+      opacity: 0.6;
+      cursor: not-allowed;
+  
+      .icon-wrapper ion-icon {
+        color: #999;
+      }
+  
+      .title {
+        color: #999;
+      }
+    }
+  }
+  
+  .option-content {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    text-align: center;
+  }
+  
+  .icon-wrapper {
+    position: relative;
+    margin-bottom: 8px;
+  
+    ion-icon {
+      font-size: 24px;
+      color: #666;
+    }
+  
+    .check-icon {
+      position: absolute;
+      top: -4px;
+      right: -4px;
+      font-size: 16px;
+      color: var(--ion-color-primary);
+      background: #fff;
+      border-radius: 50%;
+    }
+  }
+  
+  .title1 {
+    font-size: 14px;
+    color: #333;
+    margin-bottom: 4px;
+  }
+  
+  .price {
+    font-size: 12px;
+    color: var(--ion-color-primary);
+  }
+  
+  .status {
+    font-size: 12px;
+    color: #999;
+  }

+ 199 - 3
wisdom-app/src/app/page/inquiry-human/inquiry-human.component.ts

@@ -1,21 +1,120 @@
 import { Component, OnInit } from '@angular/core';
-import { IonHeader, IonToolbar, IonTitle, IonContent, IonList, IonItem, IonLabel, IonAvatar, IonButton } from '@ionic/angular/standalone';
+import { IonModal, IonHeader, IonToolbar, IonTitle, IonContent, IonList, IonItem, IonLabel, IonAvatar, IonButton, IonChip, IonIcon, IonBadge, IonText, IonCard, IonSegmentButton, IonSegment, IonCol, IonRow, IonGrid, IonButtons, IonFooter } from '@ionic/angular/standalone';
 import { ExploreContainerComponent } from '../../explore-container/explore-container.component';
 import { addIcons } from 'ionicons';
 import { airplane, bluetooth, call, wifi } from 'ionicons/icons';
 import { Router } from '@angular/router';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+
 addIcons({ airplane, bluetooth, call, wifi });
+interface Doctor {
+  avatar: string;
+  name: string;
+  title: string;
+  department: string;
+  hospital: string;
+  hospitalLevel: string;
+  hospitalType: string;
+  expertise: string;
+  rating: number;
+  consultations: string;
+  recommendations: number;
+  tags?: string[];
+  prices: {
+    text: number;
+    voice: number;
+    video: number;
+  }
+  isVerified?: boolean;
+  isExpert?: boolean;
+}
+interface ConsultOption {
+  id: number;
+  title: string;
+  icon: string;
+  price: number;
+  unit: string;
+  isAvailable: boolean;
+  isSelected?: boolean;
+}
 
 @Component({
   selector: 'inquiry-human',
   templateUrl: './inquiry-human.component.html',
   styleUrls: ['./inquiry-human.component.scss'],
   standalone: true,
-  imports: [IonHeader, IonToolbar, IonTitle, IonContent, ExploreContainerComponent,
-    IonLabel,IonItem,IonList,IonAvatar,IonLabel,IonButton
+  imports: [
+    IonHeader, IonToolbar, IonTitle, IonContent, ExploreContainerComponent,CommonModule,
+    IonLabel,IonItem,IonList,IonAvatar,IonLabel,IonButton,IonChip,IonIcon,IonBadge,
+    IonText,IonCard,IonSegment,IonSegmentButton, FormsModule,IonCol,IonRow,IonGrid,
+    IonModal,IonButtons,IonFooter
   ]
 })
 export class InquiryHumanComponent  implements OnInit {
+  options: ConsultOption[] = [
+    {
+      id: 1,
+      title: '图文咨询',
+      icon: 'chatbubbles',
+      price: 120,
+      unit: '次',
+      isAvailable: true,
+      isSelected: true
+    },
+    {
+      id: 2,
+      title: '电话咨询',
+      icon: 'call',
+      price: 200,
+      unit: '次起',
+      isAvailable: true
+    },
+    {
+      id: 3,
+      title: '视频问诊',
+      icon: 'videocam',
+      price: 0,
+      unit: '',
+      isAvailable: false
+    },
+    {
+      id: 4,
+      title: '私人医生',
+      icon: 'person',
+      price: 0,
+      unit: '',
+      isAvailable: false
+    },
+    {
+      id: 5,
+      title: '预约',
+      icon: 'calendar',
+      price: 0,
+      unit: '',
+      isAvailable: false
+    }
+  ];
+  selectOption(option: ConsultOption) {
+    if (!option.isAvailable) return;
+    
+    this.options.forEach(opt => opt.isSelected = false);
+    option.isSelected = true;
+  }
+
+
+
+  isModalOpen = false;
+  doctor: any;    
+
+  openDetailModal(doctor?: any) {
+    this.isModalOpen = true;
+    this.doctor = doctor;
+  }
+  closeDetailModal() {
+    this.isModalOpen = false;
+    this.doctor = null;
+  }
 
   constructor(
     private router: Router
@@ -26,4 +125,101 @@ export class InquiryHumanComponent  implements OnInit {
   backhome(){
     this.router.navigate(['/tabs/tab1']);
   }
+  selectedSegment = '全部';
+  segments = ['全部', '妇科', '儿科', '皮肤性病科', '内科',];
+  
+  doctors: Doctor[] = [
+    {
+      avatar: 'https://app.fmode.cn/dev/jxnu/202226701019/doctor7.png',
+      name: '张伟',
+      title: '主任医师',
+      department: '消化内科',
+      hospital: '首都医科大学附属北京友谊..',
+      hospitalLevel: '三甲',
+      hospitalType: '百强医院',
+      expertise: '擅长:结肠息肉和息肉病、胃息肉、幽门螺杆菌感染、慢性胃炎、胃食管反流、慢性萎缩性胃炎、糜烂性胃炎...',
+      rating: 5.0,
+      consultations: '1.1万',
+      recommendations: 100,
+      prices: {
+        text: 100,
+        voice: 150,
+        video: 300
+      },
+      tags: ['百强医院', '可开处方', '从业24年', '擅长消化系统疾病', '可开处方'],
+      isVerified: true,
+      isExpert: true,
+    },
+    {
+      avatar: 'https://app.fmode.cn/dev/jxnu/202226701019/doctor6.png',
+      name: '张伟',
+      title: '主任医师',
+      department: '消化内科',
+      hospital: '首都医科大学附属北京友谊..',
+      hospitalLevel: '三甲',
+      hospitalType: '百强医院',
+      expertise: '擅长:结肠息肉和息肉病、胃息肉、幽门螺杆菌感染、慢性胃炎、胃食管反流、慢性萎缩性胃炎、糜烂性胃炎...',
+      rating: 5.0,
+      consultations: '1.1万',
+      recommendations: 100,
+      prices: {
+        text: 100,
+        voice: 150,
+        video: 300
+      },
+      tags: ['百强医院', '可开处方', '从业24年', '擅长消化系统疾病', '可开处方'],
+      isVerified: true,
+      isExpert: true,
+    },{
+      avatar: 'https://app.fmode.cn/dev/jxnu/202226701019/doctor5.png',
+      name: '张伟',
+      title: '主任医师',
+      department: '消化内科',
+      hospital: '首都医科大学附属北京友谊..',
+      hospitalLevel: '三甲',
+      hospitalType: '百强医院',
+      expertise: '擅长:结肠息肉和息肉病、胃息肉、幽门螺杆菌感染、慢性胃炎、胃食管反流、慢性萎缩性胃炎、糜烂性胃炎...',
+      rating: 5.0,
+      consultations: '1.1万',
+      recommendations: 100,
+      prices: {
+        text: 100,
+        voice: 150,
+        video: 300
+      },
+      tags: ['百强医院', '可开处方', '从业24年', '擅长消化系统疾病', '可开处方'],
+      isVerified: true,
+      isExpert: true,
+    },{
+      avatar: 'https://app.fmode.cn/dev/jxnu/202226701019/doctor7.png',
+      name: '张伟',
+      title: '主任医师',
+      department: '消化内科',
+      hospital: '首都医科大学附属北京友谊..',
+      hospitalLevel: '三甲',
+      hospitalType: '百强医院',
+      expertise: '擅长:结肠息肉和息肉病、胃息肉、幽门螺杆菌感染、慢性胃炎、胃食管反流、慢性萎缩性胃炎、糜烂性胃炎...',
+      rating: 5.0,
+      consultations: '1.1万',
+      recommendations: 100,
+      prices: {
+        text: 100,
+        voice: 150,
+        video: 300
+      },
+      tags: ['百强医院', '可开处方', '从业24年', '擅长消化系统疾病', '可开处方'],
+      isVerified: true,
+      isExpert: true,
+    }
+    ];
+    goToDoctorDetail(doctor: Doctor) {
+      // this.router.navigate(['/doctor-detail'], { state: { doctor: doctor } });
+    }
+  segmentChanged(event: any) {
+    this.selectedSegment = event.detail.value;
+    console.log(this.selectedSegment);
+  }
+  openConsult(){
+    console.log("openConsult");
+  }
 }

+ 45 - 0
wisdom-app/src/app/page/page-ai-knowledge/page-ai-knowledge.component.html

@@ -0,0 +1,45 @@
+
+<ion-header [translucent]="true">
+  <ion-toolbar class="toolbar">
+    <div>
+      <ion-button (click)="backHome()" color="primary">{{back}}</ion-button>
+    </div>
+  </ion-toolbar>
+</ion-header>
+
+<ion-content [fullscreen]="true">
+  <div>
+    <ion-list>
+      <ion-item>
+        <!-- <ion-input label="输入你想了解的科普信息" placeholder="Enter text"></ion-input> -->
+        <ion-input  [value]="kepu" placeholder="请输入科普" (ionInput)="kepuInput($event)"></ion-input>
+      </ion-item>
+    </ion-list>
+  </div>
+  <ion-button (click)="doInqueryTask()">执行问诊任务集</ion-button>
+  <!-- 意境画面提示词 -->
+  <div class="desc">
+    {{PictureDescResult}}
+  </div>
+  <!-- 生成结果 -->
+  @if(images.length) {
+    @for(imageUrl of images;track imageUrl){
+      <img [src]="imageUrl" alt="图片" srcset="">
+    }
+
+    <h3>图片地址:
+      <span class="copyable">{{images.join(', ')}}</span>
+    </h3>
+
+  }
+  <!-- 生成状态 -->
+  @if(!images.length){
+    <!-- <h2 style="display: grid; place-items: center;">欢迎使用头像生成器</h2> -->
+    @if(imagineWork.progress!=0){
+      <h1 style="display: grid; place-items: center;">生成中:{{imagineWork.progress}}</h1>
+    }
+    <!-- <div style="display: grid; place-items: center;">
+      <img src="../../assets/image/头像生成器.png">
+    </div> -->
+  }
+</ion-content>

+ 0 - 0
wisdom-app/src/app/page/page-drug-purchase/page-drug-purchase.component.scss → wisdom-app/src/app/page/page-ai-knowledge/page-ai-knowledge.component.scss


+ 22 - 0
wisdom-app/src/app/page/page-ai-knowledge/page-ai-knowledge.component.spec.ts

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

+ 111 - 0
wisdom-app/src/app/page/page-ai-knowledge/page-ai-knowledge.component.ts

@@ -0,0 +1,111 @@
+import { Component, OnInit } from '@angular/core';
+import { NgModel } from '@angular/forms';
+import { Router } from '@angular/router';
+import { IonButton, IonCard, IonCardContent, IonCardHeader, IonCardTitle, IonContent, IonHeader, IonIcon, IonInput, IonItem, IonLabel, IonList, IonToolbar, ModalController } from '@ionic/angular/standalone';
+import { CloudObject, CloudQuery, CloudUser } from 'src/lib/ncloud';
+import { CommonModule } from '@angular/common';
+import { TaskInqueryUserStory } from 'src/agent/tasks/inquiry/1.inquiry-user-story';
+import { TaskInqueryDoctorQuestion } from 'src/agent/tasks/inquiry/2.inquiry-doctor-question';
+import { TaskInqueryUserAnswer } from 'src/agent/tasks/inquiry/3.inquiry-user-answer';
+import { TaskExecutor } from 'src/agent/agent.start';
+import { AgentTaskStep } from 'src/agent/agent.task';
+import { DalleOptions, FmodeChatCompletion, ImagineWork } from 'fmode-ng';
+
+@Component({
+  selector: 'page-ai-knowledge',
+  templateUrl: './page-ai-knowledge.component.html',
+  styleUrls: ['./page-ai-knowledge.component.scss'],
+  standalone: true,
+  imports:[
+    IonHeader,IonToolbar,IonButton,IonContent,IonCard,IonCardTitle, IonCardHeader,
+    IonCardContent,CommonModule, IonInput,IonList, IonItem, IonLabel, IonIcon
+  ]
+})
+export class PageAiKnowledgeComponent  implements OnInit {
+
+  back: string = 'back'; //返回
+  backHome(){
+    this.router.navigate(['/tabs/tab2']);
+  }
+  gotouser(){
+
+  }
+
+  avatar : string = "";
+  currentUser : CloudUser | undefined ;
+  objectId : string = "";
+
+  constructor(
+    private router: Router,
+    private modalCtrl: ModalController,
+  ) {
+    this.loadData();
+     // 示例任务,自己生成图片后请存储新的ID 
+    //  this.imagineWork = new ImagineWork("");
+     this.imagineWork.fetchTask().then(work=>{
+       if(work){
+         this.imagineWork.id = work.id
+       }
+       this.images = this.imagineWork?.images;
+     })
+  }
+  allMessage : Array<CloudObject> = [];
+  async loadData(){
+    this.currentUser = new CloudUser();
+    this.avatar = this.currentUser.data["avatar"];
+    this.objectId = this.currentUser.data['objectId'];
+  }
+   
+  ngOnInit() {
+  }
+  kepu:string = ""
+  kepuInput(ev:any){
+    this.kepu = ev.detail.value;
+    console.log(this.kepu);
+  }
+  imagineWork:ImagineWork = new ImagineWork; // 图片生成
+  images:Array<string> = [] // 图片数组
+  PictureDescResult:string = `` // 画面描述结果
+  doInqueryTask(){
+    this.imagineWork = new ImagineWork();
+        if (this.kepu.length > 0){
+        // 文本生成
+        let PromptTemplate = `您是一名专业的医学教育工作者,擅长将晦涩难懂的医学名词转化为一些通俗易懂的话语,请您根据下面提供的内容,将其描述的画面、场景、人物、物品等用故事的方式表达并将内容压缩在五个画面中,直接写出画面,并且描述的画风以漫画的风格为主
+        需求如下:
+        ${this.kepu}
+        `
+        let completion = new FmodeChatCompletion([
+          {role:"system",content:""},
+          {role:"user",content:PromptTemplate}
+        ])
+        completion.sendCompletion().subscribe((message:any)=>{
+          // 打印消息体
+          console.log("消息体",message.content)
+          // 赋值消息内容给组件内属性
+          this.PictureDescResult = message.content
+          if(message?.complete){ // 判断message为完成状态,则设置isComplete为完成
+            for(let i = 0; i < 5; i++){
+              // 图片生成
+              let PicturePrompt = `${this.PictureDescResult}\n根据画面${i+1}:进行绘画,如果图片中有谈话内容,请以普通话为主,风格:画面不带任何其他文字。其中以中国漫画人物为主体,人物诙谐幽默,符合中国现代人审美。图片展示的内容要和前面提供的内容保持一致`
+              console.log(PicturePrompt)
+              let options:DalleOptions = {prompt:PicturePrompt}
+              this.imagineWork?.draw(options).subscribe(work=>{
+                console.log("imagineWork",work?.toJSON())
+                console.log("images",work?.get("images"))
+                if (work?.get("images")?.length){
+                  // 将生成的每一张图片存储到数组中
+                  this.images.push(work?.get("images")[0]);
+                  console.log("work?.get('images')",work?.get("images"))
+                }
+                console.log("this.images",this.images)
+              })
+            }
+          }
+        })
+      }
+      else{
+        this.kepu = "请提供您合理的健康知识,我将根据其意境为您创作一幅画面的简短描述。"
+      }
+  }
+
+}

+ 0 - 7
wisdom-app/src/app/page/page-authority-experts/page-authority-experts.component.html

@@ -1,7 +0,0 @@
-<ion-header [translucent]="true">
-  <ion-toolbar class="searchbar">
-    <div>
-      <ion-button (click)="backhome()" color="primary" slot="start">{{back}}</ion-button>
-    </div>
-  </ion-toolbar>
-</ion-header>

+ 0 - 22
wisdom-app/src/app/page/page-authority-experts/page-authority-experts.component.spec.ts

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

+ 0 - 26
wisdom-app/src/app/page/page-authority-experts/page-authority-experts.component.ts

@@ -1,26 +0,0 @@
-import { Component, OnInit } from '@angular/core';
-import { Router } from '@angular/router';
-import { IonButton, IonHeader, IonToolbar } from '@ionic/angular/standalone';
-
-@Component({
-  selector: 'page-authority-experts',
-  templateUrl: './page-authority-experts.component.html',
-  styleUrls: ['./page-authority-experts.component.scss'],
-  standalone: true,
-  imports:[
-    IonHeader,IonToolbar,IonButton,
-  ]
-})
-export class PageAuthorityExpertsComponent  implements OnInit {
-
-  constructor(
-    private router: Router
-  ) { }
-
-  ngOnInit() {}
-  back:string = "<";
-  backhome(){
-    this.router.navigate(['/tabs/tab1']);
-  }
-
-}

+ 85 - 0
wisdom-app/src/app/page/page-create-agent/page-create-agent.component.html

@@ -0,0 +1,85 @@
+<ion-header [translucent]="true">
+  <ion-toolbar>
+    <ion-buttons slot="start">
+      <ion-button (click)="backhome()" color="primary" >{{back}}</ion-button>
+    </ion-buttons>
+    <ion-title slot="end">创建智能体</ion-title>
+    <!-- <ion-progress-bar type="indeterminate"></ion-progress-bar> -->
+     @if(this.progress > 0){
+      <!-- // buffer 是缓冲进度,可以理解为最大进度
+      // value 是当前进度 -->
+      <ion-progress-bar [buffer]="buffer" [value]="progress"></ion-progress-bar>
+     }
+
+  </ion-toolbar>
+</ion-header>
+
+<ion-content [fullscreen]="true">
+  <ion-refresher slot="fixed" (ionRefresh)="handleRefresh($event)">
+    <ion-refresher-content></ion-refresher-content>
+  </ion-refresher>
+  <div style="text-align: center; margin-top: 20px">
+    <img height="80px" [src]="currentUser.get('avatar')" alt="" style="border-radius: 50%;">
+    <p>AI生成头像</p>
+  </div>
+  <div>
+    <ion-card>
+      <ion-list>
+        <ion-item>
+          <p style="width: 60px; font-weight: bolder;">名称:</p>
+          <!-- <ion-input label="输入你想了解的科普信息" placeholder="Enter text"></ion-input> -->
+          <ion-input  [value]="name" placeholder="输入名称" (ionInput)="nameInput($event)"></ion-input>
+        </ion-item>
+        <ion-item>
+          <p style="width: 60px; font-weight: bolder;">年龄:</p>
+          <ion-input  [value]="age" placeholder="输入年龄" (ionInput)="ageInput($event)"></ion-input>
+        </ion-item>
+        <ion-item>
+          <p style="width: 60px;  font-weight: bolder;">性别:</p>
+          <ion-select
+            aria-label="性别"
+            placeholder="选择性别"
+            (ionChange)="genderChange($event)"
+            (ionCancel)="genderCancel()"
+            (ionDismiss)="genderDismiss()"
+          >
+            <ion-select-option value="男">男</ion-select-option>
+            <ion-select-option value="女">女</ion-select-option>
+          </ion-select>
+        </ion-item>
+        <ion-item style="height: auto;">
+            <p style="width:120px;font-weight: bolder;">设定描述:</p>
+            <ion-textarea [value]="desc" placeholder="示例:你是一位经验丰富的妇科医生,拥有丰富的临床经验" (ionInput)="descInput($event)" autoGrow="true"></ion-textarea> 
+        </ion-item>
+      </ion-list>
+    </ion-card>
+  </div>
+  <ion-button (click)="presentToast('top')" (click)="createAgent()" expand="block" color="primary" >创建ai医生</ion-button>
+  <!-- <ion-button (click)="presentToast('middle')" expand="block">创建智能体</ion-button> -->
+
+  <ion-card>
+    <ion-card-header>
+      <ion-card-title>我的智能体</ion-card-title>
+      <ion-card-subtitle>智能体</ion-card-subtitle>
+    </ion-card-header>
+    <ion-card-content>
+      <ion-list>
+        <ion-item  *ngFor="let agent of agentList" lines="none">
+          <ion-thumbnail slot="start" (click)="openInquiry(agent)">
+            <img [src]="agent.get('avatar') || '../../assets/image/doctor7.png'" [alt]="agent.get('name')" />
+          </ion-thumbnail>
+          <div class="doctor-info" (click)="openInquiry(agent)">
+            <div>
+              <ion-text>{{ agent.get('name') }}({{ agent.get('age') }}岁)</ion-text>
+            </div>
+            <div>
+              <ion-text>{{ agent.get('gender') }}</ion-text>
+            </div>
+          </div>
+          <ion-button ios="logo-apple" size="small" color="danger" (click)="deleteAgent(agent)" slot="end">删除</ion-button>
+        </ion-item>
+      </ion-list>
+    </ion-card-content>
+  </ion-card>
+
+</ion-content>

+ 0 - 0
wisdom-app/src/app/page/page-health-information/page-health-information.component.scss → wisdom-app/src/app/page/page-create-agent/page-create-agent.component.scss


+ 22 - 0
wisdom-app/src/app/page/page-create-agent/page-create-agent.component.spec.ts

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

+ 313 - 0
wisdom-app/src/app/page/page-create-agent/page-create-agent.component.ts

@@ -0,0 +1,313 @@
+import { Component, OnInit } from '@angular/core';
+import { Router } from '@angular/router';
+import { CloudObject, CloudQuery, CloudUser } from 'src/lib/ncloud';
+import { IonHeader, IonToolbar, IonTitle, IonContent, IonButton,IonIcon, ModalController, IonTextarea, IonInput, IonCard, IonCardHeader, IonCardTitle, IonThumbnail, IonCardContent, IonCardSubtitle, IonItem, IonList, IonLabel, IonAvatar, IonSelect, IonSelectOption, AlertController, IonButtons, IonProgressBar, IonText, IonRefresherContent, IonRefresher, ToastController, IonToast } from '@ionic/angular/standalone';
+import { CommonModule } from '@angular/common';
+import { AvatarModule, ChatPanelOptions, DalleOptions, FmodeChat, FmodeChatCompletion, FmodeChatMessage, ImagineWork, openChatPanelModal } from 'fmode-ng';
+
+
+@Component({
+  selector: 'app-page-create-agent',
+  templateUrl: './page-create-agent.component.html',
+  styleUrls: ['./page-create-agent.component.scss'],
+  standalone: true,
+  imports: [
+    IonHeader, IonToolbar, IonTitle, IonContent, IonButton,IonTextarea,IonInput,
+    IonIcon,IonCard,IonCardHeader,IonCardTitle,
+    IonCardSubtitle,IonCardContent, IonThumbnail, IonItem,IonList,CommonModule,IonLabel,
+    IonAvatar, IonSelect, IonSelectOption,IonButtons,IonProgressBar,
+    IonText, IonCardHeader, IonCardSubtitle,IonRefresher,IonRefresherContent,
+    IonToast
+  ],
+})
+export class PageCreateAgentComponent  implements OnInit {
+  public buffer = 0.05;
+  public progress = 0;
+  
+  
+  async presentToast(position: 'top' | 'middle' | 'bottom') {
+    const toast = await this.toastController.create({
+      message: '正在创建智能体,请耐心等待!',
+      duration: 1500,
+      position: position,
+    });
+    await toast.present();
+  }
+
+  handleRefresh(event:any) {
+    setTimeout(() => {
+      // Any calls to load data go here
+      this.loadAgentData()
+      event.target.complete();
+    }, 2000);
+  }
+  currentUser: CloudUser;
+  constructor(
+    private toastController: ToastController,
+    private modalCtrl:ModalController,
+    private router:Router,
+    private alertController: AlertController
+  ) {
+
+   this.currentUser = new CloudUser();
+    // 示例任务,自己生成图片后请存储新的ID 
+    this.imagineWork = new ImagineWork("");
+    this.imagineWork.fetchTask().then(work=>{
+    if(work){
+      this.imagineWork.id = work.id
+    }
+    this.images = this.imagineWork?.images || '../../assets/image/头像示例.png';
+  })
+  this.loadAgentData()
+  }
+ images:Array<string> = []
+  back:string = "返回";
+
+  backhome() {
+    this.router.navigate(['/tabs/tab1']);
+  }
+  ngOnInit() {
+
+  }
+  name: string = ''
+  nameInput(e:any) {
+    this.name = e.detail.value;
+    console.log(this.name);
+  }
+  age: number = 18;
+  ageInput(e:any) {
+    this.age = e.detail.value;
+    console.log(this.age);
+  }
+  gender: string = "男";
+  genderChange(e:any) {
+    console.log('ionChange fired with value: ' + e.detail.value);
+    this.gender = e.detail.value;
+  }
+  genderCancel(){
+
+  }
+  genderDismiss(){
+
+  }
+  // 描述
+  desc: string = ''
+  descInput(e:any) {
+    this.desc = e.detail.value;
+    console.log(this.desc);
+  }
+  imagineWork:ImagineWork
+  PictureDescResult:string = `` // 画面描述结果
+
+  // 创建医生
+  async createAgent() {
+    let alert1 = await this.alertController.create({
+      header: '温馨提示',
+      subHeader: 'Tips',
+      message: '把信息填写完整哦~',
+      buttons: ['好的'],
+    });
+    let alert2 = await this.alertController.create({
+      header: '温馨提示',
+      subHeader: 'Tips',
+      message: '智能体已经创建成功!',
+      buttons: ['好的'],
+    });
+    let alert3 = await this.alertController.create({
+      header: '温馨提示',
+      subHeader: 'Tips',
+      message: '智能体开始创建,请耐心等待!',
+      buttons: ['好的'],
+    });
+    let alert4 = await this.alertController.create({
+      header: '温馨提示',
+      subHeader: 'Tips',
+      message: '智能体创建失败,请重新创建!',
+      buttons: ['好的'],
+    });
+    if (this.name == '' || this.age == 0 || this.gender == '' || this.desc == '') {
+      await alert1.present();
+      return;
+    } 
+    await alert3.present();
+    let a = setInterval(() => {
+      this.buffer += 0.03;
+      this.progress += 0.02;
+      if (this.progress > 1) {
+        this.buffer = 0.00;
+        this.progress = 0;
+        // 删除定时器
+        clearInterval(a);
+      }
+    }, 1000);
+
+    localStorage.setItem("company","E4KpGvTEto")
+
+    let consult = new CloudObject("DoctorAgent")
+    let now = new Date();
+    let dateStr = `${now.getFullYear()}-${now.getMonth()+1}-${now.getDate()}`
+    // 对象权限的精确指定
+    let ACL:any = {
+      "*":{read:true,write:true}
+    }
+    if(this.currentUser?.id){
+      ACL[this.currentUser?.id] = {read:true,write:true}
+    }
+
+      this.imagineWork = new ImagineWork();
+      // 文本生成
+      let PromptTemplate = `您是一名专业的美术画家,擅长画各类型头像图,请您根据下面提供的需求内容,将其描述的画面、场景、人物、物品等用最简短的语言表达,直接写出画面,
+      需求如下:
+      ${this.name},${this.age}岁,${this.gender},描述:${this.desc}
+      `
+      let completion = new FmodeChatCompletion([
+        {role:"system",content:""},
+        {role:"user",content:PromptTemplate}
+      ])
+      let avatar = ""
+      if (!this.name || !this.desc){
+        this.progress = 0; // 进度条重置
+        
+        await alert4.present();
+      }
+      completion.sendCompletion().subscribe((message:any)=>{
+        // 打印消息体
+        console.log(message.content)
+        // 赋值消息内容给组件内属性
+        this.PictureDescResult = message.content
+        if(message?.complete){ // 判断message为完成状态,则设置isComplete为完成
+              // 图片生成
+            let PicturePrompt = `${this.PictureDescResult}\n风格:画面不带任何文字。人物为主体,人物要在图片的正中央。其中人物必须帅气,符合现代中国人审美。`
+            let options:DalleOptions = {prompt:PicturePrompt}
+
+            this.imagineWork?.draw(options).subscribe(work=>{
+                if(work?.get("images")?.length){
+                  avatar =  work?.get("images")[0];
+                  console.log(work?.get("images"));
+                  console.log("work",work);
+                  console.log("里面的avatar",avatar);
+                  consult.set({
+                    avatar:`${avatar}`,
+                    name:`${this.name}`,
+                    age:`${this.age}`,
+                    gender:`${this.gender}`,
+                    desc:`${this.desc}`,
+                    user:this.currentUser.toPointer(),
+                    ACL:ACL,
+                  })
+                  consult.save();
+                  this.progress = 1;
+                  console.log("consult",consult);
+                  alert2.present();
+                  this.loadAgentData();
+                  this.name = ''
+                  this.desc = ''
+                }
+            })
+        }
+      })
+
+  }
+  
+  agentList: Array<CloudObject> = [];
+  async loadAgentData() {
+    let user = new CloudUser();
+    let query = new CloudQuery("DoctorAgent")
+    query.equalTo("user",user?.id)
+    let agentlist = await query.find()
+    // 将查询到的数据反向排序
+    this.agentList = agentlist.reverse()
+    console.log(this.agentList);
+  }
+
+  openInquiry(doctor:CloudObject){
+    // 验证用户登录
+    let currentUser = new CloudUser();
+    let userPrompt = ``
+    if(currentUser?.get("realname")){
+            userPrompt += `当前来访的患者,姓名:${currentUser?.get("realname")}`
+          }
+    if(currentUser?.get("gender")){
+      userPrompt += `,性别:${currentUser?.get("gender")}`
+    }
+    if(currentUser?.get("age")){
+      userPrompt += `,年龄:${currentUser?.get("age")}`
+    }
+    
+    localStorage.setItem("company","E4KpGvTEto")
+
+    let consult = new CloudObject("Consultation")
+    let now = new Date();
+    let dateStr = `${now.getFullYear()}-${now.getMonth()+1}-${now.getDate()}`
+    // 对象权限的精确指定
+    let ACL:any = {
+      "*":{read:true,write:true}
+    }
+    if(currentUser?.id){
+      ACL[currentUser?.id] = {read:true,write:true}
+    }
+    consult.set({
+      title:`门诊记录${dateStr}-${doctor?.get("name")}`,
+      doctor:doctor.toPointer(),
+      user:currentUser.toPointer(),
+      ACL:ACL
+    })
+
+    let options:ChatPanelOptions = {
+      roleId:"2DXJkRsjXK",
+      onChatInit:(chat:FmodeChat)=>{
+        console.log("onChatInit");
+              console.log("预设角色",chat.role);
+              chat.role.set("name",doctor?.get("name"));
+              chat.role.set("desc",doctor?.get("desc"));
+              chat.role.set("avatar",doctor?.get("avatar") || "../../assets/image/doctor7.png")
+              chat.role.set("prompt",`
+# 角色设定
+您是${doctor?.get("name")},${doctor?.get("desc")},年龄${doctor?.get("age")}岁,需要完成一次完整的门诊服务。
+
+# 对话环节
+0.导诊(根据用户基本情况,引导挂号合适的科室)
+1.预设的问询方式(根据不同症状来问询具体的情况)
+- 打招呼,以用户自述为主
+- 当信息充足时候,确认用户症状对应的科室,并进入下一个环节
+2.拓展的问询细节
+例如:用户反映呼吸不畅,拓展出:是否咳嗽;是否感觉痛或者痒等其他需要的问题。
+- 当问询细节补充完成后进入下一个环节
+3.初步的诊断结果,并且同时列出检查检验项目
+初步诊断:确定需要有哪些进一步检查
+检查检验:获取医学客观数据
+- 等待用户提交客观数据,进入下一阶段
+4.给出诊断方案并给出处方
+- 完成处方时,请在消息结尾附带: [处方完成]
+
+# 开始话语
+当您准备好了,可以以一个医生的身份,向来访的用户打招呼。
+${userPrompt}
+`);
+        },
+        onMessage:(chat:FmodeChat,message:FmodeChatMessage)=>{
+          console.log("onMessage",message)
+          let content:any = message?.content
+          if(typeof content == "string"){
+            if(content?.indexOf("[处方完成]")>-1){
+              console.log("门诊已完成")
+              consult.set({
+                content:content // 处方内容
+              })
+              consult.save();
+            }
+          }
+        },
+        onChatSaved:(chat:FmodeChat)=>{
+          // chat?.chatSession?.id 本次会话的 chatId
+          console.log("onChatSaved",chat,chat?.chatSession,chat?.chatSession?.id)
+        }
+      }
+      openChatPanelModal(this.modalCtrl,options)
+  }
+  deleteAgent(agent:CloudObject){
+    console.log("删除了",agent);
+    agent.destroy();
+    this.loadAgentData();
+  }
+}

+ 0 - 7
wisdom-app/src/app/page/page-drug-purchase/page-drug-purchase.component.html

@@ -1,7 +0,0 @@
-<ion-header [translucent]="true">
-  <ion-toolbar class="searchbar">
-    <div>
-      <ion-button (click)="backhome()" color="primary" slot="start">{{back}}</ion-button>
-    </div>
-  </ion-toolbar>
-</ion-header>

+ 0 - 26
wisdom-app/src/app/page/page-drug-purchase/page-drug-purchase.component.ts

@@ -1,26 +0,0 @@
-import { Component, OnInit } from '@angular/core';
-import { Router } from '@angular/router';
-import { IonButton, IonHeader, IonToolbar } from '@ionic/angular/standalone';
-
-@Component({
-  selector: 'page-drug-purchase',
-  templateUrl: './page-drug-purchase.component.html',
-  styleUrls: ['./page-drug-purchase.component.scss'],
-  standalone: true,
-  imports:[
-    IonHeader,IonToolbar,IonButton,
-  ]
-})
-export class PageDrugPurchaseComponent  implements OnInit {
-
-  constructor(
-    private router: Router
-  ) { }
-
-  ngOnInit() {}
-  back:string = "<";
-  backhome(){
-    this.router.navigate(['/tabs/tab1']);
-  }
-
-}

+ 0 - 7
wisdom-app/src/app/page/page-health-information/page-health-information.component.html

@@ -1,7 +0,0 @@
-<ion-header [translucent]="true">
-  <ion-toolbar class="searchbar">
-    <div>
-      <ion-button (click)="backhome()" color="primary" slot="start">{{back}}</ion-button>
-    </div>
-  </ion-toolbar>
-</ion-header>

+ 0 - 22
wisdom-app/src/app/page/page-health-information/page-health-information.component.spec.ts

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

+ 0 - 26
wisdom-app/src/app/page/page-health-information/page-health-information.component.ts

@@ -1,26 +0,0 @@
-import { Component, OnInit } from '@angular/core';
-import { Router } from '@angular/router';
-import { IonButton, IonHeader, IonToolbar } from '@ionic/angular/standalone';
-
-@Component({
-  selector: 'page-health-information',
-  templateUrl: './page-health-information.component.html',
-  styleUrls: ['./page-health-information.component.scss'],
-  standalone: true,
-  imports:[
-    IonHeader,IonToolbar,IonButton,
-  ]
-})
-export class PageHealthInformationComponent  implements OnInit {
-
-  constructor(
-    private router: Router
-  ) { }
-
-  ngOnInit() {}
-  back:string = "<";
-  backhome(){
-    this.router.navigate(['/tabs/tab1']);
-  }
-
-}

+ 0 - 7
wisdom-app/src/app/page/page-health-records/page-health-records.component.html

@@ -1,7 +0,0 @@
-<ion-header [translucent]="true">
-  <ion-toolbar class="searchbar">
-    <div>
-      <ion-button (click)="backhome()" color="primary" >{{back}}</ion-button>
-    </div>
-  </ion-toolbar>
-</ion-header>

+ 0 - 0
wisdom-app/src/app/page/page-health-records/page-health-records.component.scss


+ 0 - 22
wisdom-app/src/app/page/page-health-records/page-health-records.component.spec.ts

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

+ 0 - 26
wisdom-app/src/app/page/page-health-records/page-health-records.component.ts

@@ -1,26 +0,0 @@
-import { Component, OnInit } from '@angular/core';
-import { Router } from '@angular/router';
-import { IonButton, IonHeader, IonToolbar } from '@ionic/angular/standalone';
-
-@Component({
-  selector: 'page-health-records',
-  templateUrl: './page-health-records.component.html',
-  styleUrls: ['./page-health-records.component.scss'],
-  standalone: true,
-  imports:[
-    IonHeader,IonToolbar,IonButton,
-  ]
-})
-export class PageHealthRecordsComponent  implements OnInit {
-
-  constructor(
-    private router: Router
-  ) { }
-
-  ngOnInit() {}
-  back:string = "<";
-  backhome(){
-    this.router.navigate(['/tabs/tab1']);
-  }
-
-}

+ 56 - 4
wisdom-app/src/app/page/page-inquiry/page-inquiry.component.html

@@ -7,7 +7,51 @@
 </ion-header>
 
 <ion-content>
-
+  <div>
+    <ion-list>
+      <ion-item>
+        <ion-avatar aria-hidden="true" slot="start">
+          <img alt="currentUser.get('realname') | 头像" [src]="currentUser.get('avatar')"   />
+        </ion-avatar>
+        <ion-label>{{currentUser.get('realname')}}</ion-label>
+      </ion-item>
+    </ion-list>
+  </div>
+  
+  <div>
+      <ion-grid>
+        <ion-row>
+          <ion-col size="6" *ngFor="let doctor of doctorList">
+            <ion-card class="ioncard">
+              <ion-item class="ionitem" lines="none" (click)="openInquiry(doctor)">
+                <ion-avatar slot="start">
+                  <img [src]="doctor.get('avatar')" />
+                </ion-avatar>
+                <ion-label>
+                  <h2>{{ doctor.get('name') }}({{ doctor.get('age') }}岁)</h2>
+                  <p>{{ doctor.get('title') }},{{ doctor.get('depart')?.name }}</p>
+                </ion-label>
+              </ion-item>
+              
+              <ion-item lines="none" class="hospital-infom">
+                <ion-label>
+                  <!-- <p>{{doctor.hospital}}</p> -->
+                  <p>智养互联网医院</p>
+                  <div class="badges">
+                    <!-- <ion-badge color="success">{{doctor.hospitalLevel}}</ion-badge>
+                    <span>{{doctor.hospitalType}}</span> -->
+                    <ion-badge color="success">三甲</ion-badge>
+                    <span>百强医院</span>
+                  </div>
+                </ion-label>
+              </ion-item>
+            </ion-card>
+          </ion-col>
+        </ion-row>
+      </ion-grid>
+  </div>
+  
+  
   <!-- <h1>科室</h1>
   <ion-input  [value]="keshi" placeholder="请输入科室" (ionInput)="keshiInput($event)"></ion-input> -->
 
@@ -28,7 +72,7 @@
   <!-- @if(isComplete){
     <fm-markdown-preview class="content-style" [content]="responseMsg"></fm-markdown-preview>
   } -->
-  <ion-button (click)="doInqueryTask()">执行问诊任务集</ion-button>
+  <!-- <ion-button (click)="doInqueryTask()">执行问诊任务集</ion-button> -->
   <ul>
     @for(step of taskList;track step.title;){
       <div>
@@ -65,7 +109,7 @@
       <h2>{{shareData.diagResult.desc}}</h2>
       <p>{{shareData.diagResult.content}}</p>
     }
-    <div>
+    <!-- <div>
       <ion-card>
         <ion-card-header>
           <ion-card-title>权威医生</ion-card-title>
@@ -86,5 +130,13 @@
           </ion-list>
         </ion-card-content>
       </ion-card>
+    </div> -->
+</ion-content>
+
+<ion-footer>
+  <ion-toolbar>
+    <div class="createai">
+      <ion-button aria-setsize="large" expand="block" (click)="createAI()" color="primary" slot="start">创建ai医生</ion-button>
     </div>
-</ion-content>
+  </ion-toolbar>
+</ion-footer>

+ 52 - 0
wisdom-app/src/app/page/page-inquiry/page-inquiry.component.scss

@@ -0,0 +1,52 @@
+.createai{
+    ion-button{
+        contain-intrinsic-height: 50px;
+    }
+}
+
+.ioncard {
+    margin: 8px;
+    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+    
+    ion-item {
+      --padding-start: 8px;
+      --padding-end: 8px;
+      --min-height: auto;
+    }
+    
+    ion-avatar {
+      width: 40px;
+      height: 40px;
+    }
+    
+    h2 {
+      font-size: 14px;
+      font-weight: 500;
+      margin-bottom: 4px;
+    }
+    
+    p {
+      font-size: 12px;
+      color: #666;
+      margin: 0;
+    }
+  }
+  
+  .hospital-infom {
+    .badges {
+      display: flex;
+      align-items: center;
+      gap: 4px;
+      margin-top: 4px;
+      
+      ion-badge {
+        font-size: 10px;
+        padding: 2px 4px;
+      }
+      
+      span {
+        font-size: 10px;
+        color: #666;
+      }
+    }
+  }

+ 77 - 10
wisdom-app/src/app/page/page-inquiry/page-inquiry.component.ts

@@ -1,5 +1,5 @@
 import { Component,OnInit } from '@angular/core';
-import { IonHeader, IonToolbar, IonTitle, IonContent, IonButton,IonIcon, ModalController, IonTextarea, IonInput, IonCard, IonCardHeader, IonCardTitle, IonThumbnail, IonCardContent, IonCardSubtitle, IonItem, IonList } from '@ionic/angular/standalone';
+import { IonHeader, IonToolbar, IonTitle, IonContent, IonButton,IonIcon, ModalController, IonTextarea, IonInput, IonCard, IonCardHeader, IonCardTitle, IonThumbnail, IonCardContent, IonCardSubtitle, IonItem, IonList, IonLabel, IonAvatar, IonCol, IonRow, IonGrid, IonBadge, IonFooter } from '@ionic/angular/standalone';
 import { AgentTaskStep } from 'src/agent/agent.task';
 import { addIcons } from 'ionicons';
 import { radioButtonOffOutline, reloadOutline, checkmarkCircleOutline, closeCircleOutline } from 'ionicons/icons';
@@ -16,8 +16,20 @@ import { TaskInqueryUserAnswer } from 'src/agent/tasks/inquiry/3.inquiry-user-an
 import { Router } from '@angular/router';
 import { CloudObject, CloudQuery, CloudUser } from 'src/lib/ncloud';
 import { openUserLoginModal } from 'src/lib/user/modal-user-login/modal-user-login.component';
+import { FormsModule } from '@angular/forms';
 addIcons({radioButtonOffOutline,reloadOutline,checkmarkCircleOutline,closeCircleOutline})
 
+interface Doctor1 {
+  id: number;
+  name: string;
+  title: string;
+  department: string;
+  hospital: string;
+  hospitalLevel: string;
+  hospitalType: string;
+  avatar: string;
+}
+
 @Component({
   selector: 'page-inquiry',
   templateUrl: './page-inquiry.component.html',
@@ -26,10 +38,16 @@ addIcons({radioButtonOffOutline,reloadOutline,checkmarkCircleOutline,closeCircle
   imports: [
     IonHeader, IonToolbar, IonTitle, IonContent, IonButton,IonTextarea,IonInput,
     IonIcon,AgentUserInputComponent,DecimalPipe,IonCard,IonCardHeader,IonCardTitle,
-    IonCardSubtitle,IonCardContent, IonThumbnail, IonItem,IonList,CommonModule
+    IonCardSubtitle,IonCardContent, IonThumbnail, IonItem,IonList,CommonModule,IonLabel,
+    IonAvatar,FormsModule,IonCol,IonRow,IonGrid,IonBadge,IonFooter
   ],
 })
+
 export class PageInquiryComponent  implements OnInit {
+  createAI(){
+    this.router.navigate(['/tabs/create-agent']);
+    console.log("createAI")
+  }
 
   ngOnInit(){
     this.loadDoctorList();
@@ -42,11 +60,14 @@ export class PageInquiryComponent  implements OnInit {
     this.doctorList = await query.find()
     console.log(this.doctorList)
   }
-
+  currentUser: CloudUser 
   constructor(
     private modalCtrl:ModalController,
     private router:Router
-  ) {}
+  ) {
+    this.currentUser = new CloudUser;
+    console.log(this.currentUser)
+  }
 
   back:string = "<";
 
@@ -130,11 +151,14 @@ export class PageInquiryComponent  implements OnInit {
       let userPrompt = ``
       if(!currentUser?.id){
         console.log("用户未登录,请登录后重试");
-        let user = await openUserLoginModal(this.modalCtrl);
-        if(!user?.id){
-          return
-        }
-        currentUser = user;
+        this.router.navigate(['/tabs/tab4']);
+        return
+        // let user = await openUserLoginModal(this.modalCtrl);
+        // if(!user?.id){
+        //   this.router.navigate(['/tabs/tab4']);
+        //   return
+        // }
+        // currentUser = user;
       }
       
       if(currentUser?.get("realname")){
@@ -155,7 +179,7 @@ export class PageInquiryComponent  implements OnInit {
       let dateStr = `${now.getFullYear()}-${now.getMonth()+1}-${now.getDate()}`
       // 对象权限的精确指定
       let ACL:any = {
-        "*":{read:false,write:false}
+        "*":{read:true,write:true}
       }
       if(currentUser?.id){
         ACL[currentUser?.id] = {read:true,write:true}
@@ -226,4 +250,47 @@ export class PageInquiryComponent  implements OnInit {
       }
       openChatPanelModal(this.modalCtrl,options)
     }
+
+    doctors1: Doctor1[] = [
+      {
+        id: 1,
+        name: '张晨芙',
+        title: '主任医师',
+        department: '小儿重症...',
+        hospital: '浙江大学医学院附属...',
+        hospitalLevel: '三甲',
+        hospitalType: '百强医院',
+        avatar: 'assets/doctor1.jpg'
+      },
+      {
+        id: 2,
+        name: '时若',
+        title: '副主任医师',
+        department: '皮肤科',
+        hospital: '空军军医大学西京医院',
+        hospitalLevel: '三甲',
+        hospitalType: '百强医院',
+        avatar: 'assets/doctor2.jpg'
+      },
+      {
+        id: 3,
+        name: '李洁',
+        title: '主治医师',
+        department: '儿科',
+        hospital: '北京大学人民医院',
+        hospitalLevel: '三甲',
+        hospitalType: '百强医院',
+        avatar: 'assets/doctor3.jpg'
+      },
+      {
+        id: 4,
+        name: '马凤富',
+        title: '主治医师',
+        department: '肛肠科',
+        hospital: '中日友好医院',
+        hospitalLevel: '三甲',
+        hospitalType: '百强医院',
+        avatar: 'assets/doctor4.jpg'
+      }
+    ];
 }

+ 58 - 6
wisdom-app/src/app/page/page-my-health/page-my-health.component.html

@@ -1,11 +1,63 @@
 <ion-header [translucent]="true">
   <ion-toolbar class="searchbar">
-    <div>
-      <ion-button (click)="backHome()" color="primary">{{back}}</ion-button>
-    </div>
+    <ion-button slot="start" (click)="backHome()" color="primary">{{back}}</ion-button>
+    <ion-title>
+      <div class="user-info">
+        <ion-avatar class="user-avatar">
+          <img [src]="avatar" (error)="handleImageError()" alt="用户头像" class="avatar" />
+        </ion-avatar>
+        <span class="user-name">欢迎,{{ userName }}!</span>
+      </div>
+      我的每次问询记录
+    </ion-title>
+    <ion-buttons slot="end">
+      <ion-icon name="menu-outline"></ion-icon>
+    </ion-buttons>
   </ion-toolbar>
 </ion-header>
 
-<p>
-  page-my-health works!
-</p>
+<ion-content [fullscreen]="true">
+  <ion-refresher slot="fixed" (ionRefresh)="handleRefresh($event)">
+    <ion-refresher-content></ion-refresher-content>
+  </ion-refresher>
+
+  <!-- 数据加载指示器 -->
+  <ion-spinner *ngIf="isLoading" name="crescent" class="loading-spinner"></ion-spinner>
+
+  <!-- 数据展示区域 -->
+
+  <div *ngIf="!isLoading && allMessage.length === 0" class="no-data">
+    <ion-icon name="folder-open-outline" style="font-size: 50px; color: #888;"></ion-icon>
+    <p>暂无问询记录,赶快去咨询医生吧!</p>
+  </div>
+
+  <ion-list *ngIf="!isLoading && allMessage.length > 0">
+    <ion-item *ngFor="let message of allMessage" lines="none">
+      <ion-card class="message-card">
+        <ion-card-header>
+          <ion-card-title>就诊时间: {{ message?.updatedAt | date:'short' }}</ion-card-title>
+        </ion-card-header>
+        <ion-card-content>
+          <ion-icon name="person-outline" slot="start"></ion-icon>
+          <p><strong>就诊医生:</strong> {{ message.data["doctor"]?.name }}</p>
+          <ion-icon name="business-outline" slot="start"></ion-icon>
+          <p><strong>就诊部门:</strong> {{ message.data["depart"]?.name }}</p>
+          <ion-icon name="medical-outline" slot="start"></ion-icon>
+          <p><strong>门诊名称:</strong> {{ message.data["title"] }}</p>
+          <ion-icon name="document-text-outline" slot="start"></ion-icon>
+          <p><strong>就诊内容:</strong> {{ message.data["content"] }}</p>
+        </ion-card-content>
+      </ion-card>
+    </ion-item>
+  </ion-list>
+
+  <!-- 无数据提示 -->
+  <div *ngIf="!isLoading && allMessage.length === 0" class="no-data">
+    <p>暂无问询记录。</p>
+  </div>
+
+  <!-- 错误提示 -->
+  <div *ngIf="!isLoading && errorMessage" class="error-message">
+    <p>{{ errorMessage }}</p>
+  </div>
+</ion-content>

+ 97 - 0
wisdom-app/src/app/page/page-my-health/page-my-health.component.scss

@@ -0,0 +1,97 @@
+.searchbar {
+    --background: #ffffff;
+    --ion-color-primary: #3880ff;
+  }
+  
+  .user-info {
+    display: flex;
+    align-items: center;
+    background: linear-gradient(to right, #f8fafc, #58f083);
+    padding: 10px;
+    border-radius: 8px;
+  }
+  
+  .user-avatar {
+    width: 50px;
+    height: 50px;
+    margin-right: 10px;
+  }
+  
+  .user-avatar img.avatar {
+    width: 100%;
+    height: 100%;
+    border-radius: 50%;
+  }
+  
+  .user-name {
+    font-size: 20px;
+    font-weight: bold;
+    color: #3880ff;
+    margin-left: 10px;
+  }
+  
+  .user-details {
+    text-align: center;
+    margin: 10px 0;
+  }
+  
+  .loading-spinner {
+    display: block;
+    margin: 50px auto;
+  }
+  
+  .message-card {
+    margin: 15px;
+    border-radius: 10px;
+    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
+    background: #f9f9f9;
+    transition: transform 0.2s;
+  }
+  .message-card:hover {
+    transform: scale(1.03);
+  }
+  .message-card ion-card-header {
+    background: #e7effb;
+    padding: 10px;
+    border-radius: 10px 10px 0 0;
+  }
+  
+  .message-card ion-card-title {
+    font-size: 16px;
+    font-weight: bold;
+  }
+  
+  .message-card ion-card-content p {
+    margin: 5px 0;
+    font-size: 14px;
+  }
+  
+  .no-data {
+    text-align: center;
+    margin-top: 50px;
+    color: gray;
+    font-size: 16px;
+  }
+  
+  .error-message {
+    text-align: center;
+    margin-top: 50px;
+    color: red;
+    font-size: 16px;
+  }
+
+  .ion-icon {
+    margin-right: 8px;
+    color: #3880ff;
+  }
+
+  .loading-spinner {
+    display: block;
+    margin: 50px auto;
+    animation: spin 2s linear infinite;
+  }
+  
+  @keyframes spin {
+    0% { transform: rotate(0deg); }
+    100% { transform: rotate(360deg); }
+  }

+ 140 - 13
wisdom-app/src/app/page/page-my-health/page-my-health.component.ts

@@ -1,29 +1,156 @@
 import { Component, OnInit } from '@angular/core';
+import {
+  ModalController,
+  IonModal,
+  IonHeader,
+  IonToolbar,
+  IonTitle,
+  IonContent,
+  IonList,
+  IonItem,
+  IonLabel,
+  IonAvatar,
+  IonButton,
+  IonSegment,
+  IonSegmentButton,
+  IonSegmentContent,
+  IonSegmentView,
+  IonCardContent,
+  IonCardTitle,
+  IonCardHeader,
+  IonCard,
+  IonIcon,
+  IonButtons,
+  IonInput,
+  IonRefresherContent,
+  IonRefresher,
+  LoadingController,
+  IonSpinner,
+  IonGrid,        // 导入 IonGrid
+  IonRow,         // 导入 IonRow
+  IonCol          // 导入 IonCol
+} from '@ionic/angular/standalone'; // 确保导入自 '@ionic/angular/standalone'
+
+import { addIcons } from 'ionicons';
+import { airplane, bluetooth, call, wifi, arrowBackOutline, menuOutline, personOutline, businessOutline, medicalOutline, documentTextOutline, folderOpenOutline } from 'ionicons/icons';
+import { CommonModule } from '@angular/common';
+import { CloudObject, CloudQuery, CloudUser } from 'src/lib/ncloud';
+// import { FmMarkdownPreview } from 'fmode-ng';
 import { Router } from '@angular/router';
-import { IonButton, IonHeader, IonToolbar } from '@ionic/angular/standalone';
+addIcons({ airplane, bluetooth, call, wifi });
 
 @Component({
   selector: 'page-my-health',
   templateUrl: './page-my-health.component.html',
   styleUrls: ['./page-my-health.component.scss'],
   standalone: true,
-  imports:[
-    IonHeader,IonToolbar,IonButton
+  imports: [
+    IonHeader,
+    IonToolbar,
+    IonTitle,
+    IonContent,
+    IonLabel,
+    IonItem,
+    IonList,
+    IonAvatar,
+    CommonModule,
+    IonButton,
+    IonSegment,
+    IonSegmentButton,
+    IonSegmentContent,
+    IonSegmentView,
+    IonCardContent,
+    IonCardTitle,
+    IonCardHeader,
+    IonCard,
+    IonModal,
+    IonIcon,
+    IonButtons,
+    IonInput,
+    IonRefresher,
+    IonRefresherContent,
+    IonSpinner,
+    IonGrid,        // 添加 IonGrid 到 imports
+    IonRow,         // 添加 IonRow 到 imports
+    IonCol          // 添加 IonCol 到 imports
+    // FmMarkdownPreview,
   ]
 })
-export class PageMyHealthComponent  implements OnInit {
+export class PageMyHealthComponent implements OnInit {
+  allMessage: Array<CloudObject> = [];
+  isLoading: boolean = false;
+  errorMessage: string = "";
+
+  avatar: string = "../assets/imgs/avatar.png"; // 默认头像
+  currentUser: CloudUser | undefined;
+  objectId: string = "";
+  userName: string = "";
+
+  back: string = "back";
+
+  // 备用头像 URL
+  fallbackAvatarUrl: string = 'https://app.fmode.cn/dev/jxnu/202226701019/头像示例.png';
 
   constructor(
-    private router: Router
-  ) { }
+    private router: Router,
+    private loadingController: LoadingController
+  ) {
+    this.currentUser = new CloudUser();
+    this.avatar = this.currentUser.data["avatar"] || this.fallbackAvatarUrl;
+    this.objectId = this.currentUser.data['objectId'];
+    this.userName = this.currentUser.data["realname"] || "用户";
+  }
+
+  ngOnInit() {
+    this.loadData();
+  }
+
+  async loadData() {
+    this.isLoading = true;
+    const loading = await this.loadingController.create({
+      message: '加载中...',
+    });
+    await loading.present();
+
+    try {
+      let user = new CloudUser();
+      console.log("objectId", this.objectId);
+      let query = new CloudQuery('Consultation');
+      query.include("doctor", "depart");
+      query.equalTo("user", { "__type": "Pointer", "className": "_User", "objectId": this.objectId });
 
-  ngOnInit() {}
-  /**
-   * 返回上一页
-   */
-  back:string = "<";
+      const messages = await query.find();
+      console.log("allMessage", messages);
 
-  backHome(){
+      this.allMessage = messages;
+    } catch (error) {
+      console.error("加载数据失败:", error);
+      this.errorMessage = "数据加载失败,请稍后再试。";
+    } finally {
+      this.isLoading = false;
+      await loading.dismiss();
+    }
+  }
+
+  handleRefresh(event: any) {
+    setTimeout(() => {
+      this.allMessage = [];
+      this.loadData().then(() => {
+        event.target.complete();
+      });
+    }, 2000);
+  }
+
+  backHome() {
     this.router.navigate(['/tabs/tab1']);
   }
-}
+
+  gotouser() {
+    // 用户相关逻辑
+  }
+
+  // 处理图片加载错误,设置备用图片
+  handleImageError() {
+    this.avatar = this.fallbackAvatarUrl;
+  }
+}

+ 0 - 7
wisdom-app/src/app/page/page-phone-inquiry/page-phone-inquiry.component.html

@@ -1,7 +0,0 @@
-<ion-header [translucent]="true">
-  <ion-toolbar class="searchbar">
-    <div>
-      <ion-button (click)="backhome()" color="primary" slot="start">{{back}}</ion-button>
-    </div>
-  </ion-toolbar>
-</ion-header>

+ 0 - 0
wisdom-app/src/app/page/page-phone-inquiry/page-phone-inquiry.component.scss


+ 0 - 26
wisdom-app/src/app/page/page-phone-inquiry/page-phone-inquiry.component.ts

@@ -1,26 +0,0 @@
-import { Component, OnInit } from '@angular/core';
-import { Router } from '@angular/router';
-import { IonButton, IonHeader, IonToolbar } from '@ionic/angular/standalone';
-
-@Component({
-  selector: 'page-phone-inquiry',
-  templateUrl: './page-phone-inquiry.component.html',
-  styleUrls: ['./page-phone-inquiry.component.scss'],
-  standalone: true,
-  imports:[
-    IonHeader,IonToolbar,IonButton,
-  ]
-})
-export class PagePhoneInquiryComponent  implements OnInit {
-
-  constructor(
-    private router: Router
-  ) { }
-
-  ngOnInit() {}
-  back:string = "<";
-  backhome(){
-    this.router.navigate(['/tabs/tab1']);
-  }
-
-}

+ 0 - 11
wisdom-app/src/app/page/page-smart-community/page-smart-community.component.html

@@ -1,11 +0,0 @@
-<ion-header [translucent]="true">
-  <ion-toolbar class="searchbar">
-    <div>
-      <ion-button (click)="backHome()" color="primary">{{back}}</ion-button>
-    </div>
-  </ion-toolbar>
-</ion-header>
-
-<p>
-  page-smart-community works!
-</p>

+ 0 - 0
wisdom-app/src/app/page/page-smart-community/page-smart-community.component.scss


+ 0 - 22
wisdom-app/src/app/page/page-smart-community/page-smart-community.component.spec.ts

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

+ 0 - 29
wisdom-app/src/app/page/page-smart-community/page-smart-community.component.ts

@@ -1,29 +0,0 @@
-import { Component, OnInit } from '@angular/core';
-import { Router } from '@angular/router';
-import { IonButton, IonHeader, IonToolbar } from '@ionic/angular/standalone';
-
-@Component({
-  selector: 'page-smart-community',
-  templateUrl: './page-smart-community.component.html',
-  styleUrls: ['./page-smart-community.component.scss'],
-  standalone: true,
-  imports:[
-    IonHeader,IonToolbar,IonButton
-  ]
-})
-export class PageSmartCommunityComponent  implements OnInit {
-
-  constructor(
-    private router: Router
-  ) { }
-
-  ngOnInit() {}
-  /**
-   * 返回上一页
-   */
-  back:string = "<";
-
-  backHome(){
-    this.router.navigate(['/tabs/tab1']);
-  }
-}

+ 20 - 16
wisdom-app/src/app/poem-picture/poem-picture.component.html

@@ -1,36 +1,40 @@
 <ion-header [translucent]="true">
-  <ion-toolbar>
-    <ion-title>
-      示例:古诗文意境生成{{imagineWork.progress || 0}}
-    </ion-title> 
+  <ion-toolbar class="custom-toolbar">
+    <ion-button slot="start" size="small" (click)="backHome()" color="primary">back</ion-button>
+    <ion-title class="custom-title">
+      个性化头像生成
+    </ion-title>
   </ion-toolbar>
 </ion-header>
 
 <ion-content [fullscreen]="true">
   <!-- 生成提示词 -->
-  <ion-textarea [value]="userPrompt" (ionInput)="promptInput($event)" placeholder="请输入古诗" autoGrow="true"></ion-textarea>
-  <ion-button (click)="createImage()" expand="block">生成意境</ion-button>
+  <ion-textarea [value]="userPrompt" (ionInput)="promptInput($event)" placeholder="请输入头像要求(示例:画风采用动漫风,一位长发飘飘的女孩抬头仰望着天空微笑。)" autoGrow="true"></ion-textarea>
+  <ion-button (click)="createImage()" expand="block" color="success" class="anniu">头像生成</ion-button>
   <!-- 意境画面提示词 -->
-   <div>
-    明月几时有,把酒问青天。不知天上宫阙,今夕是何年?
-   </div>
-  <div>
+  <div class="desc">
     {{PictureDescResult}}
   </div>
   <!-- 生成结果 -->
   @if(images.length) {
     @for(imageUrl of images;track imageUrl){
-      <img [src]="imageUrl" alt="" srcset="">
+      <img [src]="imageUrl || '../../assets/image/logo.png'" alt="" srcset="">
     }
+
+    <h3>图片地址:
+      <span class="copyable">{{images.join(', ')}}</span>
+    </h3>
+
   }
   <!-- 生成状态 -->
   @if(!images.length){
-    @if(imagineWork){
-      <h1>生成中</h1>
-    }
-    @if(!imagineWork){
-      <h1>未开始</h1>
+    <h2 style="display: grid; place-items: center;">欢迎使用头像生成器</h2>
+    @if(imagineWork.progress!=0){
+      <h1 style="display: grid; place-items: center;">生成中:{{imagineWork.progress}}</h1>
     }
+    <div style="display: grid; place-items: center;">
+      <img src="https://app.fmode.cn/dev/jxnu/202226701019/头像生成器.png">
+    </div>
   }
 
 </ion-content>

+ 93 - 0
wisdom-app/src/app/poem-picture/poem-picture.component.scss

@@ -0,0 +1,93 @@
+.custom-toolbar {
+    --background: rgba(255, 255, 255, 0.8); /* 使工具栏背景透明 */
+    display: flex; /* 使用 Flexbox 布局 */
+    justify-content: center; /* 水平居中 */
+    align-items: center; /* 垂直居中 */
+    padding: 0; /* 去掉默认内边距 */
+}
+
+.custom-title {
+    font-size: 1.3em; /* 字体大小 */
+    font-weight: bold; /* 加粗 */
+    color: #000000; 
+    text-align: center; /* 文字居中对齐 */
+    margin: 0; /* 去掉默认外边距 */
+    text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2); /* 添加文字阴影效果 */
+    /* 添加其他美化效果 */
+    font-family: "微软雅黑"; /* 自定义字体 */
+}
+
+/* 全局样式 */
+ion-content {
+    background-color: #7acbd9; /* 背景颜色 */
+    padding: 20px; /* 内边距 */
+    font-family: 'Arial', sans-serif; /* 字体 */
+  }
+  
+  /* 文本区域样式 */
+  ion-textarea {
+    border: 1px solid #55e788; /* ���框颜色 */
+    border-radius: 8px; /* 圆角 */
+    padding: 10px; /* 内边距 */
+    font-size: 16px; /* 字体大小 */
+    color: #333; /* 字体颜色 */
+    background-color: #fff; /* 背景颜色 */
+    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); /* 阴影效果 */
+  }
+  
+  /* 按钮样式 */
+  .anniu {
+    background-color: #6be2ea; /* 按钮背景颜色 */
+    color: white; /* 按钮文字颜色 */
+    border-radius: 8px; /* 圆角 */
+    font-size: 18px; /* 字体大小 */
+    padding: 10px; /* 内边距 */
+    transition: background-color 0.3s; /* 背景颜色过渡效果 */
+  }
+  
+  ion-button:hover {
+    background-color: #53d888; /* 悬停时的背景颜色 */
+  }
+  
+  /* 图片容器样式 */
+  img {
+    max-width: 100%; /* 最大宽度为100% */
+    height: auto; /* 高度自动 */
+    border-radius: 8px; /* 圆角 */
+    margin-top: 10px; /* 上边距 */
+  }
+  
+  /* 图片地址样式 */
+  h3 {
+    color: #555; /* 字体颜色 */
+    font-size: 14px; /* 字体大小 */
+    margin-top: 10px; /* 上边距 */
+  }
+  
+  /* 生成状态样式 */
+  h1 {
+    color: #333; /* 字体颜色 */
+    font-size: 24px; /* 字体大小 */
+    text-align: center; /* 居中对齐 */
+    margin-top: 20px; /* 上边距 */
+  }
+  
+  /* 意境画面提示词样式 */
+  .desc {
+    background-color: #8ceea6; /* 背景颜色 */
+    border: 1px solid #24e34e; /* 边框颜色 */
+    border-radius: 8px; /* 圆角 */
+    padding: 15px; /* 内边距 */
+    margin-top: 20px; /* 上边距 */
+    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); /* 阴影效果 */
+  }
+
+  .copyable {
+    user-select: text; /* 允许文本选择 */
+    background-color: #f9f9f9; /* 背景颜色 */
+    padding: 5px; /* 内边距 */
+    border: 1px solid #ccc; /* 边框 */
+    border-radius: 4px; /* 圆角 */
+    display: inline-block; /* 使其呈现为块级元素 */
+    cursor: text; /* 鼠标悬停时显示文本光标 */
+  }

+ 14 - 7
wisdom-app/src/app/poem-picture/poem-picture.component.ts

@@ -1,4 +1,5 @@
 import { Component, OnInit } from '@angular/core';
+import { Router } from '@angular/router';
 import { IonHeader, IonToolbar, IonTitle, IonContent } from '@ionic/angular/standalone';
 import { IonTextarea, IonButton,IonInput } from "@ionic/angular/standalone";
 import { DalleOptions, ImagineWork, FmodeChatCompletion } from 'fmode-ng';
@@ -31,14 +32,15 @@ export class PoemPictureComponent  implements OnInit {
   imagineWork:ImagineWork
   images:Array<string> = []
   constructor(
+    private router: Router
   ){
-    // 示例任务,自己生成图片后请存储新的ID
-    this.imagineWork = new ImagineWork("4mPR0IW1i5");
+    // 示例任务,自己生成图片后请存储新的ID 
+    this.imagineWork = new ImagineWork("");
     this.imagineWork.fetchTask().then(work=>{
       if(work){
         this.imagineWork.id = work.id
       }
-      this.images = this.imagineWork?.images || [];
+      this.images = this.imagineWork?.images || '../../assets/image/头像示例.png';
     })
   }
 
@@ -47,8 +49,8 @@ export class PoemPictureComponent  implements OnInit {
     this.imagineWork = new ImagineWork();
     if (this.userPrompt.length > 0){
     // 文本生成
-    let PromptTemplate = `您是一名专业的美术画家,请您根据下面提供的的内容,将其描述的画面、场景、人物、物品等用最简短的语言表达,直接写出画面,并且以中国的古风意境为主
-    诗文如下:
+    let PromptTemplate = `您是一名专业的图片设计师,擅长设计各类型适合作为头像的唯美图片,请您根据下面提供的需求内容,将其描述的画面、场景、人物、物品等用最简短的语言表达,直接写出画面,并且要贴合描述的画风为主
+    需求如下:
     ${this.userPrompt}
     `
     let completion = new FmodeChatCompletion([
@@ -62,7 +64,7 @@ export class PoemPictureComponent  implements OnInit {
       this.PictureDescResult = message.content
       if(message?.complete){ // 判断message为完成状态,则设置isComplete为完成
         // 图片生成
-        let PicturePrompt = `${this.PictureDescResult}\n风格:中国古风。画面不带任何文字。突出色彩。`
+        let PicturePrompt = `${this.PictureDescResult}\n风格:画面不带任何文字。人物为主体占据整个图片的3/4。正面特写。人物不可呈现怪异形态。不可出现分割。`
       let options:DalleOptions = {prompt:PicturePrompt}
       this.imagineWork?.draw(options).subscribe(work=>{
           console.log("imagineWork",work?.toJSON())
@@ -75,10 +77,15 @@ export class PoemPictureComponent  implements OnInit {
     })
   }
   else{
-    this.userPrompt = "请提供您想要描述的诗文内容,我将根据其意境为您创作一幅古风画面的简短描述。"
+    this.userPrompt = "请提供您理想头像的组成内容,我将根据其意境为您创作一幅画面的简短描述。"
   }
     
   }
+  back:string = "back"
+  backHome(){
+    this.router.navigate(['/tabs/tab4']);
+  }
+
   ngOnInit() {}
 
 }

+ 216 - 0
wisdom-app/src/app/tab1/schema.md

@@ -0,0 +1,216 @@
+## 时序图
+```plantuml
+@startuml
+title AI问诊服务时序图
+
+actor User as U
+participant AIDoctor as AD
+participant Department as D
+participant Consultation as C
+participant Prescription as P
+
+U -> U: 决定选择或创建AI医生
+alt 选择已有医生
+    U -> AD: 选择现有AI医生
+else 创建新医生
+    U -> AD: 输入医生属性信息创建新AI医生
+end
+U -> AD: 发起问诊,提供信息
+AD -> AD: 接收用户信息
+AD -> AD: 与用户对话
+AD -> P: 生成处方
+AD -> U: 返回对话结果及处方
+U -> C: 创建问诊记录实例,关联相关对象(自身、医生、科室等)
+C -> D: 获取科室信息(若需要完整记录科室情况)
+D -> C: 返回科室信息
+C -> C: 整合问诊信息(包含处方等)
+C -> C: 保存到数据库
+U -> C: 查询问诊记录(可按需指定查询条件)
+C -> U: 返回相应问诊记录
+@enduml
+```
+
+## 类图
+```plantuml
+@startuml
+class User {
+    - userId : int
+    + selectExistingDoctor() : AIDoctor
+    + createCustomDoctor(doctorInfo : Map<String, String>) : AIDoctor
+    + startConsultation(doctor : AIDoctor) : void
+    + viewConsultationRecords() : List<Consultation>
+}
+
+class AIDoctor {
+    - objectid : int
+    - avator : String
+    - name : String
+    - gender : String
+    - age : int
+    - title : String
+    - qualications : String
+    - desc : String
+    - depart : String
+    - specialty : String
+    - scrid : int
+    + haveConversation(userInfo : String) : String
+    + generatePrescription() : Prescription
+}
+
+class Department {
+    - objectid : int
+    - desc : String
+    - name : String
+    - srcid : int
+}
+
+class Consultation {
+    - objectid : int
+    - user : User
+    - content : String
+    - doctor : AIDoctor
+    - department : Department
+    - title : String
+    + saveToDatabase() : void
+    + queryFromDatabase(queryParams : Map<String, String>) : Consultation
+}
+
+class Prescription {
+    - prescriptionId : int
+    - medicineList : List<String>
+    - usageInstructions : String
+}
+
+User "1" --> "0..*" AIDoctor : selects/ creates
+User "1" --> "0..*" Consultation : initiates/ views
+AIDoctor "1" --> "1" Prescription : generates
+Consultation "1" --> "1" Prescription : contains
+Consultation "1" --> "1" Department : belongs to
+@enduml
+```
+
+# 状态图
+```plantuml
+@startuml
+[*] --> Initiated
+state Initiated {
+    [*] --> SelectingDoctor
+    SelectingDoctor : 用户决定选择已有或创建新AI医生
+    SelectingDoctor --> DoctorSelected : 完成医生选择
+}
+state DoctorSelected {
+    [*] --> ProvidingInfo
+    ProvidingInfo : 用户向选定医生提供问诊信息
+    ProvidingInfo --> ConversationInProgress : 医生开始对话交流
+}
+state ConversationInProgress {
+    [*] --> PrescriptionGenerated
+    PrescriptionGenerated : AI医生生成处方
+    PrescriptionGenerated --> ConversationFinished : 对话结束
+}
+state ConversationFinished {
+    [*] --> CreatingRecord
+    CreatingRecord : 创建问诊记录实例
+    CreatingRecord --> SavingRecord : 整合记录信息
+    SavingRecord --> RecordSaved : 保存到数据库
+    RecordSaved --> [*]
+}
+@enduml
+```
+- 在这个状态图中:
+[*] 表示初始状态和最终状态(即整个流程开始前的状态和流程完整结束后的状态)。
+从 Initiated 开始,代表问诊流程启动,首先进入 SelectingDoctor 状态,意味着用户要进行选择 AI 医生的操作,完成选择后进入 DoctorSelected 状态。
+在 DoctorSelected 状态下,用户接着要提供问诊信息,进入 ProvidingInfo 状态,随后 AI 医生开始与之对话,进入 ConversationInProgress 状态。
+当 AI 医生生成处方后,进入 PrescriptionGenerated 状态,对话结束后到达 ConversationFinished 状态。
+最后在 ConversationFinished 状态下依次进行创建问诊记录、整合信息并保存记录的操作,最终达到 RecordSaved 状态,表示整个问诊记录成功保存到数据库,流程结束返回初始的结束状态 [*] 。
+
+
+## 活动图
+```plantuml
+@startuml
+start
+:用户发起问诊;
+if (选择已有AI医生?) then (是)
+    :选择已有的AI医生;
+else (否)
+    :输入信息创建新的AI医生;
+endif
+:用户提供问诊信息;
+:AI医生接收信息并对话;
+:AI医生生成处方;
+:结束对话;
+:创建问诊记录实例;
+:关联用户、医生、科室等信息;
+:整合问诊记录内容(包含处方);
+:保存问诊记录到数据库;
+:用户查询问诊记录;
+stop
+@enduml
+```
+在这个活动图中:
+首先通过 “用户发起问诊” 活动开始整个流程。
+接着通过一个条件判断分支来决定是选择已有 AI 医生还是创建新的 AI 医生,根据用户的选择执行相应的活动。
+然后用户提供问诊信息后,AI 医生依次进行接收信息并对话、生成处方以及结束对话等活动。
+后续开展创建问诊记录实例,并关联相关的用户、医生、科室等重要信息,再整合包含处方在内的问诊记录内容,接着将其保存到数据库中。
+最后用户可以进行查询问诊记录的活动,整个流程结束。
+此活动图从比较宏观的角度展示了 AI 问诊服务中主要的活动以及它们之间的先后顺序和逻辑关系,
+
+```plantuml
+@startuml
+class "病人" {
+  - patientId: int
+  - name: string
+  - age: int
+  - contactInfo: string
+  + register()
+  + login()
+  + updateProfile()
+}
+
+class "问答记录" {
+  - qnaId: int
+  - patientId: int
+  - question: string
+  - answer: string
+  - timestamp: Date
+  + addQuestion()
+  + addAnswer()
+  + getQnAHistory()
+}
+
+class "诊断记录" {
+  - diagnosisId: int
+  - patientId: int
+  - diagnosisResult: string
+  - diagnosisDate: Date
+  + generateDiagnosis()
+  + compareDiagnosis()
+}
+
+class "智能诊断" {
+  - algorithmVersion: string
+  - accuracyRate: float
+  + performSmartDiagnosis()
+}
+
+class "普通AI诊断" {
+  - algorithmVersion: string
+  + performStandardDiagnosis()
+}
+
+class "管理员" {
+  - adminId: int
+  - username: string
+  - password: string
+  + manageUsers()
+  + manageDiagnoses()
+}
+
+"病人" -- "问答记录" : 1..*
+"病人" -- "诊断记录" : 1..*
+"诊断记录" <|-- "智能诊断"
+"诊断记录" <|-- "普通AI诊断"
+"管理员" -- "病人" : 管理
+"管理员" -- "诊断记录" : 管理
+@enduml
+```

+ 138 - 81
wisdom-app/src/app/tab1/tab1.page.html

@@ -12,19 +12,21 @@
         size="default" 
         (click)="search()">搜索</ion-button>
     </div>
+    
   </ion-toolbar>
 </ion-header>
 <!-- 内存不足 使用以下代码 -->
-<!-- set NODE_OPTIONS=--max_old_space_size=8192 -->
-<!-- node --max_old_space_size=8192 node_modules/@angular/cli/bin/ng serve -->
-
+<!-- set NODE_OPTIONS=--max_old_space_size=8192
+node --max_old_space_size=8192 node_modules/@angular/cli/bin/ng serve -->
+<!-- parse-dashboard --appId dev --masterKey devmk --serverURL http://dev.fmode.cn:1337/parse --appName DevServer -->
+<!-- 1234567890
+1234 -->
 <ion-content [fullscreen]="true">
-
-   <!-- 轮播图区域 -->
-  <div class="carousel-container">
+    <!-- 轮播图区域 -->
+    <div class="carousel-container" style="border-radius: 25px; margin: 5px auto;">
     <div class="carousel" [style.transform]="'translateX(-' + currentSlide * 100 + '%)'">
       <div class="slide" *ngFor="let image of images">
-        <img [src]="image" alt="轮播图">
+        <img [src]="image" alt="轮播图" height="100px" >
       </div>
     </div>
   
@@ -36,40 +38,39 @@
             [class.active]="i === currentSlide" 
             (click)="goToSlide(i)"></span>
     </div>
-  </div> 
-
-
-  <div class="inquery">
-    <div class="inquery-ai">
-      <ion-button color="light" size="large" (click)="goToPage1()">
-        <ion-list>
-          <ion-item>
-            <img src="../../assets/image/ai.png" alt="AI问诊">
-            <p>AI问诊</p>
-          </ion-item>
-        </ion-list>
-      </ion-button>
+  </div>
+  <div class="inquery" style="margin-top: 10px ; margin-bottom: 15px; display: flex; height: 120px;">
+    <div class="inquery-ai" style="margin-left:5px;width: 48%; background-color: rgb(255, 255, 255);border-radius: 10px; box-shadow: 2px 2px 2px 0px rgba(0, 0, 0, 0.163), -2px -2px 2px 0px rgba(0, 0, 0, 0.148);">
+      <div style="display: flex; margin: 0; padding: 0;">
+        <div (click)="goToPage1()" style="margin-left: 8px">
+          <!-- <img src="../../assets/image/ai.png" alt="AI问诊"> -->
+          <h1>AI问诊</h1>
+          <p style="margin: 0; font-size: 10px; color: grey">7X24小时 智能AI医生</p>
+          <p style="margin-top:5px; width:50px;color:white;background-color: rgba(214, 10, 10, 0.589); font-size: 8px;">不限次畅聊</p>
+        </div>
+        <div (click)="goToPage1()" style="margin-left: 2px; margin-top: 10px;">
+          <img src="https://app.fmode.cn/dev/jxnu/202226701019/ai.png" alt="AI问诊" height="95px">
+        </div>
+      </div>
     </div>
-    <div class="inquery-human">
-      <ion-button color="light" size="large" (click)="goToPage2()">
-        <ion-list>
-          <ion-item>
-            <img src="../../assets/image/askdoct.jpg" alt="找医生">
-            <p>找医生</p>
-          </ion-item>
-        </ion-list>
-      </ion-button>
+    <div style="width: 1%;"></div>
+    <div class="inquery-human" style="margin-left:0px;width: 48%; background-color: rgb(255, 255, 255);border-radius: 10px; box-shadow: 2px 2px 2px 0px rgba(0, 0, 0, 0.163), -2px -2px 2px 0px rgba(0, 0, 0, 0.148);">
+      <div style="display: flex;">
+        <div (click)="goToPage2()" style="margin-left: 8px">
+          <!-- <img src="../../assets/image/askdoct.jpg" alt="找医生"> -->
+          <h1>  找医生</h1>
+          <p style="margin-left: 0px; margin-top:5px; font-size: 10px; color: grey ">全国66万医生等你来选</p>
+        </div>
+        <div (click)="goToPage2()"  style="margin-left: 2px; margin-top: 10px;">
+          <img src="https://app.fmode.cn/dev/jxnu/202226701019/askdoct.jpg" alt="找医生" height="95px">
+        </div>
+      </div>
     </div>
   </div>
 
 
-  <!-- <ion-button expand="block" color="light" size="large" (click)="goToPicture()">
-    生成图片
-  </ion-button> -->
-
   <!-- 功能区 -->
-<div class="function-area">
-  <!-- 第一行功能按钮 -->
+<div class="function-area" style="border-radius: 20px; margin-left: 10px; margin-right: 10px;">
   <div class="function-row">
     <div class="function-item" *ngFor="let item of functionItems1" (click)="navigateTo(item.route)">
       <div class="icon">
@@ -78,61 +79,117 @@
       <div class="label">{{ item.label }}</div>
     </div>
   </div>
-
-  <!-- 第二行功能按钮 -->
-  <div class="function-row">
-    <div class="function-item" *ngFor="let item of functionItems2" (click)="navigateTo(item.route)">
-      <div class="icon">
-        <ion-icon [name]="item.icon"></ion-icon>
-      </div>
-      <div class="label">{{ item.label }}</div>
-    </div>
-  </div>
 </div>
 
-<!-- <div>
+<div class="aidoctor">
   <ion-card>
-    <ion-card-header>
-      <ion-card-title>权威医生</ion-card-title>
-      <ion-card-subtitle>医生简介</ion-card-subtitle>
+    <ion-card-header style="margin: 0; padding: 0;">
+      <!-- <ion-card-title>权威医生</ion-card-title> -->
+      <div class="mid-nav">
+        <div style="font-weight: bold; ">
+          <h1>AI医生</h1>
+        </div>
+        <div class="under_slide">
+          <ion-label (click)="goToViewAll()">查看全部</ion-label>
+          <ion-ripple-effect></ion-ripple-effect>
+          <ion-icon name="chevron-forward-outline"></ion-icon>
+        </div>
+      </div>
     </ion-card-header>
-    <ion-card-content>
+    <ion-card-content style="margin: 0; padding: 0;">
       <ion-list>
-        <ion-item *ngFor="let doctor of doctors" lines="none">
-          <ion-thumbnail slot="start">
-            <img [src]="doctor.image" [alt]="doctor.name" />
-          </ion-thumbnail>
-          <div class="doctor-info">
-            <h3>{{ doctor.name }}({{ doctor.age }}岁)</h3>
-            <p>{{ doctor.position }},{{ doctor.department }}</p>
-            <p>{{ doctor.hospital }}</p>
-          </div>
-        </ion-item>
+        <div style="display: flex; justify-content: space-between; margin: 0; padding: 0;">
+          <ion-item style="margin: 0; padding: 0;" (click)="openInquiry(doctor)" *ngFor="let doctor of doctorList" lines="none">
+            <div style="margin: 0; padding:0;">
+              <div style="margin:0; padding:0px;">
+                <img height="90px" [src]="doctor.get('avatar') || '../../assets/image/doctor7.png'" [alt]="doctor.get('name')" />
+              </div>
+              <div class="doctor-info" style="margin:0; padding:0px;">
+                <h4 style="text-align:center;margin:0; padding:0px;">{{ doctor.get('name') }}({{ doctor.get('age') }}岁)</h4>
+                <p style="text-align:center;margin:0; padding:0px;">{{ doctor.get('title') }}</p>
+                <p style="text-align:center;margin:0; padding:0px;">{{ doctor.get('depart')?.name }}</p>
+                <p style="width: 100%; margin:0; padding:0px;">飞码互联网医院</p>
+              </div>
+            </div>
+          </ion-item>
+        </div>
       </ion-list>
     </ion-card-content>
   </ion-card>
-</div> -->
+</div>
+<div class="clinic-container"  style=" margin:0px 10px;box-shadow: 2px 2px 2px 0px rgba(0, 0, 0, 0.163), -2px -2px 2px 0px rgba(0, 0, 0, 0.148);">
+  <div class="clinic-header">
+    <h2>{{title}}</h2>
+    <p>{{subtitle}}</p>
+  </div>
+  
+  <div class="ads-container">
+    <div class="ad-card" *ngFor="let ad of clinicAds" [style.background-color]="ad.backgroundColor">
+      <div class="ad-content">
+        <div class="text-content">
+          <h3>{{ad.title}}</h3>
+          <p *ngIf="ad.price" class="price">{{ad.price}}</p>
+          <p class="description">{{ad.description}}</p>
+          <ion-button fill="outline" size="small">
+            立即查看
+            <ion-icon name="chevron-forward-outline"></ion-icon>
+          </ion-button>
+        </div>
+        <div class="image-container">
+          <img [src]="ad.image" [alt]="ad.title">
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
+<div class="service-container"  style=" margin:5px 10px;box-shadow: 2px 2px 2px 0px rgba(0, 0, 0, 0.163), -2px -2px 2px 0px rgba(0, 0, 0, 0.148);">
+  <div class="service-header">
+    <div class="title-section">
+      <h2>{{title1}}</h2>
+      <p>{{subtitle1}}</p>
+    </div>
+    <ion-button fill="clear" size="small">
+      查看更多 <ion-icon name="chevron-forward-outline"></ion-icon>
+    </ion-button>
+  </div>
 
-<div>
-  <ion-card>
-    <ion-card-header>
-      <ion-card-title>权威医生</ion-card-title>
-      <ion-card-subtitle>医生简介</ion-card-subtitle>
-    </ion-card-header>
-    <ion-card-content>
-      <ion-list>
-        <ion-item (click)="openInquiry(doctor)" *ngFor="let doctor of doctorList" lines="none">
-          <ion-thumbnail slot="start">
-            <img [src]="doctor.get('avatar') || '../../assets/image/doctor7.png'" [alt]="doctor.get('name')" />
-          </ion-thumbnail>
-          <div class="doctor-info">
-            <h3>{{ doctor.get('name') }}({{ doctor.get('age') }}岁)</h3>
-            <p>{{ doctor.get('title') }},{{ doctor.get('depart')?.name }}</p>
-            <p>飞码互联网医院</p>
+  <div class="service-grid">
+    <!-- 大卡片区域 -->
+    <div class="large-cards">
+      <div class="service-card large" 
+           *ngFor="let service of services | slice:0:2"
+           [style.background-color]="service.backgroundColor">
+        <div class="card-content">
+          <div class="text-content">
+            <h3>{{service.title}}</h3>
+            <p>{{service.description}}</p>
+            <ion-button *ngIf="service.hasDetail" fill="outline" size="small">
+              查看详情
+            </ion-button>
           </div>
-        </ion-item>
-      </ion-list>
-    </ion-card-content>
-  </ion-card>
+          <div class="image-container">
+            <img [src]="service.image" [alt]="service.title">
+            <ion-badge *ngIf="service.isHot" color="danger">热门</ion-badge>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 小卡片网格 -->
+    <div class="small-cards">
+      <div class="service-card small" 
+           *ngFor="let service of services | slice:2">
+        <div class="card-content">
+          <div class="text-content">
+            <h3>{{service.title}}</h3>
+            <p>{{service.description}}</p>
+          </div>
+          <div class="image-container">
+            <img [src]="service.image" [alt]="service.title">
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
 </div>
 </ion-content>

+ 291 - 41
wisdom-app/src/app/tab1/tab1.page.scss

@@ -79,53 +79,74 @@
 
 
 
-.inquery{
-  width:100%;
-  height:100px;
-  // --background-color: #fd0000;
-  padding: 5px 0px;
-  box-sizing: border-box;
-  margin: 0px 0px;
-  ion-button{
-      width: 100%;
-      height: 100%;
-      display: inline-block;
-  }
-}
+// .inquery{
+//   width:100%;
+//   height:100px;
+//   // --background-color: #fd0000;
+//   padding: 5px 0px;
+//   box-sizing: border-box;
+//   margin: 0px 0px;
+//   ion-button{
+//       width: 100%;
+//       height: 100%;
+//       display: inline-block;
+//   }
+// }
 
-.inquery-ai{
-  height: 100%;
-  width: 48%;
-  display: inline-block;
-  margin: 0;
-  padding: 0;
-}
+// .inquery-ai{
+//   height: 100%;
+//   width: 48%;
+//   display: inline-block;
+//   margin: 0;
+//   padding: 0;
+// }
 
-.inquery-ai img{
-  width:50%;
-  height: 100%;
-  margin: 0;
-  padding: 0;
-  border-radius: 10px;
-  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
-}
+// .inquery-ai img{
+//   width:50%;
+//   height: 100%;
+//   margin: 0;
+//   padding: 0;
+//   border-radius: 10px;
+//   box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
+// }
+
+// .inquery-human{
+//   height: 100%;
+//   width: 48%;
+//   display: inline-block;
+//   margin-left: 2%;
+//   padding: 0;
+// }
+
+// .inquery-human img{
+//   width:50%;
+//   height: 100%;
+//   margin: 0;
+//   padding: 0;
+//   border-radius: 10px;
+//   box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
+// }
+
+.mid-nav {
+  display: flex;
+  justify-content: space-between;
+  margin-top: 5px;
+  margin-bottom: 5px;
+  margin-left: 15px;
+  margin-right: 15px;
 
-.inquery-human{
-  height: 100%;
-  width: 48%;
-  display: inline-block;
-  margin-left: 2%;
-  padding: 0;
 }
 
-.inquery-human img{
-  width:50%;
-  height: 100%;
-  margin: 0;
-  padding: 0;
-  border-radius: 10px;
-  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
+.under_slide {
+  display: flex;
+  align-items: center;
+  text-align: right;
+  font-size: smaller;
 }
+
+
+
+
 ion-item {
   margin-bottom: 12px; /* 增加医生卡片之间的间距 */
   padding: 12px; /* 调整卡片内边距 */
@@ -198,4 +219,233 @@ ion-thumbnail {
         color: #333;
       }
     }
+  }
+
+
+  // 
+  .clinic-container {
+    padding: 16px;
+    background: #fff;
+  }
+  
+  .clinic-header {
+    margin-bottom: 12px;
+    
+    h2 {
+      font-size: 16px;
+      font-weight: 500;
+      margin: 0 0 4px 0;
+    }
+    
+    p {
+      font-size: 12px;
+      color: #999;
+      margin: 0;
+    }
+  }
+  
+  .ads-container {
+    display: flex;
+    gap: 12px;
+  }
+  
+  .ad-card {
+    flex: 1;
+    border-radius: 8px;
+    padding: 12px;
+    
+    .ad-content {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+    }
+    
+    .text-content {
+      h3 {
+        font-size: 14px;
+        font-weight: 500;
+        margin: 0 0 4px 0;
+      }
+      
+      .price {
+        color: #FF6B6B;
+        font-size: 12px;
+        margin: 0 0 4px 0;
+      }
+      
+      .description {
+        color: #666;
+        font-size: 12px;
+        margin: 0 0 8px 0;
+      }
+      
+      ion-button {
+        --padding-start: 8px;
+        --padding-end: 8px;
+        --padding-top: 4px;
+        --padding-bottom: 4px;
+        height: 24px;
+        font-size: 12px;
+        
+        &::part(native) {
+          border-radius: 12px;
+        }
+      }
+    }
+    
+    .image-container {
+      width: 60px;
+      height: 60px;
+      overflow: hidden;
+      border-radius: 30px;
+      
+      img {
+        width: 100%;
+        height: 100%;
+        object-fit: cover;
+      }
+    }
+  }
+
+
+  //
+  .service-container {
+    padding: 16px;
+    background: #fff;
+  }
+  
+  .service-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: flex-start;
+    margin-bottom: 16px;
+  
+    .title-section {
+      h2 {
+        font-size: 16px;
+        font-weight: 500;
+        margin: 0 0 4px 0;
+      }
+  
+      p {
+        font-size: 12px;
+        color: #999;
+        margin: 0;
+      }
+    }
+  
+    ion-button {
+      --color: #999;
+      font-size: 12px;
+    }
+  }
+  
+  .service-grid {
+    display: flex;
+    flex-direction: column;
+    gap: 12px;
+  }
+  
+  .large-cards {
+    display: grid;
+    grid-template-columns: repeat(2, 1fr);
+    gap: 12px;
+  
+    .service-card {
+      border-radius: 12px;
+      padding: 16px;
+      height: 120px;
+  
+      .card-content {
+        display: flex;
+        height: 100%;
+        
+        .text-content {
+          flex: 1;
+          display: flex;
+          flex-direction: column;
+          justify-content: space-between;
+  
+          h3 {
+            font-size: 14px;
+            font-weight: 500;
+            margin: 0 0 4px 0;
+          }
+  
+          p {
+            font-size: 12px;
+            color: #666;
+            margin: 0 0 8px 0;
+          }
+  
+          ion-button {
+            --padding-start: 8px;
+            --padding-end: 8px;
+            height: 24px;
+            font-size: 12px;
+          }
+        }
+  
+        .image-container {
+          position: relative;
+          width: 60px;
+          
+          img {
+            width: 100%;
+            height: auto;
+          }
+  
+          ion-badge {
+            position: absolute;
+            top: 0;
+            right: 0;
+            font-size: 10px;
+          }
+        }
+      }
+    }
+  }
+  
+  .small-cards {
+    display: grid;
+    grid-template-columns: repeat(3, 1fr);
+    gap: 12px;
+  
+    .service-card {
+      background: #f5f5f5;
+      border-radius: 12px;
+      padding: 12px;
+      height: 100px;
+  
+      .card-content {
+        height: 100%;
+        display: flex;
+        flex-direction: column;
+        justify-content: space-between;
+  
+        .text-content {
+          h3 {
+            font-size: 14px;
+            font-weight: 500;
+            margin: 0 0 4px 0;
+          }
+  
+          p {
+            font-size: 12px;
+            color: #666;
+            margin: 0;
+          }
+        }
+  
+        .image-container {
+          text-align: right;
+          
+          img {
+            width: 40px;
+            height: 40px;
+            object-fit: cover;
+          }
+        }
+      }
+    }
   }

+ 166 - 60
wisdom-app/src/app/tab1/tab1.page.ts

@@ -1,5 +1,5 @@
 import { Component } from '@angular/core';
-import { IonCardHeader, IonHeader, IonToolbar, IonTitle, IonContent, IonTabButton, IonSearchbar, IonLabel, IonItem, IonList, NavController, IonCard, IonCardTitle, IonCardSubtitle, IonCardContent, IonThumbnail } from '@ionic/angular/standalone';
+import { IonCardHeader, IonHeader, IonToolbar, IonTitle, IonContent, IonTabButton, IonSearchbar, IonLabel, IonItem, IonList, NavController, IonCard, IonCardTitle, IonCardSubtitle, IonCardContent, IonThumbnail, IonRippleEffect, IonFab, IonFabList, IonFabButton, IonBadge } from '@ionic/angular/standalone';
 import { ExploreContainerComponent } from '../explore-container/explore-container.component';
 import { IonButton } from '@ionic/angular/standalone';
 import { IonIcon } from '@ionic/angular/standalone';
@@ -9,14 +9,35 @@ import { ModalController } from '@ionic/angular/standalone';
 import { HttpClient } from '@angular/common/http';
 import { addIcons } from 'ionicons';
 import { documentText, chatbubbles, person, calendar, newspaper,
-   medkit,clipboard, podium, videocam, people } from 'ionicons/icons';
+   medkit,clipboard, podium, videocam, people, chevronForwardOutline, 
+   add} from 'ionicons/icons';
 import { CloudObject, CloudQuery, CloudUser } from 'src/lib/ncloud';
 import { ChatPanelOptions, FmodeChat, FmodeChatMessage, openChatPanelModal } from 'fmode-ng';
-import { openUserLoginModal } from 'src/lib/user/modal-user-login/modal-user-login.component';
-import { ArticleCardComponent } from '../component/article-card/article-card.component';
 addIcons({ documentText, chatbubbles, person, calendar, newspaper,
-   medkit,clipboard, podium, videocam, people
+   medkit,clipboard, podium, videocam, people,add
  });
+ import { FmodeMapModule } from 'fmode-ng';
+
+ 
+interface ClinicAd {
+  id: number;
+  title: string;
+  price?: string;
+  description: string;
+  image: string;
+  backgroundColor: string;
+}
+
+interface ServiceItem {
+  id: number;
+  title: string;
+  description: string;
+  image: string;
+  hasDetail?: boolean;
+  isHot?: boolean;
+  backgroundColor?: string;
+  size?: 'large' | 'small';
+}
 @Component({
   selector: 'app-tab1',
   templateUrl: 'tab1.page.html',
@@ -25,17 +46,104 @@ addIcons({ documentText, chatbubbles, person, calendar, newspaper,
   imports: [
     IonHeader, IonToolbar, IonTitle, IonContent, ExploreContainerComponent, IonTabButton, IonButton,
     IonIcon,IonSearchbar,IonLabel,IonItem,IonList,CommonModule,IonCard,IonCardHeader,IonCardTitle,IonCardSubtitle,
-    IonCardContent, IonThumbnail, 
+    IonCardContent, IonThumbnail, IonRippleEffect, IonFab, IonFabButton, IonFabList,IonBadge
   ],
 })
 export class Tab1Page {
-
+  title1 = "特色服务";
+  subtitle1 = "一站式医疗健康解决方案";
+  
+  services: ServiceItem[] = [
+    {
+      id: 1,
+      title: "援脑妇科病",
+      description: "小症状隐藏大隐患",
+      image: "../../assets/image/doctor7.png",
+      hasDetail: true,
+      backgroundColor: "#E8F5F2",
+      size: 'large'
+    },
+    {
+      id: 2,
+      title: "解决口腔难题",
+      description: "享健康生活",
+      image: "../../assets/image/doctor7.png",
+      hasDetail: true,
+      isHot: true,
+      backgroundColor: "#E8F5F2",
+      size: 'large'
+    },
+    {
+      id: 3,
+      title: "解决皮肤难题",
+      description: "专业医生来助力",
+      image: "../../assets/image/doctor7.png",
+      size: 'small'
+    },
+    {
+      id: 4,
+      title: "儿科常见疾病",
+      description: "在家就能请专家",
+      image: "../../assets/image/doctor7.png",
+      size: 'small'
+    },
+    {
+      id: 5,
+      title: "赶走烦恼困扰",
+      description: "科学治疗好经不费",
+      image: "../../assets/image/doctor7.png",
+      size: 'small'
+    },
+    {
+      id: 6,
+      title: "知己心理",
+      description: "温暖地陪你懂自己",
+      image: "../../assets/image/doctor7.png",
+      size: 'small'
+    },
+    {
+      id: 7,
+      title: "搞定偏头痛",
+      description: "止疼彻底合集",
+      image: "../../assets/image/doctor7.png",
+      size: 'small'
+    },
+    {
+      id: 8,
+      title: "搞定偏头痛",
+      description: "止疼彻底合集",
+      image: "../../assets/image/doctor7.png",
+      size: 'small'
+    }
+  ];
+  title = "专科门诊";
+  subtitle = "智养高复诊率、高口碑名医";
+  
+  clinicAds: ClinicAd[] = [
+    {
+      id: 1,
+      title: "专业男科",
+      price: "18元起",
+      description: "阳痿早泄",
+      image: "../../assets/image/doctor7.png",
+      backgroundColor: "#EEF4FF"
+    },
+    {
+      id: 2,
+      title: "智养中医馆",
+      price: "18元起",
+      description: "口碑中医",
+      image: "../../assets/image/doctor6.png",
+      backgroundColor: "#FFF5EB"
+    }
+  ];
   constructor(
     private router: Router,
     private modalCtrl: ModalController,
     // private navCtrl: NavController,
     private http: HttpClient // 注入 HttpClient
-  ) {}
+  ) {
+      addIcons({chevronForwardOutline});}
 
  /**
   * 轮播图
@@ -43,7 +151,10 @@ export class Tab1Page {
   images = [
     'https://picsum.photos/800/400?random=1',
     'https://picsum.photos/800/400?random=2',
-    'https://picsum.photos/800/400?random=3'
+    'https://picsum.photos/800/400?random=3',
+    'https://picsum.photos/800/400?random=4',
+    'https://picsum.photos/800/400?random=5',
+    'https://picsum.photos/800/400?random=6',
   ];
   currentSlide = 0;
   intervalId: any;
@@ -78,6 +189,11 @@ export class Tab1Page {
    */
   goToPage1(){
     console.log(['route'])
+    let user = new CloudUser;
+    if (!user.id){
+      this.router.navigate(['/tabs/tab4'])
+      return
+    }
     this.router.navigate(['/tabs/inquiry/ai'])
   }
 
@@ -85,6 +201,11 @@ export class Tab1Page {
    * Go to the human page
    */
   goToPage2(){
+    let user = new CloudUser;
+    if (!user.id){
+      this.router.navigate(['/tabs/tab4'])
+      return
+    }
     this.router.navigate(['/tabs/inquiry/human'])
   }
 
@@ -111,51 +232,19 @@ export class Tab1Page {
 
   // 功能按钮数据
   functionItems1 = [
-    { label: '我的健康', icon: 'document-text', route: '/tabs/my-health' },
-    { label: '健康档案', icon: 'person', route: '/tabs/health-records' },
-    { label: '电话问诊', icon: 'calendar', route: '/tabs/phone-inquiry' },
-    { label: '购买药品', icon: 'medkit', route: '/tabs/drug-purchase' },
-  ];
-
-  functionItems2 = [
-    { label: '专业男科', icon: 'clipboard', route: '/tabs/tab1' },
-    { label: '权威专家', icon: 'podium', route: '/tabs/authority-experts' },
-    { label: '健康资讯', icon: 'newspaper', route: '/tabs/health-information' },
-    { label: '智慧社区', icon: 'people', route: '/tabs/smart-community' }
-  ];
-
-  doctors = [
-    {
-      name: '余海涛',
-      age: 20,
-      position: '主任医师',
-      department: '中医草药科',
-      hospital: '南昌市江西师范医院',
-      desc:'中医大师,擅长用中药调养身体来根治病症',
-      image: '../../assets/image/doctor5.png',
-    },
-    {
-      name: '聂翼伏',
-      age: 25,
-      position: '副主任医师',
-      department: '骨科',
-      hospital: 'YY市人民医院',
-      desc:'骨科专家,擅长治疗各种骨骼损伤症状',
-      image: '../../assets/image/doctor7.png',
-    },
-    {
-      name: '徐君豪',
-      age: 28,
-      position: '主治医师',
-      department: '心理科',
-      hospital: 'XX市第一医院',
-      desc:'心理专家,擅长解决各类心理问题和疾病',
-      image: '../../assets/image/doctor6.png',
-    },
+    { label: '专属医生', icon: 'document-text', route: '/tabs/create-agent' },
+    { label: '我的健康', icon: 'person', route: '/tabs/my-health' },
+    { label: '药品展示', icon: 'calendar', route: '/tabs/tab3' },
+    { label: '健康科普', icon: 'medkit', route: '/tabs/tab2' },
   ];
 
   // 导航到指定路由
   navigateTo(route: string) {
+    let user = new CloudUser;
+    if (!user.id){
+      this.router.navigate(['/tabs/tab4'])
+      return
+    }
     this.router.navigate([route]);
     console.log("route: ",route)
   }
@@ -169,10 +258,17 @@ export class Tab1Page {
   async loadDoctorList(){
     let query = new CloudQuery("Doctor");
     query.include("depart")
-    this.doctorList = await query.find()
+    let List = await query.find()
+    for(let i = 0; i < 3; i++) {
+      this.doctorList.push(List[i])
+    }
   }
-
-
+  goToViewAll(){
+    console.log(['route'])
+    this.router.navigate(['/tabs/inquiry/ai'])
+  }
+  
+  currentUser:CloudUser|undefined
    /** 示例:问诊根据doctor拼接提示词 */
    async openInquiry(doctor:any){
     // 验证用户登录
@@ -180,13 +276,15 @@ export class Tab1Page {
     let userPrompt = ``
     if(!currentUser?.id){
       console.log("用户未登录,请登录后重试");
-      let user = await openUserLoginModal(this.modalCtrl);
-      if(!user?.id){
-        return
-      }
-      currentUser = user;
+      // let user = await openUserLoginModal(this.modalCtrl);
+      // if(!user?.id){
+      //   return
+      // }
+      // currentUser = user;
+      this.router.navigate(['/tabs/tab4'])
+      return 
     }
-    
+    console.log("currentUser: ",currentUser)
     if(currentUser?.get("realname")){
       userPrompt += `当前来访的患者,姓名:${currentUser?.get("realname")}`
     }
@@ -252,7 +350,7 @@ export class Tab1Page {
 - 完成处方时,请在消息结尾附带: [处方完成]
 
 # 开始话语
-当您准备好了,可以以一个医生的身份,向来访的用户打招呼。
+当您准备好了,可以以一个医生的身份,向来访的用户亲切地打招呼。
 ${userPrompt}
 `);
       },
@@ -268,12 +366,20 @@ ${userPrompt}
             consult.save();
           }
         }
+
       },
       onChatSaved:(chat:FmodeChat)=>{
         // chat?.chatSession?.id 本次会话的 chatId
         console.log("onChatSaved",chat,chat?.chatSession,chat?.chatSession?.id)
+        // consult.set({
+        //   chatId:chat?.chatSession?.id
+        // })
+        console.log("chat.MessageList", chat?.messageList)
       }
     }
     openChatPanelModal(this.modalCtrl,options)
   }
+  addNew(){
+    this.router.navigate(["/tabs/create-agent"]);
+  }
 }

+ 197 - 43
wisdom-app/src/app/tab2/tab2.page.html

@@ -1,17 +1,14 @@
 <ion-header [translucent]="true">
   <ion-toolbar class="custom-toolbar">
-    <ion-title class="custom-title">
-      健康科普
-    </ion-title>
-  </ion-toolbar>
-</ion-header>
-
-<ion-content class="knowledge" [fullscreen]="true">
-  <div class="search-bar">
-    <input type="text" placeholder="输入关键词搜索科普文章">
-  </div>
-  <div class="content">
-    <ion-card>
+    <div class="search-bar" >
+      <ion-searchbar 
+      placeholder="搜索" 
+      class="custom-searchbar" 
+      (ionInput)="searchProducts($event)">
+      </ion-searchbar>
+    </div>
+    @if(!searchTerm){
+    <div class="header">
       <ion-card-header>
         <ion-card-title>
           <ion-segment [scrollable]="true" value="hotdot" [value]="type" (ionChange)="typeChange($event)">
@@ -27,47 +24,204 @@
             <ion-segment-button value="life" content-id="life">
               <ion-label>生活</ion-label>
             </ion-segment-button>
-            <ion-segment-button value="male" content-id="male">
+            <ion-segment-button value="" content-id="male">
               <ion-label>男性</ion-label>
             </ion-segment-button>
-            <ion-segment-button value="female" content-id="female">
+            <ion-segment-button value="" content-id="female">
               <ion-label>女性</ion-label>
             </ion-segment-button>
           </ion-segment>
         </ion-card-title>
-        <!-- <ion-card-subtitle>请输入账号密码</ion-card-subtitle> -->
       </ion-card-header>
+    </div>
+  }
+  </ion-toolbar>
+</ion-header>
+
+<ion-content class="knowledge" [fullscreen]="true">
+  @if(!searchTerm){
     
-      <ion-card-content>
-        <ion-segment-view>
-          <ion-segment-content id="hotdot">
-            <app-article-card *ngFor="let card of cards" [card]="card"></app-article-card>
-          </ion-segment-content>
+    <div class="content">
+      <ion-card>
+        <ion-card-header></ion-card-header>
+  
+        <ion-card-content>
+          <ion-segment-view>
+            <ion-segment-content id="hotdot">
+              <!-- 轮播图区域 -->
+              <div class="carousel-container" style="border-radius: 0px; margin: 0px auto;">
+                <div class="carousel" [style.transform]="'translateX(-' + currentSlide * 100 + '%)'">
+                  <div class="slide" *ngFor="let image of images">
+                    <img [src]="image" alt="轮播图" height="100px" >
+                  </div>
+                </div>
+              
+                <button class="prev" (click)="prevSlide()">&#10094;</button>
+                <button class="next" (click)="nextSlide()">&#10095;</button>
+              
+                <div class="dots">
+                  <span class="dot" *ngFor="let image of images; let i = index" 
+                        [class.active]="i === currentSlide" 
+                        (click)="goToSlide(i)"></span>
+                </div>
+              </div>
+              <app-article-card (click)="openDetailModal(card)" *ngFor="let card of cards" [card]="card"></app-article-card>
+            </ion-segment-content>
+  
+            <ion-segment-content id="export">
+              <app-article-card (click)="openDetailModal(card)" *ngFor="let card of cards" [card]="card"></app-article-card>
+            </ion-segment-content>
+  
+            <ion-segment-content id="sleep">
+              <!-- 轮播图区域 -->
+              <div class="carousel-container" style="border-radius: 0px; margin: 0px auto;">
+                <div class="carousel" [style.transform]="'translateX(-' + currentSlide * 100 + '%)'">
+                  <div class="slide" *ngFor="let image of images">
+                    <img [src]="image" alt="轮播图" height="100px" >
+                  </div>
+                </div>
+              
+                <button class="prev" (click)="prevSlide()">&#10094;</button>
+                <button class="next" (click)="nextSlide()">&#10095;</button>
+              
+                <div class="dots">
+                  <span class="dot" *ngFor="let image of images; let i = index" 
+                        [class.active]="i === currentSlide" 
+                        (click)="goToSlide(i)"></span>
+                </div>
+              </div>
+              <app-article-card (click)="openDetailModal(card)" *ngFor="let card of cards" [card]="card"></app-article-card>
+            </ion-segment-content>
+  
+            <ion-segment-content id="life">
+              <app-article-card (click)="openDetailModal(card)" *ngFor="let card of cards" [card]="card"></app-article-card>
+            </ion-segment-content>
+            <ion-segment-content id="male">
+              <!-- 轮播图区域 -->
+              <div class="carousel-container" style="border-radius: 0px; margin: 0px auto;">
+                <div class="carousel" [style.transform]="'translateX(-' + currentSlide * 100 + '%)'">
+                  <div class="slide" *ngFor="let image of images">
+                    <img [src]="image" alt="轮播图" height="100px" >
+                  </div>
+                </div>
+              
+                <button class="prev" (click)="prevSlide()">&#10094;</button>
+                <button class="next" (click)="nextSlide()">&#10095;</button>
+              
+                <div class="dots">
+                  <span class="dot" *ngFor="let image of images; let i = index" 
+                        [class.active]="i === currentSlide" 
+                        (click)="goToSlide(i)"></span>
+                </div>
+              </div>
+              <app-article-card (click)="openDetailModal(card)" *ngFor="let card of cards" [card]="card"></app-article-card>
+            </ion-segment-content>
+            <ion-segment-content id="female">
+              <!-- 轮播图区域 -->
+              <div class="carousel-container" style="border-radius: 0px; margin: 0px auto;">
+                <div class="carousel" [style.transform]="'translateX(-' + currentSlide * 100 + '%)'">
+                  <div class="slide" *ngFor="let image of images">
+                    <img [src]="image" alt="轮播图" height="100px" >
+                  </div>
+                </div>
+              
+                <button class="prev" (click)="prevSlide()">&#10094;</button>
+                <button class="next" (click)="nextSlide()">&#10095;</button>
+              
+                <div class="dots">
+                  <span class="dot" *ngFor="let image of images; let i = index" 
+                        [class.active]="i === currentSlide" 
+                        (click)="goToSlide(i)"></span>
+                </div>
+              </div>
+              <app-article-card (click)="openDetailModal(card)" *ngFor="let card of cards" [card]="card"></app-article-card>
+            </ion-segment-content>
+          </ion-segment-view>
+        </ion-card-content>
+      </ion-card>
+    </div>
+  }
+  @if(searchTerm){
+    <div>
+      <app-article-card (click)="openDetailModal(product)" *ngFor="let product of products" [card]="product"></app-article-card>
+    </div>
+    @if (products.length == 0) {
+      <div class="no-results" style="margin: 50px auto;">
+        <h2>寻找中···   请耐性等待 ····</h2>
+      </div>
+    }
+  }
 
-          <ion-segment-content id="export">
-            <app-article-card *ngFor="let card of cards" [card]="card"></app-article-card>
-          </ion-segment-content>
 
-          <ion-segment-content id="sleep">
-            <app-article-card *ngFor="let card of cards" [card]="card"></app-article-card>
-          </ion-segment-content>
-          
-          <ion-segment-content id="life">
-            <app-article-card *ngFor="let card of cards" [card]="card"></app-article-card>
-          </ion-segment-content>
-          <ion-segment-content id="male">
-            <app-article-card *ngFor="let card of cards" [card]="card"></app-article-card>
-          </ion-segment-content>
-          <ion-segment-content id="female">
-            <app-article-card *ngFor="let card of cards" [card]="card"></app-article-card>
-          </ion-segment-content>
-        </ion-segment-view>
-      </ion-card-content>
-    </ion-card>
-  </div>
+  <!-- 底部弹出模态 -->
+  <ion-modal [isOpen]="isModalOpen" cssClass="bottom-modal">
+    <ng-template>
 
-  <div class="knowledge-cards">
-      
-  </div>
+      <ion-header>
+        <ion-toolbar>
+          <ion-buttons slot="start">
+            <ion-button (click)="closeDetailModal()">关闭</ion-button>
+          </ion-buttons>
+          <ion-title>{{currentProduct.get('category')}}</ion-title>
+          <ion-buttons slot="end">
+            <ion-button (click)="shareDetailModal()">分享</ion-button>
+          </ion-buttons>
+        </ion-toolbar>
+      </ion-header>
 
+      <ion-content class="ion-padding">
+        <div class="modal-content" *ngIf="currentProduct">
+          <h1 class="product-name">{{currentProduct.get('title')}}</h1>
+          <p><strong>作者:</strong>{{currentProduct.get('author')}}</p>
+          <p>{{currentProduct.get('content')[0]}}</p>
+          <div class="image-container">
+            <img style="width: 100%; height: auto;" [src]="currentProduct.get('image')[0]" alt="图片" class="medicine-image">
+          </div>
+          <p>{{currentProduct.get('content')[0]}}</p>  
+          <div class="image-container">
+            <img style="width: 100%; height: auto;" [src]="currentProduct.get('image')[0]" alt="图片" class="medicine-image">
+          </div>
+          <div style="display: flex; height: 30px; width: 100%; justify-content: space-between; align-items: center">
+            <p style="margin-left:30px"><strong>阅读量:</strong>{{currentProduct.get('views')}}</p>
+            <p style="margin-right:30px"><strong>点赞量:</strong>{{currentProduct.get('likes')}}</p>  
+          </div>
+        </div>
+      </ion-content>
+      <ion-footer>
+        <ion-item>
+          <!-- <ion-label position="stacked">评论</ion-label> -->
+          <ion-input [value]="comment" (ionInput)="onCommentInput($event)" placeholder="请输入评论"></ion-input>
+          <ion-button (click)="postComment()">发布</ion-button>
+        </ion-item>
+        
+      </ion-footer>
+    </ng-template>
+  </ion-modal>
+
+  <ion-modal class="share-modal" [isOpen]="shareDetail">
+      <ion-header>
+        <ion-toolbar>
+          <ion-buttons slot="end">
+            <ion-button (click)="closeDetailModal()">X</ion-button>
+          </ion-buttons>
+          <ion-title>分享</ion-title>
+        </ion-toolbar>
+      </ion-header>
+      <ion-content>
+        <ion-item>
+          <ion-label position="stacked">分享链接</ion-label>
+          <!-- <ion-input [(ngModel)]="shareLink" readonly></ion-input> -->
+        </ion-item>
+        <ion-button expand="block" (click)="copyLink()">复制链接</ion-button>
+    </ion-content>
+    <!-- 评论 -->
+    <ion-footer>
+      <ion-item>
+        <!-- <ion-label position="stacked">评论</ion-label> -->
+        <ion-input [value]="comment" (ionInput)="onCommentInput($event)" placeholder="请输入评论"></ion-input>
+        <ion-button (click)="postComment()">发布</ion-button>
+      </ion-item>
+      
+    </ion-footer>
+  </ion-modal>
 </ion-content>

+ 121 - 28
wisdom-app/src/app/tab2/tab2.page.scss

@@ -6,34 +6,37 @@
   padding: 0; /* 去掉默认内边距 */
 }
 
-.custom-title {
-  font-size: 1.3em; /* 字体大小 */
-  font-weight: bold; /* 加粗 */
-  color: #000000; 
-  text-align: center; /* 文字居中对齐 */
-  margin: 0; /* 去掉默认外边距 */
-  text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2); /* 添加文字阴影效果 */
-  /* 添加其他美化效果 */
-  font-family: "微软雅黑"; /* 自定义字体 */
-}
 
 .search-bar {
     padding: 10px;
     text-align: center;
   }
   
-.search-bar input {
-  width: 80%;
-  padding: 8px;
-  border: 1px solid #ccc;
-  border-radius: 4px;
+.custom-searchbar {
+  --background: #ffffff;
+  --border-radius: 20px;
+  box-shadow: 0 2px 6px rgba(0,0,0,0.1);
 }
-.content {
-  margin-top: -10px;
+
+.header {
+  height: 80px;
+  margin-top:-10px
+}
+.knowledge {
   height: 100%;
   width: 100%;
 }
 
+.content {
+  margin-top: -5px;
+  -height: 100%;
+  width: 100%;
+}
+ion-card-header {
+  font-size: 1.5em;
+  height: auto;
+}
+
 ion-card {
   width: 100%;
   height: 100%;
@@ -42,10 +45,7 @@ ion-card {
   border-radius: 0;
   box-shadow: none;
 }
-ion-card-header {
-  font-size: 1.5em;
-  height: auto;
-}
+
 
 ion-card-content {
   font-size: 1.2em;
@@ -64,14 +64,42 @@ ion-segment-content {
   justify-content: center;
 }
 
-ion-segment-content:nth-of-type(5) {
-  background: lightpink;
-}
-ion-segment-content:nth-of-type(2) {
-  background: lightblue;
+// ion-segment-content:nth-of-type(5) {
+//   background: lightpink;
+// }
+// ion-segment-content:nth-of-type(2) {
+//   background: lightblue;
+// }
+// ion-segment-content:nth-of-type(3) {
+//   background: lightgreen;
+// }
+
+.share-modal{
+  --height: 30vh;
+  --width: 100%;
+  --offset-y: 0; /* 确保模态窗口从底部弹出 */
 }
-ion-segment-content:nth-of-type(3) {
-  background: lightgreen;
+// 底部弹窗(modal)样式
+.bottom-modal {
+  --height: 100vh;
+  --width: 100%;
+  --offset-y: 0; /* 确保模态窗口从底部弹出 */
+  
+  .modal-content {
+    padding-left: 20px;
+    padding-right: 20px;
+  }
+  
+  .image-container {
+    display: flex;
+    justify-content: center;
+    margin-bottom: 16px;
+  }
+  
+  .medicine-image {
+    object-fit: cover;
+    border-radius: 8px;
+  }
 }
 
 
@@ -90,6 +118,7 @@ ion-segment-content:nth-of-type(3) {
 
 
 
+
 // .tabs {
 //   display: flex;
 //   justify-content: space-around;
@@ -120,4 +149,68 @@ ion-segment-content:nth-of-type(3) {
 //   background-color: rgb(255, 255, 255);
 // }
 
+//
+
+// 轮播图区域
+.carousel-container {
+  position: relative;
+  max-width: 800px;
+  margin: 0 auto;
+  overflow: hidden;
+}
+
+.carousel {
+  display: flex;
+  transition: transform 0.5s ease-in-out;
+}
+
+.slide {
+  min-width: 100%;
+}
+
+.slide img {
+  width: 100%;
+  height: auto;
+}
+
+.prev, .next {
+  position: absolute;
+  top: 50%;
+  transform: translateY(-50%);
+  background: rgba(0, 0, 0, 0.5);
+  color: white;
+  padding: 16px;
+  border: none;
+  cursor: pointer;
+}
+
+.prev {
+  left: 0;
+}
+
+.next {
+  right: 0;
+}
+
+.dots {
+  position: absolute;
+  bottom: 20px;
+  left: 50%;
+  transform: translateX(-50%);
+  text-align: center;
+}
+
+.dot {
+  display: inline-block;
+  width: 10px;
+  height: 10px;
+  margin: 0 5px;
+  background: #bbb;
+  border-radius: 50%;
+  cursor: pointer;
+}
+
+.dot.active {
+  background: #717171;
+} 
 //

+ 140 - 44
wisdom-app/src/app/tab2/tab2.page.ts

@@ -1,73 +1,169 @@
-import { Component, NgModule } from '@angular/core';
-import { IonHeader, IonToolbar, IonTitle, IonContent, IonList, IonItem, IonLabel, IonAvatar, IonButton, IonSegment, IonSegmentButton, IonSegmentContent, IonSegmentView, IonCardContent, IonCardTitle, IonCardHeader, IonCard } from '@ionic/angular/standalone';
+import { Component } from '@angular/core';
+import { ModalController, IonModal, IonHeader, IonToolbar, IonTitle, IonContent, IonList, IonItem, IonLabel, IonAvatar, IonButton, IonSegment, IonSegmentButton, IonSegmentContent, IonSegmentView, IonCardContent, IonCardTitle, IonCardHeader, IonCard, IonIcon, IonButtons, IonSearchbar, IonFab, IonFabButton, IonFabList, IonFooter, IonInput } from '@ionic/angular/standalone';
 import { ExploreContainerComponent } from '../explore-container/explore-container.component';
 import { addIcons } from 'ionicons';
 import { airplane, bluetooth, call, wifi } from 'ionicons/icons';
-import { IonicModule, ModalController } from '@ionic/angular';
 import { ArticleCardComponent } from '../component/article-card/article-card.component';
 import { CommonModule } from '@angular/common';
-import { CloudObject, CloudQuery } from 'src/lib/ncloud';
-import { FormsModule } from '@angular/forms';
+import { CloudObject, CloudQuery, CloudUser } from 'src/lib/ncloud';
 import { NavigationLanComponent } from '../component/navigation-lan/navigation-lan.component';
+import { Router } from '@angular/router';
+import {
+  chevronDownCircle,
+  chevronForwardCircle,
+  chevronUpCircle,
+  colorPalette,
+  document,
+  globe,
+} from 'ionicons/icons';
 addIcons({ airplane, bluetooth, call, wifi });
-
-interface Article {
-  image: string;
-  title: string;
-  category: string;
-  date: string;
-  views: number;
-  likes: number;
-}
-
+addIcons({ chevronDownCircle, chevronForwardCircle, chevronUpCircle, colorPalette, document, globe });
 @Component({
   selector: 'app-tab2',
   templateUrl: 'tab2.page.html',
   styleUrls: ['tab2.page.scss'],
   standalone: true,
-  imports: [IonHeader, IonToolbar, IonTitle, IonContent, ExploreContainerComponent,
+  imports: [
+    IonHeader, IonToolbar, IonTitle, IonContent, ExploreContainerComponent,
     IonLabel,IonItem,IonList,IonAvatar,ArticleCardComponent,CommonModule,IonButton,
     IonSegment, IonSegmentButton,NavigationLanComponent,
-    IonSegmentContent,IonSegmentView,IonCardContent, IonCardTitle, IonCardHeader,IonCard
+    IonSegmentContent,IonSegmentView,IonCardContent, IonCardTitle, IonCardHeader,IonCard,
+    IonModal,IonIcon, IonButtons, IonSearchbar, IonFab, IonFabButton,IonFabList,IonFooter,
+    IonInput
   ]
 })
 
 export class Tab2Page {
+  
+ /**
+  * 轮播图
+  */
+ images = [
+  'https://picsum.photos/800/400?random=7',
+  'https://picsum.photos/800/400?random=8',
+  'https://picsum.photos/800/400?random=9',
+  'https://picsum.photos/800/400?random10',
+  'https://picsum.photos/800/400?random=11',
+  'https://picsum.photos/800/400?random=12',
+];
 
-  type:"hotdot"|"export"|"sleep"|"lift"|"male"|"female" = "hotdot"
-  typeChange(ev:any){
-    this.type = ev?.detail?.value || ev?.value || 'hotdot'
-    console.log(this.type)
-  }
-  // constructor(private modalCtrl:ModalController) { }
-  constructor() { }
-  cards: Array<CloudObject> = [];
-  async loadCards() {
-    let query = new CloudQuery('HotDot');
-    // query.equalTo('category', 'HotDot');
-    // query.greaterThan('views', 1000); // 查询 views 大于 1000 的文章
-    if (this.type == 'hotdot') {
+currentSlide = 0;
+intervalId: any;
+setSlidePosition() {
+  // 这里不需要额外的逻辑,因为在 HTML 中已经通过绑定实现
+}
 
-    }
-    if (this.type == 'hotdot') {
+nextSlide() {
+  this.currentSlide = (this.currentSlide + 1) % this.images.length;
+}
 
-    }
-    if (this.type == 'hotdot') {
+prevSlide() {
+  this.currentSlide = (this.currentSlide - 1 + this.images.length) % this.images.length;
+}
 
+goToSlide(index: number) {
+  this.currentSlide = index;
+}
+
+startAutoSlide() {
+  this.intervalId = setInterval(() => this.nextSlide(), 3000);
+}
+
+
+  products: Array<CloudObject> = []; // 当前显示的科普信息
+  allCards: Array<CloudObject> = []; // 所有科普信息
+
+  //搜索功能
+  searchTerm: string = '';
+
+  async searchProducts(event: any) {
+    this.searchTerm = event.detail.value.toLowerCase();
+    if (this.searchTerm) {
+      this.products = this.allCards.filter(product =>
+        product.get('topic').toLowerCase().includes(this.searchTerm) ||
+        product.get('title').toLowerCase().includes(this.searchTerm) ||
+        product.get('category').toLowerCase().includes(this.searchTerm) ||
+        product.get('content')[0].toLowerCase().includes(this.searchTerm)
+      );
+    } else {
+      this.products = [...this.allCards]; // 如果搜索词为空,则显示所有科普信息
     }
-    if (this.type == 'male') {
-      query.equalTo('category', 'MaleHealth')
-    }
-    if (this.type == 'female') {
-      query.equalTo("category", "FemaleHealth")
+  }
+
+  isModalOpen = false;
+  currentProduct: any;      // 当前选择的科普信息
+
+  openDetailModal(product?: any) {
+    let user = new CloudUser;
+    if (!user.id){
+      this.router.navigate(['/tabs/tab4'])
+      return
     }
-    // query.greaterThan('views', 1000); // 查询 views 大于 1000 的文章
-    this.cards = await query.find();
-    console.log(this.cards);
+    this.isModalOpen = true;
+    this.currentProduct = product;
   }
+  closeDetailModal() {
+    this.isModalOpen = false;
+    this.currentProduct = null;
+  }
+  shareDetail = false;
+  shareDetailModal() {
+    this.shareDetail = true;
+    // 在这里确保模态框的aria-hidden属性被正确处理
+    // setTimeout(() => {
+    //   const modalElement = document.querySelector('ion-modal');
+    //   if (modalElement) {
+    //     modalElement.setAttribute('aria-hidden', 'false');
+    //   }
+    // }, 0);
+  }
+  closeShareModal(){
+    this.shareDetail = false;
 
-  ngOnInit() {
-    this.loadCards();
   }
+  copyLink() {
+    console.log('复制链接');
+  }
+  type:"hotdot"|"export"|"sleep"|"life"|"男"|"女" = "hotdot"
+
+  constructor(
+    private modalCtrl:ModalController,
+    private router:Router,
+  ) { 
+    this.loadCards(); // 初始化时加载所有科普信息
+  }
+
+  cards: Array<CloudObject> = []; // 当前显示的分类卡片
+  async typeChange(ev: any) {
+    this.type = ev?.detail?.value || ev?.value || 'hotdot';
+    console.log(this.type);
+    await this.loadCards(); // 重新加载卡片
+  }
+
+  async loadCards() {
+    const query = new CloudQuery('HotDot');
+    this.allCards = await query.find(); // 执行查询并获取结果
+    this.cards = this.allCards.filter((card) => card.get('category').toLowerCase().includes(this.type));
+  }
+
+
+  publishHealthInfo() {
+    // 这里可以添加发布求医信息的逻辑
+    console.log('发布求医信息');
+  }
+
+  openAiKnowledge(){
+    this.router.navigate(['tabs/ai-knowledge']);
+  }
+  ngOnInit() {
 
+  }
+  comment:string = ''
+  onCommentInput(e:any){
+    this.comment = e.detail.value
+    console.log(this.comment);
+  }
+  postComment(){
+    console.log('发布评论');
+  }
 }

+ 137 - 36
wisdom-app/src/app/tab3/tab3.page.html

@@ -1,46 +1,147 @@
 <ion-header [translucent]="true">
   <ion-toolbar class="custom-toolbar">
     <ion-title class="custom-title">
-      药品商城
+      药品
     </ion-title>
   </ion-toolbar>
 </ion-header>
 
-<ion-content [fullscreen]="true">
-  <ion-searchbar placeholder="搜索"></ion-searchbar>
+<ion-content [fullscreen]="true" class="content-background">
+  <!-- 搜索栏 -->
+  <ion-searchbar 
+    placeholder="搜索" 
+    class="custom-searchbar" 
+    (ionInput)="searchProducts($event)">
+  </ion-searchbar>
 
-  <ion-grid>
-    <ion-row>
-      <ion-col size="2" *ngFor="let category of categories">
-        <ion-button fill="">
-          <div class="category-image-wrapper">
-            <img [src]="category.image" alt="{{ category.name }}" class="category-image">
-          </div>
-          <div class="category-name">{{ category.name }}</div>
-        </ion-button>
-      </ion-col>
-    </ion-row>
-  </ion-grid>
+  <!-- 分类区域(可横向滑动) -->
+  <div class="category-scroll">
+    <div class="category-scroll-inner">
+      <ion-grid>
+        <ion-row class="category-row">
+          <ion-col 
+            size="3" 
+            size-sm="3" 
+            size-md="3" 
+            size-lg="3" 
+            size-xl="3" 
+            *ngFor="let category of categories" 
+            class="category-col">
+            <div class="category-item" (click)="onCategoryClick(category)">
+              <div class="category-image-wrapper">
+                <img [src]="category.image" alt="{{category.name}}" class="category-image">
+              </div>
+              <div class="category-text">{{ category.name }}</div>
+            </div>
+          </ion-col>
+        </ion-row>
+      </ion-grid>
+    </div>
+  </div>
 
-  <!-- <ion-card>
-    <ion-card-header>
-      <ion-card-title>健康护肤专场</ion-card-title>
-    </ion-card-header>
-    <ion-card-content>
-      <ion-item *ngFor="let product of products">
-        <ion-thumbnail slot="start">
-          <img [src]="product.image">
-        </ion-thumbnail>
-        <ion-label>
-          <h2>{{ product.name }}</h2>
-          <p>{{ product.price }}</p>
-        </ion-label>
-      </ion-item>
-    </ion-card-content>
-  </ion-card> -->
-  <ion-card>
-    <app-sale-card *ngFor="let product of products" [product]="product"></app-sale-card>
-  </ion-card>
+  <!-- 热销模块 -->
+  <div class="marketing-section">
+    <h2>热销🔥🔥🔥</h2>
+    <ion-grid>
+      <ion-row>
+        <ion-col size="6" size-md="4" size-lg="3" *ngFor="let product of hotProducts | slice:0:4">
+          <ion-card class="product-card" (click)="openDetailModal(product)">
+            <ion-card-header class="product-card-header">
+              <div class="product-tag">{{ product.get('title') || '热销🔥🔥🔥' }}</div>
+            </ion-card-header>
+            <ion-card-content class="product-card-content">
+              <div class="product-image-wrapper">
+                <img [src]="product.get('image')" alt="{{product.get('name')}}" class="product-image">
+              </div>
+              <div class="product-info">
+                <h3 class="product-name">{{ product.get('name') }}</h3>
+                <div class="product-price">{{ product.get('price') }}</div>
+              </div>
+            </ion-card-content>
+          </ion-card>
+        </ion-col>
+      </ion-row>
+    </ion-grid>
+    <ion-button fill="clear" (click)="viewMore('hot')">查看更多</ion-button>
+  </div>
 
-  
-</ion-content>
+  <!-- 特价模块 -->
+  <div class="marketing-section">
+    <h2>特价优惠💰💰💰</h2>
+    <ion-grid>
+      <ion-row>
+        <ion-col size="6" size-md="4" size-lg="3" *ngFor="let product of specialProducts | slice:0:4">
+          <ion-card class="product-card" (click)="openDetailModal(product)">
+            <ion-card-header class="product-card-header">
+              <div class="product-tag">{{ product.get('title') || '特价优惠💰💰💰' }}</div>
+            </ion-card-header>
+            <ion-card-content class="product-card-content">
+              <div class="product-image-wrapper">
+                <img [src]="product.get('image')" alt="{{product.get('name')}}" class="product-image">
+              </div>
+              <div class="product-info">
+                <h3 class="product-name">{{ product.get('name') }}</h3>
+                <div class="product-price">{{ product.get('price') }}</div>
+              </div>
+            </ion-card-content>
+          </ion-card>
+        </ion-col>
+      </ion-row>
+    </ion-grid>
+    <ion-button fill="clear" (click)="viewMore('special')">查看更多</ion-button>
+  </div>
+
+  <!-- 商品卡片列表区域 -->
+  <div class="product-container">
+    <ion-grid>
+      <ion-row>
+        <ion-col size="6" size-md="4" size-lg="3" *ngFor="let product of products">
+          <ion-card class="product-card" (click)="openDetailModal(product)">
+            <ion-card-header class="product-card-header">
+              <div class="product-tag">{{ product.get('title') || '药品详情' }}</div>
+            </ion-card-header>
+            <ion-card-content class="product-card-content">
+              <div class="product-image-wrapper">
+                <img [src]="product.get('image')" alt="{{product.get('name')}}" class="product-image">
+              </div>
+              <div class="product-info">
+                <h3 class="product-name">{{ product.get('name') }}</h3>
+                <div class="product-price">{{ product.get('price') }}</div>
+              </div>
+            </ion-card-content>
+          </ion-card>
+        </ion-col>
+      </ion-row>
+    </ion-grid>
+  </div>
+
+  <!-- 底部弹出模态 -->
+  <ion-modal [isOpen]="showDetailModal" cssClass="bottom-modal" backdropDismiss="true" (ionModalDidDismiss)="closeDetailModal()">
+    <ion-header>
+      <ion-toolbar>
+        <ion-title>详情</ion-title>
+        <ion-buttons slot="end">
+          <ion-button fill="clear" (click)="closeDetailModal()">
+            <ion-icon name="close"></ion-icon>
+          </ion-button>
+        </ion-buttons>
+      </ion-toolbar>
+    </ion-header>
+
+    <ion-content>
+      <div class="modal-content" *ngIf="currentProduct">
+        <div class="image-container">
+          <img [src]="currentProduct.get('image')" alt="药品图片" class="medicine-image">
+        </div>
+        <h2 class="product-name">{{ currentProduct.get('name') }}</h2>
+        <p><strong>价格:</strong>{{ currentProduct.get('price') }}</p>
+        <p><strong>是否处方药:</strong>{{ currentProduct.get('prescription') ? '是' : '否' }}</p>
+        <p><strong>用法用量:</strong>{{ currentProduct.get('usage') }}</p>
+        <p><strong>主治功能:</strong>{{ currentProduct.get('function') }}</p>
+        <p><strong>规格:</strong>{{ currentProduct.get('spec') }}</p>
+        <p><strong>成分:</strong>{{ currentProduct.get('composition') }}</p>
+        <p><strong>禁忌:</strong>{{ currentProduct.get('taboo') }}</p>
+      </div>
+    </ion-content>
+  </ion-modal>
+</ion-content>

+ 179 - 50
wisdom-app/src/app/tab3/tab3.page.scss

@@ -1,54 +1,183 @@
+/* 整体背景渐变,可以根据需要调整或移除 */
+.content-background {
+  background: linear-gradient(to bottom, #e0f7fa, #ffffff);
+  --padding-bottom: 0;
+}
+
+/* 标题栏相关样式 */
 .custom-toolbar {
-  --background: rgba(255, 255, 255, 0.8); /* 使工具栏背景透明 */
-  display: flex; /* 使用 Flexbox 布局 */
-  justify-content: center; /* 水平居中 */
-  align-items: center; /* 垂直居中 */
-  padding: 0; /* 去掉默认内边距 */
+  --background: transparent;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  padding: 0;
+  border-bottom: none;
 }
 
 .custom-title {
-  font-size: 1.3em; /* 字体大小 */
-  font-weight: bold; /* 加粗 */
-  color: #000000; 
-  text-align: center; /* 文字居中对齐 */
-  margin: 0; /* 去掉默认外边距 */
-  text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2); /* 添加文字阴影效果 */
-  /* 添加其他美化效果 */
-  font-family: "微软雅黑"; /* 自定义字体 */
-}
-
-ion-button {
-    display: flex;
-    flex-direction: column;
-    align-items: center;
-    text-align: center;
-  }
-  
-  .category-image-wrapper {
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    width: 80px;
-    height: 80px;
-    border-radius: 50%;
-    background-color: #e0f7fa; /* 调整背景色 */
-    margin-bottom: 8px;
-  }
-  
-  .category-image {
-    display: inline-block;
-    width: 60px;
-    height: 60px;
-    border-radius: 50%;
-  }
-  
-  .category-name {
-    margin-top: 4px;
-    font-size: 14px;
-    color: #333;
-  }
-  
-  ion-icon {
-    font-size: 24px;
-    margin-bottom: 4px;
-  } 
+  font-size: 1.4em;
+  font-weight: bold;
+  color: #000; 
+  text-align: center;
+  margin: 0;
+  font-family: "微软雅黑", sans-serif;
+}
+
+/* 搜索栏区域样式 */
+.search-container {
+  padding: 0 16px;
+  margin-top: 8px;
+}
+
+.custom-searchbar {
+  --background: #ffffff;
+  --border-radius: 20px;
+  box-shadow: 0 2px 6px rgba(0,0,0,0.1);
+}
+
+/* 分类区域(可横向滚动) */
+.category-scroll {
+  overflow-x: auto; /* 如果需要横向滚动 */
+  width: 100%;
+}
+
+.category-scroll-inner {
+  width: 100%;
+}
+
+.category-row {
+  margin: 0;
+}
+
+.category-col {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  text-align: center;
+  margin-bottom: 16px; 
+  max-width: 25%; /* 确保每个列最大宽度为25%,即四个一行 */
+  flex: 0 0 25%; /* 防止列自动扩展 */
+}
+
+.category-item {
+  display: flex;
+  flex-direction: column; /* 垂直排列:图片在上,文字在下 */
+  align-items: center;
+  justify-content: center;
+  text-align: center;
+  cursor: pointer; /* 可选:让鼠标移上去有点击手势 */
+  width: 100%; /* 占满整个列 */
+}
+
+.category-image-wrapper {
+  width: 80px; /* 设定一个固定的宽度和高度 */
+  height: 80px;
+}
+
+.category-image {
+  width: 100%;
+  height: 100%;
+  object-fit: contain; 
+}
+
+.category-text {
+  font-size: 14px;
+  color: #333;
+  font-weight: 500;
+  text-align: center;
+  white-space: normal; 
+  max-width: 100%;
+}
+
+/* 商品列表区域样式 */
+.product-container {
+  padding: 0 16px;
+  margin-top: 16px;
+}
+
+.product-card {
+  border-radius: 12px;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.08);
+  margin: 8px 0; /* 调整上下间距 */
+}
+
+.product-card-header {
+  background: #348ef5;
+  border-top-left-radius: 12px;
+  border-top-right-radius: 12px;
+  display: flex;
+  align-items: center;
+  padding: 8px 12px;
+}
+
+.product-tag {
+  font-size: 14px;
+  font-weight: bold;
+  color: #333;
+}
+
+.product-card-content {
+  display: flex;
+  flex-direction: column; /* 竖直排列图片和信息 */
+  align-items: center; /* 居中对齐 */
+  padding: 12px;
+}
+
+.product-image-wrapper {
+  width: 100%;
+  height: 120px; /* 增大图片高度以适应网格布局 */
+  border-radius: 8px;
+  overflow: hidden;
+  margin-bottom: 12px; /* 增加底部间距 */
+}
+
+.product-image {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+}
+
+.product-info {
+  width: 100%;
+  text-align: center; /* 居中对齐文本 */
+}
+
+.product-name {
+  font-size: 16px;
+  font-weight: bold;
+  color: #333;
+  white-space: normal;
+  word-break: break-all;
+  margin-bottom: 4px;
+}
+
+.product-price {
+  font-size: 14px;
+  color: #e53935;
+  font-weight: bold;
+}
+
+/* 底部弹窗(modal)样式 */
+.bottom-modal {
+  --height: 75vh;
+  --width: 100%;
+  --border-radius: 20px 20px 0 0; 
+  --offset-y: calc(100% - 75vh);
+}
+
+.modal-content {
+  padding: 16px;
+}
+
+.image-container {
+  display: flex;
+  justify-content: center;
+  margin-bottom: 16px;
+}
+
+.medicine-image {
+  width: 120px;
+  height: 120px;
+  object-fit: cover;
+  border-radius: 8px;
+}

+ 132 - 36
wisdom-app/src/app/tab3/tab3.page.ts

@@ -1,13 +1,18 @@
 import { Component } from '@angular/core';
-import { Router } from '@angular/router';
-import { IonHeader, IonToolbar, IonTitle, IonContent, ModalController, IonButton, IonGrid, IonCol, IonCardHeader, IonLabel, IonThumbnail, IonCardContent, IonCardTitle, IonCard, IonIcon, IonSearchbar } from '@ionic/angular/standalone';
+import { ModalController, IonModal, IonHeader, IonToolbar, IonTitle, IonContent, IonList, IonItem, IonLabel, IonAvatar, IonButton, IonSegment, IonSegmentButton, IonSegmentContent, IonSegmentView, IonCardContent, IonCardTitle, IonCardHeader, IonCard, IonIcon, IonButtons, IonGrid, IonRow, IonThumbnail, IonSearchbar, IonCol } from '@ionic/angular/standalone';
 import { ExploreContainerComponent } from '../explore-container/explore-container.component';
-import { FmChatModalInput } from 'fmode-ng';
-import { IonRow, IonItem } from '@ionic/angular/standalone';
-import { CommonModule } from '@angular/common';
+import { addIcons } from 'ionicons';
+import { airplane, bluetooth, call, wifi, close } from 'ionicons/icons';
 import { SaleCardComponent } from '../component/sale-card/sale-card.component';
-// import { ModalAudioMessageComponent } from 'fmode-ng/lib/aigc/chat/chat-modal-input/modal-audio-message/modal-audio-message.component';
+import { CommonModule } from '@angular/common';
+import { CloudObject, CloudQuery } from 'src/lib/ncloud';
+import { Router } from '@angular/router';
+import { FmChatModalInput } from 'fmode-ng';
+import { AllProductsModalComponent } from '../all-products-modal/all-products-modal.component';
+import { DetailModalComponent } from '../detail-modal/detail-modal.component'; // 确保此组件已创建
+import { IonicModule } from '@ionic/angular';
 
+addIcons({ airplane, bluetooth, call, wifi });
 
 @Component({
   selector: 'app-tab3',
@@ -15,40 +20,131 @@ import { SaleCardComponent } from '../component/sale-card/sale-card.component';
   styleUrls: ['tab3.page.scss'],
   standalone: true,
   imports: [
-    IonHeader, IonToolbar, IonTitle, IonContent, ExploreContainerComponent,
-    IonButton, IonGrid, IonRow, IonCol,IonCardHeader, IonItem, IonLabel,IonThumbnail,IonCardContent,
-    IonCardTitle, IonCard, IonIcon, IonSearchbar, CommonModule,SaleCardComponent,
-    // ASR语音输入模块
-    FmChatModalInput,
-    // ModalAudioMessageComponent
+    IonicModule,
+    CommonModule,
+    AllProductsModalComponent,
+    DetailModalComponent,
+    ExploreContainerComponent,
+    SaleCardComponent,
+    FmChatModalInput
   ]
 })
 export class Tab3Page {
-  constructor(
-    private modalCtrl:ModalController,
-    private router:Router,
-    ) {
-  }
+  showDetailModal = false;  // 控制详情模态显示与否
+  currentProduct: any;      // 当前选择的药品信息
 
   categories = [
-    { name: '皮肤用药', image: '../../assets/image/doctor7.png' },
-    { name: '妇科用药', image: '../../assets/image/doctor7.png' },
-    { name: '肠胃消化', image: '../../assets/image/doctor7.png' },
-    { name: '呼吸用药', image: '../../assets/image/doctor7.png' },
-    { name: '营养补充', image: '../../assets/image/doctor7.png' },
-    { name: '家庭常备', image: '../../assets/image/doctor7.png' },
-    { name: '耳鼻咽喉', image: '../../assets/image/doctor7.png' },
-    { name: '男科用药', image: '../../assets/image/doctor7.png' },
-  ];
-  
-  // 商品列表
-  products = [
-    { title: '特价', subtitle: '药品', name: '清宫长春胶囊', price: '¥120', image: '../../assets/image/doctor7.png' },
-    { title: '特价', subtitle: '药品', name: '知柏地黄丸', price: '¥200', image: '../../assets/image/doctor7.png' },
-    { title: '特价', subtitle: '药品', name: '知柏地黄丸', price: '¥200', image: '../../assets/image/doctor7.png' },
+    { name: '皮肤用药', image: 'https://app.fmode.cn/dev/jxnu/202226701019/yao1.png' },
+    { name: '肠胃消化', image: 'https://app.fmode.cn/dev/jxnu/202226701019/yao5.png' },
+    { name: '呼吸用药', image: 'https://app.fmode.cn/dev/jxnu/202226701019/yao11.png' },
+    { name: '营养补充', image: 'https://app.fmode.cn/dev/jxnu/202226701019/yao9.png' },
+    { name: '家庭常备', image: 'https://app.fmode.cn/dev/jxnu/202226701019/yao12.png' },
+    { name: '耳鼻咽喉', image: 'https://app.fmode.cn/dev/jxnu/202226701019/yao10.png' },
+    { name: '骨科疼痛', image: 'https://app.fmode.cn/dev/jxnu/202226701019/yao6.png' },
+    { name: '心脑血管', image: 'https://app.fmode.cn/dev/jxnu/202226701019/yao7.png' },
   ];
 
-  // goChat(){
-  //   this.router.navigateByUrl("/chat/session/role/2DXJkRsjXK")
-  // }
-}
+  products: Array<CloudObject> = [];
+  allProducts: Array<CloudObject> = []; // 存储所有药品数据,用于分类过滤
+
+  hotProducts: Array<CloudObject> = [];
+  specialProducts: Array<CloudObject> = [];
+
+  constructor(
+    private modalCtrl: ModalController,
+    private router: Router,
+  ) {}
+
+  async ngOnInit() {
+    await this.loadProducts();
+  }
+
+  async loadProducts() {
+    try {
+      const query = new CloudQuery('Drug');
+      this.products = await query.find();
+      this.allProducts = [...this.products]; // 初始化所有产品
+
+      // 分类“热销”和“特价”药品
+      this.hotProducts = this.allProducts.filter(product => product.get('marketing') === 'hot');
+      this.specialProducts = this.allProducts.filter(product => product.get('marketing') === 'special');
+    } catch (error) {
+      console.error('加载药品数据失败', error);
+    }
+  }
+
+  // 打开详情模态窗口
+  openDetailModal(product: any) {
+    this.currentProduct = product;
+    this.showDetailModal = true;
+  }
+
+  // 关闭详情模态窗口
+  closeDetailModal() {
+    this.showDetailModal = false;
+    this.currentProduct = null;
+  }
+
+  // 根据分类导航到 drug-category 页面
+  onCategoryClick(category: any) {
+    this.router.navigate(['/drug-category', category.name]);
+  }
+
+  // 分享链接功能(可选)
+  shareDetailModal() {
+    // 实现分享功能
+    console.log('分享功能待实现');
+  }
+
+  // 复制链接功能
+  copyLink() {
+    const link = window.location.href;
+    navigator.clipboard.writeText(link).then(() => {
+      console.log('链接已复制');
+      // 可添加用户提示
+    }).catch(err => {
+      console.error('复制失败', err);
+    });
+  }
+
+  // 搜索功能
+  searchTerm: string = '';
+
+  async searchProducts(event: any) {
+    this.searchTerm = event.detail.value.toLowerCase();
+    if (this.searchTerm) {
+      this.products = this.allProducts.filter(product =>
+        product.get('name').toLowerCase().includes(this.searchTerm) ||
+        product.get('function').toLowerCase().includes(this.searchTerm) ||
+        product.get('composition').toLowerCase().includes(this.searchTerm)
+      );
+    } else {
+      this.products = [...this.allProducts];
+    }
+  }
+
+  // 查看更多功能,打开 AllProductsModalComponent 模态窗口
+  async viewMore(type: string) {
+    let filteredProducts: Array<CloudObject> = [];
+    let title: string = '';
+
+    if (type === 'hot') {
+      filteredProducts = this.hotProducts;
+      title = '热销药品';
+    } else if (type === 'special') {
+      filteredProducts = this.specialProducts;
+      title = '特价药品';
+    }
+
+    const modal = await this.modalCtrl.create({
+      component: AllProductsModalComponent,
+      componentProps: {
+        products: filteredProducts,
+        title: title
+      },
+      cssClass: 'bottom-modal'
+    });
+
+    return await modal.present();
+  }
+}

+ 136 - 43
wisdom-app/src/app/tab4/tab4.page.html

@@ -6,55 +6,148 @@
   </ion-toolbar>
 </ion-header>
 <ion-content [fullscreen]="true">
- 
+  <ion-refresher slot="fixed" (ionRefresh)="handleRefresh($event)">
+    <ion-refresher-content></ion-refresher-content>
+  </ion-refresher>
   <!-- 用户登录状态 -->
-  <ion-card>
+  
     <!-- 未登录 -->
      @if(!currentUser?.id){
-       <ion-card-header>
-         <ion-card-title>请登录</ion-card-title>
-         <ion-card-subtitle>暂无信息</ion-card-subtitle>
-        </ion-card-header>
-      }
-        <!-- 已登录 -->
-     @if(currentUser?.id){
-      <!-- <ion-card-header>
-        <ion-card-title>{{currentUser?.get("username")}}</ion-card-title>
-        <ion-card-subtitle>姓名:{{currentUser?.get("realname")||"-"}} 性别:{{currentUser?.get("gender")||"-"}} 年龄:{{currentUser?.get("age")||"-"}}</ion-card-subtitle>
-      </ion-card-header> -->
-      <ion-card-header class="card-header">
-        <img [src]="currentUser?.get('avatar')|| '../../assets/image/doctor7.png'" alt="头像" class="avatar" />
-        <div class="user-info">
-            <ion-card-title>账号:{{currentUser?.get("username")}}</ion-card-title>
-            <ion-card-subtitle>
-                姓名: {{currentUser?.get("realname") || "-"}} 
-                性别: {{currentUser?.get("gender") || "-"}} 
-                年龄: {{currentUser?.get("age") || "-"}}
-            </ion-card-subtitle>
-        </div>
-    </ion-card-header>
-      }
+      <ion-card >
+        <ion-content class="login">
+          <ion-card class="login-card">
+              <ion-card-header>
+                  <ion-card-title>请登录</ion-card-title>
+                  <ion-card-subtitle>暂无信息</ion-card-subtitle>
+                  <ion-card-content>欢迎来到“智养人生”!在这里,我们为您提供科学、全面的健康管理方案,帮助您实现身心的和谐与平衡。无论是饮食、运动还是心理调适,我们的专业团队将为您量身定制个性化的健康计划。让我们一起探索智慧养生的奥秘,开启健康新生活!登录后,您将踏上智养之旅,发现更好的自己。欢迎您的加入,智养人生,从此刻开始!</ion-card-content>
+              </ion-card-header>
+              <div class="image-container">
+                <img src="https://app.fmode.cn/dev/jxnu/202226701019/logo.png" alt="健康主题图片" class="responsive-image">
+            </div>
+          </ion-card>
+      </ion-content>
       <ion-card-content>
-      @if(!currentUser?.id){
         <ion-button expand="block" (click)="signup()" color="success">注册</ion-button>
         <ion-button expand="block" (click)="login()" color="success">登录</ion-button>
-      }
-     @if(currentUser?.id){
-      <ion-button expand="block" (click)="editUser()" color="success">编辑资料</ion-button>
-      <ion-button expand="block" (click)="logout()" color="medium">登出</ion-button>
-    }
-    </ion-card-content>
+      </ion-card-content>
   </ion-card>
-  <ion-card class="memo-card">
-    <h2 class="memo-title">健康备忘录</h2>
-    <p class="memo-description">写下您问诊的医生名或者心动的科普知识,便于您下次查找(点击标签可删除)</p>
-    <app-edit-tag (onTagChange)="setTagsValue($event)"></app-edit-tag>
+  }
+        <!-- 已登录 -->
+  @if(currentUser?.id){
+    @if(pageNum==0){
+        <div class="container">
+          <div class="top-section">
+            <ion-button expand="block" fill="outline" (click)="changeNum1()" color="dark">简约朴素-模块型</ion-button>
+            <ion-label class="zi1">点击进入此主题页面</ion-label>
+          </div>
+          <div class="bottom-section">
+            <ion-button expand="block" fill="outline" (click)="changeNum2()" color="light">优雅精致-层次型</ion-button>
+            <ion-label class="zi2">点击进入此主题页面</ion-label>
+          </div>
+        </div>
+      
+    }
+    @if(pageNum==1){
+      <ion-card >
+          <ion-card-header class="card-header">
+            <img [src]="currentUser?.get('avatar')" onerror="this.src='https://app.fmode.cn/dev/jxnu/202226701019/头像示例.png';" alt="图片加载失败" class="avatar" />
+            <div class="user-info">
+                <ion-card-title>账号:{{currentUser?.get("username")}}</ion-card-title>
+                <ion-card-subtitle>
+                    姓名: {{currentUser?.get("realname") || "-"}} 
+                    性别: {{currentUser?.get("gender") || "-"}} 
+                    年龄: {{currentUser?.get("age") || "-"}}
+                </ion-card-subtitle>
+            </div>
+        </ion-card-header>
+        <ion-card-content>
+          <ion-button expand="block" (click)="editUser()" color="success">编辑资料</ion-button>
+          <ion-button expand="block" (click)="changeNum2()">切换主题</ion-button>
+          <ion-button expand="block" (click)="logout()" color="medium">登出</ion-button>
+        </ion-card-content>
+      </ion-card>
+
+      <ion-card >
+        <ion-card-header>
+          <ion-card-title>个性头像生成器</ion-card-title>
+          <ion-card-subtitle>点击创建个性化头像</ion-card-subtitle>
+        </ion-card-header>
+        <ion-card-content>
+          <ion-button expand="block" (click)="goToAvatar()" color="success">前往生成</ion-button>
+        </ion-card-content>
+      </ion-card>
 
-    <h2 class="memo-title">收藏夹</h2>
-    <ul class="tag-list">
-        @for(tag of editTags; track tag;){
-            <li class="tag-item">{{tag}}</li>
-        }
-    </ul>
-</ion-card>
+      <ion-card class="memo-card" >
+        <h2 class="memo-title">健康备忘录</h2>
+        <p class="memo-description">写下您问诊的医生名或者心动的科普知识,便于您下次查找</p>
+        <app-edit-tag (onTagChange)="setTagsValue($event)"></app-edit-tag>
+        <h2 class="memo-title">收藏夹</h2>
+        <ul class="tag-list">
+            @for(tag of editTags; track tag;){
+                <li class="tag-item">{{tag}}</li>
+            }
+        </ul>
+      </ion-card>
+    }
+    @if(pageNum==2){
+      <ion-content class="ye2">
+      <ion-card class="custom-card">
+        <ion-avatar (click)="editUser()">
+          <img [src]="currentUser?.get('avatar')" onerror="this.src='https://app.fmode.cn/dev/jxnu/202226701019/头像示例.png';" alt="图片加载失败" class="avatar" />
+        </ion-avatar>
+        <ion-label>{{currentUser?.get("realname") || "-"}}</ion-label>
+      </ion-card>
+
+        <ion-list>
+          <ion-item>
+            <ion-icon name="person-circle" slot="start" ></ion-icon>
+            <ion-label (click)="editUser()">我的信息</ion-label>
+          </ion-item>
+          <ion-item>
+            <ion-icon name="image" slot="start"></ion-icon>
+            <ion-label>头像生成</ion-label>
+            <ion-button slot="end" fill="outline" size="small" color="success" (click)="goToAvatar()">前往生成</ion-button>
+          </ion-item>
+          <ion-item>
+            <ion-icon name="document" slot="start"></ion-icon>
+            <ion-label (click)="goToHealth()">健康档案</ion-label>
+          </ion-item>
+          <ion-item>
+            <ion-icon name="location" slot="start"></ion-icon>
+            <ion-label>我的地址</ion-label>
+          </ion-item>
+          <ion-item>
+            <ion-icon name="card" slot="start"></ion-icon>
+            <ion-label>我的优惠券</ion-label>
+          </ion-item>
+          <ion-item>
+            <ion-icon name="bag" slot="start"></ion-icon>
+            <ion-label>我的套餐包</ion-label>
+          </ion-item>
+          <ion-item>
+            <ion-icon name="chatbox" slot="start"></ion-icon>
+            <ion-label>联系客服</ion-label>
+          </ion-item>
+          <ion-item>
+            <ion-icon name="call" slot="start"></ion-icon>
+            <ion-label>绑定手机</ion-label>
+          </ion-item>
+          <ion-item>
+            <ion-icon name="folder" slot="start"></ion-icon>
+            <ion-label>我的收藏<app-edit-tag (onTagChange)="setTagsValue($event)"></app-edit-tag></ion-label>
+          </ion-item>
+        </ion-list>
+      
+        <ion-item>
+          <ion-label>关注公众号</ion-label>
+          <ion-label>每日医生直播义诊早知道~</ion-label>
+          <ion-button slot="end" fill="solid" size="small" color="success">立即前往</ion-button>
+        </ion-item>
+          <ion-button expand="block" fill="outline" (click)="changeNum1()" color="default">切换主题</ion-button>
+          <ion-button expand="block" fill="outline" (click)="logout()" color="medium">登出</ion-button>
+        
+        
+      </ion-content>
+    }
+}
 </ion-content>

+ 99 - 1
wisdom-app/src/app/tab4/tab4.page.scss

@@ -95,4 +95,102 @@ ion-card:hover {
 
 .user-info {
     flex: 1; /* 使用户信息部分占据剩余空间 */
-}
+}
+
+.login {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    height: 68vh; /* 使内容区域高度为视口高度 */
+}
+
+.ye2{
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    height: 100vh; /* 使内容区域高度为视口高度 */
+}
+
+.login-card {
+    width: 94%; /* 可以根据需要调整宽度 */
+    max-width: 400px; /* 设置最大宽度以避免过宽 */
+    text-align: center; /* 文本居中 */
+    padding: 10px; /* 添加内边距 */
+}
+
+.image-container {
+    width: 100%; /* 图片容器宽度100% */
+    display: flex; /* 使用flex布局 */
+    justify-content: center; /* 水平居中 */
+    margin-top: 10px; /* 上方间距 */
+}
+
+.responsive-image {
+    max-width: 80%; /* 最大宽度为容器宽度 */
+    height: auto; /* 高度自动 */
+    border-radius: 8px; /* 可选:添加圆角效果 */
+}
+
+//卡片背景
+.custom-card {
+    background-image: url('https://app.fmode.cn/dev/jxnu/202226701019/background.png'); /* 替换为你的图片链接 */
+    background-size: cover; /* 使背景图像覆盖整个卡片 */
+    background-position: center; /* 背景图像居中 */
+    height: 115px; /* 设置卡片高度,可以根据需求调整 */
+    color: white; /* 根据需要设置字体颜色 */
+    display: flex;
+    flex-direction: column; /* 使内容垂直排列 */
+    justify-content: center; /* 垂直居中 */
+    align-items: center; /* 水平居中 */
+    text-align: center; /* 文字居中 */
+    padding: 10px; /* 内边距 */
+  }
+
+  ion-avatar {
+    cursor: pointer; /* 鼠标悬停时显示为可点击 */
+    margin-bottom: 10px; /* 图片和文字之间的间距 */
+  }
+  
+  ion-label {
+    font-family: "微软雅黑";
+    font-size: 20px; /* 根据需要调整字体大小 */
+    color: #333; /* 根据需要调整字体颜色 */
+    
+  }
+
+  //选界面
+  .container {
+    display: flex;
+    flex-direction: column; /* 垂直排列 */
+    height: 100%; /* 使容器填满整个页面 */
+  }
+  
+  .top-section, .bottom-section {
+    flex: 1; /* 平均分配空间 */
+    display: flex;
+    justify-content: center; /* 水平居中 */
+    flex-direction: column; /* 使内容垂直排列 */
+    justify-content: center; /* 垂直居中 */
+    align-items: center; /* 垂直居中 */
+  }
+  
+  .top-section {
+    background-image: url('https://app.fmode.cn/dev/jxnu/202226701019/zhuti1.jpg'); /* 替换为你的图片链接 */
+    background-size: cover; /* 使背景图像覆盖整个卡片 */
+    background-position: center; /* 背景图像居中 */
+  }
+  
+  .bottom-section {
+    background-image: url('https://app.fmode.cn/dev/jxnu/202226701019/zhuti2.jpg'); /* 替换为你的图片链接 */
+    background-size: cover; /* 使背景图像覆盖整个卡片 */
+    background-position: center; /* 背景图像居中 */
+  }
+
+  .zi1{
+    font-size: smaller;
+    color: #000000;
+  }
+  .zi2{
+    font-size: smaller;
+    color: #e0f7fa;
+  }

+ 37 - 4
wisdom-app/src/app/tab4/tab4.page.ts

@@ -1,23 +1,55 @@
 import { Component } from '@angular/core';
-import { IonHeader, IonToolbar, IonTitle, IonContent, IonCard, IonCardContent, IonButton, IonCardHeader, IonCardTitle, IonCardSubtitle, ModalController } from '@ionic/angular/standalone';
+import { IonHeader, IonToolbar, IonTitle, IonContent, IonCard, IonCardContent, IonButton, IonCardHeader, IonCardTitle, IonCardSubtitle, ModalController, IonRefresher, IonRefresherContent, IonLabel, IonItem, IonIcon, IonList, IonAvatar } from '@ionic/angular/standalone';
 import { CloudUser } from 'src/lib/ncloud';
 import { openUserEditModal } from 'src/lib/user/modal-user-edit/modal-user-edit.component';
 import { openUserLoginModal } from 'src/lib/user/modal-user-login/modal-user-login.component';
 import { EditTagComponent } from '../component/edit-tag/edit-tag.component';
+import { Router } from '@angular/router';
 
 @Component({
   selector: 'app-tab4',
   templateUrl: 'tab4.page.html',
   styleUrls: ['tab4.page.scss'],
   standalone: true,
-  imports: [IonHeader, IonToolbar, IonTitle, IonContent, 
+  imports: [IonHeader, IonToolbar, IonTitle, IonContent, IonLabel,IonItem,IonIcon,IonList,IonAvatar,
     IonCard,IonCardContent,IonButton,IonCardHeader,IonCardTitle,IonCardSubtitle,
-    EditTagComponent
+    EditTagComponent,IonRefresher,IonRefresherContent
   ],
 })
 export class Tab4Page {
+  pageNum:Number=0
+  changeNum1(){
+    this.pageNum=1;
+  }
+  changeNum2(){
+    this.pageNum=2;
+  }
+
+  handleRefresh(event:any) {
+    setTimeout(() => {
+      // Any calls to load data go here
+      this.currentUser = new CloudUser();
+      event.target.complete();
+    }, 2000);
+  }
+
+  goToCollection(){
+    console.log("goToCollection");
+  }
+
+  goToAvatar(){
+    console.log(['route'])
+    this.router.navigate(['/tabs/picture'])
+  }
+
+  goToHealth(){
+    this.router.navigate(['/tabs/my-health'])
+  }
+
   currentUser:CloudUser|undefined
-  constructor(private modalCtrl:ModalController) {
+  constructor(
+    private router: Router,
+    private modalCtrl:ModalController) {
     this.currentUser = new CloudUser();
   }
   async login(){
@@ -35,6 +67,7 @@ export class Tab4Page {
     }
   }
   logout(){
+    // this.pageNum=0;
     this.currentUser?.logout();
   }
 

+ 4 - 4
wisdom-app/src/app/tabs/tabs.page.html

@@ -10,10 +10,10 @@
       <ion-label>科普</ion-label>
     </ion-tab-button>
 
-    <ion-tab-button tab="tab3" href="/tabs/tab3">
-      <ion-icon aria-hidden="true" name="cart"></ion-icon>
-      <ion-label>商城</ion-label>
-    </ion-tab-button>
+    <!-- <ion-tab-button tab="tab3" href="/tabs/tab3">
+      <ion-icon aria-hidden="true" name="bag-add"></ion-icon>
+      <ion-label>药品</ion-label>
+    </ion-tab-button> -->
 
     <ion-tab-button tab="tab4" href="/tabs/tab4">
       <ion-icon aria-hidden="true" name="person"></ion-icon>

+ 25 - 4
wisdom-app/src/app/tabs/tabs.page.ts

@@ -1,8 +1,18 @@
 import { Component, EnvironmentInjector, inject } from '@angular/core';
 import { IonTabs, IonTabBar, IonTabButton, IonIcon, IonLabel } from '@ionic/angular/standalone';
 import { addIcons } from 'ionicons';
-import { home, accessibility,cart, person } from 'ionicons/icons';
-
+import { home, accessibility,cart, person,bagAdd } from 'ionicons/icons';
+import {
+  compassOutline, bookOutline, book, storefront, personOutline, documentOutline,
+  mailOutline, calendarOutline, logoUsd, briefcaseOutline, heartOutline, footballOutline,
+  chevronForwardOutline, storefrontOutline, businessOutline, documentsOutline,
+  rocketOutline, sparklesOutline, medalOutline, listOutline, giftOutline,
+  scanOutline, settingsOutline, heartCircleOutline, walletOutline, bagRemoveOutline,
+  folderOutline, readerOutline, cartOutline, thumbsUpOutline, ticketOutline, documentTextOutline,
+  timeOutline, cloudDownloadOutline, bagCheckOutline, cardOutline, searchOutline, menuOutline,
+  addCircleOutline, addOutline, optionsOutline,checkmarkCircle
+} from 'ionicons/icons';
+import { CloudUser } from 'src/lib/ncloud';
 @Component({
   selector: 'app-tabs',
   templateUrl: 'tabs.page.html',
@@ -13,7 +23,18 @@ import { home, accessibility,cart, person } from 'ionicons/icons';
 export class TabsPage {
   public environmentInjector = inject(EnvironmentInjector);
 
-  constructor() {
-    addIcons({ home,accessibility,cart,person });
+    constructor() {
+      addIcons({
+        home, accessibility,cart, person,bagAdd,
+        compassOutline, bookOutline, book, storefront, personOutline, documentOutline,
+        mailOutline, calendarOutline, logoUsd, briefcaseOutline, heartOutline,
+        footballOutline, chevronForwardOutline, storefrontOutline, businessOutline,
+        documentsOutline, rocketOutline, sparklesOutline, medalOutline, listOutline,
+        giftOutline, scanOutline, settingsOutline, heartCircleOutline, walletOutline,
+        bagRemoveOutline, folderOutline, readerOutline, cartOutline, thumbsUpOutline,
+        ticketOutline, documentTextOutline, timeOutline, cloudDownloadOutline, bagCheckOutline,
+        cardOutline, searchOutline, menuOutline, addCircleOutline, addOutline, optionsOutline,checkmarkCircle
+      });
   }
+
 }

+ 28 - 27
wisdom-app/src/app/tabs/tabs.routes.ts

@@ -1,5 +1,6 @@
-import { Routes } from '@angular/router';
 import { TabsPage } from './tabs.page';
+import { NgModule } from '@angular/core';
+import { PreloadAllModules, RouterModule, Routes } from '@angular/router';
 
 export const routes: Routes = [
   {
@@ -51,46 +52,46 @@ export const routes: Routes = [
         loadComponent: () =>
           import('../page/page-my-health/page-my-health.component').then((m) => m.PageMyHealthComponent),
       },
+
       {
-        path: 'health-records', // 健康档案
-        loadComponent: () =>
-          import('../page/page-health-records/page-health-records.component').then((m) => m.PageHealthRecordsComponent),
-      },
-      {
-        path: 'drug-purchase', // 药品购买
-        loadComponent: () =>
-          import('../page/page-drug-purchase/page-drug-purchase.component').then((m) => m.PageDrugPurchaseComponent),
-      },
-      {
-        path: 'authority-experts', // 权威专家
-        loadComponent: () =>
-          import('../page/page-authority-experts/page-authority-experts.component').then((m) => m.PageAuthorityExpertsComponent),
-      },
-      {
-        path: 'health-information', // 健康资讯
+        path: 'drug-category/:name',
         loadComponent: () =>
-          import('../page/page-health-information/page-health-information.component').then((m) => m.PageHealthInformationComponent),
+          import('../drug-category/drug-category.page').then(
+            (m) => m.DrugCategoryPage
+          ),
       },
       {
-        path: 'phone-inquiry', // 电话咨询
+        path: 'ai-knowledge',
         loadComponent: () =>
-          import('../page/page-phone-inquiry/page-phone-inquiry.component').then((m) => m.PagePhoneInquiryComponent),
+          import('../page/page-ai-knowledge/page-ai-knowledge.component').then(
+            (m) => m.PageAiKnowledgeComponent
+          ),
       },
       {
-        path: 'smart-community', // 智慧社区
+        path: 'create-agent',
         loadComponent: () =>
-          import('../page/page-smart-community/page-smart-community.component').then((m) => m.PageSmartCommunityComponent),
+          import('../page/page-create-agent/page-create-agent.component').then(
+            (m) => m.PageCreateAgentComponent
+          ),
       },
       {
         path: '',
-        redirectTo: '/tabs/tab1',
-        pathMatch: 'full',
+        redirectTo: '/tabs/tab4',
+        pathMatch: 'full'
       },
     ],
   },
   {
     path: '',
-    redirectTo: '/tabs/tab1',
-    pathMatch: 'full',
-  },
+    redirectTo: '/tabs/tab4',
+    pathMatch: 'full'
+  }
 ];
+
+@NgModule({
+  imports: [
+    RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })
+  ],
+  exports: [RouterModule]
+})
+export class AppRoutingModule { }

BIN
wisdom-app/src/assets/image/background.png


BIN
wisdom-app/src/assets/image/doctor10.png


BIN
wisdom-app/src/assets/image/doctor11.png


BIN
wisdom-app/src/assets/image/doctor12.png


BIN
wisdom-app/src/assets/image/doctor8.png


BIN
wisdom-app/src/assets/image/doctor9.png


BIN
wisdom-app/src/assets/image/logo.png


BIN
wisdom-app/src/assets/image/yao1.png


BIN
wisdom-app/src/assets/image/yao10.png


BIN
wisdom-app/src/assets/image/yao11.png


BIN
wisdom-app/src/assets/image/yao12.png


BIN
wisdom-app/src/assets/image/yao2.png


BIN
wisdom-app/src/assets/image/yao3.png


BIN
wisdom-app/src/assets/image/yao4.png


BIN
wisdom-app/src/assets/image/yao5.png


BIN
wisdom-app/src/assets/image/yao6.png


BIN
wisdom-app/src/assets/image/yao7.png


BIN
wisdom-app/src/assets/image/yao8.jpg


BIN
wisdom-app/src/assets/image/yao9.png


Some files were not shown because too many files changed in this diff