浏览代码

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

惊鸿戏梦 4 月之前
父节点
当前提交
e7d45d1859

+ 2 - 0
wisdom-app/src/app/page/inquiry-human/inquiry-human.component.html

@@ -7,6 +7,8 @@
 </ion-header>
 
 <ion-content>
+
+  
   <div>
     <ion-list>
       <ion-item>

+ 2 - 1
wisdom-app/src/app/page/inquiry-human/inquiry-human.component.ts

@@ -12,7 +12,7 @@ addIcons({ airplane, bluetooth, call, wifi });
   styleUrls: ['./inquiry-human.component.scss'],
   standalone: true,
   imports: [IonHeader, IonToolbar, IonTitle, IonContent, ExploreContainerComponent,
-    IonLabel,IonItem,IonList,IonAvatar,IonLabel,IonButton
+    IonLabel,IonItem,IonList,IonAvatar,IonLabel,IonButton,
   ]
 })
 export class InquiryHumanComponent  implements OnInit {
@@ -26,4 +26,5 @@ export class InquiryHumanComponent  implements OnInit {
   backhome(){
     this.router.navigate(['/tabs/tab1']);
   }
+
 }

+ 13 - 1
wisdom-app/src/app/page/page-inquiry/page-inquiry.component.html

@@ -7,7 +7,19 @@
 </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-avatar>
+        <ion-label>Huey</ion-label>
+      </ion-item>
+    </ion-list>
+  </div>
+  <div class="createai">
+    <ion-button expand="block" (click)="createAI()" color="primary" slot="start">创建ai医生</ion-button>
+  </div>
   <!-- <h1>科室</h1>
   <ion-input  [value]="keshi" placeholder="请输入科室" (ionInput)="keshiInput($event)"></ion-input> -->
 

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

@@ -0,0 +1,5 @@
+.createai{
+    ion-button{
+        contain-intrinsic-height: 50px;
+    }
+}

+ 6 - 2
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 } from '@ionic/angular/standalone';
 import { AgentTaskStep } from 'src/agent/agent.task';
 import { addIcons } from 'ionicons';
 import { radioButtonOffOutline, reloadOutline, checkmarkCircleOutline, closeCircleOutline } from 'ionicons/icons';
@@ -26,10 +26,14 @@ 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
   ],
 })
 export class PageInquiryComponent  implements OnInit {
+  createAI(){
+    this.router.navigate(['/tabs/tab1']);
+  }
 
   ngOnInit(){
     this.loadDoctorList();

+ 15 - 1
wisdom-app/src/app/tab1/schema.md

@@ -117,6 +117,13 @@ state ConversationFinished {
 }
 @enduml
 ```
+- 在这个状态图中:
+[*] 表示初始状态和最终状态(即整个流程开始前的状态和流程完整结束后的状态)。
+从 Initiated 开始,代表问诊流程启动,首先进入 SelectingDoctor 状态,意味着用户要进行选择 AI 医生的操作,完成选择后进入 DoctorSelected 状态。
+在 DoctorSelected 状态下,用户接着要提供问诊信息,进入 ProvidingInfo 状态,随后 AI 医生开始与之对话,进入 ConversationInProgress 状态。
+当 AI 医生生成处方后,进入 PrescriptionGenerated 状态,对话结束后到达 ConversationFinished 状态。
+最后在 ConversationFinished 状态下依次进行创建问诊记录、整合信息并保存记录的操作,最终达到 RecordSaved 状态,表示整个问诊记录成功保存到数据库,流程结束返回初始的结束状态 [*] 。
+
 
 ## 活动图
 ```plantuml
@@ -139,4 +146,11 @@ endif
 :用户查询问诊记录;
 stop
 @enduml
-```
+```
+在这个活动图中:
+首先通过 “用户发起问诊” 活动开始整个流程。
+接着通过一个条件判断分支来决定是选择已有 AI 医生还是创建新的 AI 医生,根据用户的选择执行相应的活动。
+然后用户提供问诊信息后,AI 医生依次进行接收信息并对话、生成处方以及结束对话等活动。
+后续开展创建问诊记录实例,并关联相关的用户、医生、科室等重要信息,再整合包含处方在内的问诊记录内容,接着将其保存到数据库中。
+最后用户可以进行查询问诊记录的活动,整个流程结束。
+此活动图从比较宏观的角度展示了 AI 问诊服务中主要的活动以及它们之间的先后顺序和逻辑关系,

+ 71 - 35
wisdom-app/src/app/tab3/tab3.page.html

@@ -1,46 +1,82 @@
 <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">
+  <!-- 搜索栏 -->
+  <div class="search-container">
+    <ion-searchbar placeholder="搜索" class="custom-searchbar"></ion-searchbar>
+  </div>
 
-  <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 class="category-scroll">
+    <div class="category-scroll-inner">
+      <ion-grid>
+        <ion-row class="category-row">
+          <ion-col size="3" *ngFor="let category of categories" class="category-col">
+            <div class="category-item">
+              <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>
+
+  <!-- 商品卡片列表区域 -->
+  <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.title}}</div>
+        </ion-card-header>
+        <ion-card-content class="product-card-content">
+          <div class="product-image-wrapper">
+            <img [src]="product.image" alt="{{product.name}}" class="product-image">
+          </div>
+          <div class="product-info">
+            <h3 class="product-name">{{product.name}}</h3>
+            <div class="product-price">{{product.price}}</div>
           </div>
-          <div class="category-name">{{ category.name }}</div>
-        </ion-button>
-      </ion-col>
-    </ion-row>
-  </ion-grid>
+        </ion-card-content>
+      </ion-card>
+    </ng-container>
+  </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>
+  <!-- 底部弹出模态 -->
+  <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>
+    <ion-content>
+      <div class="modal-content" *ngIf="currentProduct">
+        <div class="image-container">
+          <img [src]="currentProduct.image" alt="药品图片" class="medicine-image">
+        </div>
+        <h2 class="product-name">{{currentProduct.name}}</h2>
+        <p><strong>价格:</strong>{{currentProduct.price}}</p>
+        <p><strong>是否处方药:</strong>{{currentProduct.prescription ? '是' : '否'}}</p>
+        <p><strong>用法用量:</strong>{{currentProduct.usage}}</p>
+        <p><strong>主治功能:</strong>{{currentProduct.function}}</p>
+        <p><strong>规格:</strong>{{currentProduct.spec}}</p>
+        <p><strong>成分:</strong>{{currentProduct.composition}}</p>
+        <p><strong>禁忌:</strong>{{currentProduct.taboo}}</p>
+      </div>
+    </ion-content>
+  </ion-modal>
+</ion-content>

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

@@ -1,54 +1,167 @@
+// 整体背景渐变,可以根据需要调整或移除
+.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-row {
+  margin: 0;
+}
+
+.category-col {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  text-align: center;
+  margin-bottom: 16px; 
+}
+
+.category-item {
+  display: flex;
+  flex-direction: column; /* 垂直排列:图片在上,文字在下 */
+  align-items: center;
+  justify-content: center;
+  text-align: center;
+  cursor: pointer; /* 可选:让鼠标移上去有点击手势 */
+}
+
+.category-image {
+  max-width: 90%;
+  max-height: 90%;
+  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-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;
+}
+
+// 底部弹窗(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;
+}

+ 57 - 18
wisdom-app/src/app/tab3/tab3.page.ts

@@ -1,13 +1,11 @@
 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 { IonHeader, IonToolbar, IonTitle, IonContent, ModalController, IonButton, IonGrid, IonCol, IonCardHeader, IonLabel, IonThumbnail, IonCardContent, IonCardTitle, IonCard, IonIcon, IonSearchbar, IonModal, IonButtons } 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 { 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';
-
 
 @Component({
   selector: 'app-tab3',
@@ -16,19 +14,19 @@ import { SaleCardComponent } from '../component/sale-card/sale-card.component';
   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
+    IonButton, IonGrid, IonRow, IonCol, IonCardHeader, IonItem, IonLabel, IonThumbnail, IonCardContent,
+    IonCardTitle, IonCard, IonIcon, IonSearchbar, CommonModule, SaleCardComponent,
+    FmChatModalInput, IonModal, IonButtons
   ]
 })
 export class Tab3Page {
+  showDetailModal = false;  // 控制模态显示与否
+  currentProduct: any;      // 当前选择的商品信息
+
   constructor(
     private modalCtrl:ModalController,
     private router:Router,
-    ) {
-  }
+  ) {}
 
   categories = [
     { name: '皮肤用药', image: '../../assets/image/doctor7.png' },
@@ -41,14 +39,55 @@ export class Tab3Page {
     { 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' },
+    { 
+      title: '热销🔥🔥🔥', 
+      subtitle: '药品', 
+      name: '藿香正气水', 
+      price: '¥120', 
+      image: '../../assets/image/doctor7.png',
+      prescription: false, 
+      usage: '口服,每次5-10毫升,每天2次', 
+      function: '解表化湿,理气和中。',
+      spec: '10ml*10支/盒', 
+      composition: '藿香、紫苏叶、白芷、法半夏、厚朴等',
+      taboo: '孕妇慎用'
+    },
+    { 
+      title: '特价💰💰💰', 
+      subtitle: '药品', 
+      name: '知柏地黄丸', 
+      price: '¥200', 
+      image: '../../assets/image/doctor7.png',
+      prescription: true,
+      usage: '口服,一次6克,一日2次',
+      function: '滋阴清热,用于阴虚火旺所致的潮热盗汗。',
+      spec: '9g*10丸/盒',
+      composition: '知母、黄柏、熟地黄、山药等',
+      taboo: '孕妇、严重肝肾功能不全者慎用'
+    },
+    { 
+      title: '特价💰💰💰', 
+      subtitle: '药品', 
+      name: '知柏地黄丸', 
+      price: '¥200', 
+      image: '../../assets/image/doctor7.png',
+      prescription: true,
+      usage: '口服,一次6克,一日2次',
+      function: '滋阴清热,用于阴虚火旺所致的潮热盗汗。',
+      spec: '9g*10丸/盒',
+      composition: '知母、黄柏、熟地黄、山药等',
+      taboo: '孕妇、严重肝肾功能不全者慎用'
+    },
   ];
 
-  // goChat(){
-  //   this.router.navigateByUrl("/chat/session/role/2DXJkRsjXK")
-  // }
-}
+  openDetailModal(product: any) {
+    this.currentProduct = product;
+    this.showDetailModal = true;
+  }
+
+  closeDetailModal() {
+    this.showDetailModal = false;
+    this.currentProduct = null;
+  }
+}

+ 14 - 1
wisdom-app/src/app/tab4/tab4.page.html

@@ -45,6 +45,18 @@
     }
     </ion-card-content>
   </ion-card>
+  @if(currentUser?.id){
+  <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)="goToCollection()" color="success">查看收藏</ion-button>
+    </ion-card-content>
+  </ion-card>
+  }
+  @if(currentUser?.id){
   <ion-card class="memo-card">
     <h2 class="memo-title">健康备忘录</h2>
     <p class="memo-description">写下您问诊的医生名或者心动的科普知识,便于您下次查找(点击标签可删除)</p>
@@ -56,5 +68,6 @@
             <li class="tag-item">{{tag}}</li>
         }
     </ul>
-</ion-card>
+  </ion-card>
+  }
 </ion-content>

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

@@ -16,6 +16,10 @@ import { EditTagComponent } from '../component/edit-tag/edit-tag.component';
   ],
 })
 export class Tab4Page {
+  goToCollection(){
+    console.log("goToCollection");
+  }
+
   currentUser:CloudUser|undefined
   constructor(private modalCtrl:ModalController) {
     this.currentUser = new CloudUser();