Browse Source

feat add import.data

0225216 1 week ago
parent
commit
9e2045cb6d
5 changed files with 336 additions and 9 deletions
  1. 81 1
      src/app/tab1/tab1.page.html
  2. 33 0
      src/app/tab1/tab1.page.scss
  3. 91 8
      src/app/tab1/tab1.page.ts
  4. 119 0
      src/lib/import.data.ts
  5. 12 0
      src/lib/ncloud.ts

+ 81 - 1
src/app/tab1/tab1.page.html

@@ -80,7 +80,7 @@
 <!--今日任务-->
   <ion-card class="task-card">
     <ion-item lines="none">
-      <ion-label>今日任务 (3/5)</ion-label>
+      <ion-label (click)="importData()">今日任务 (3/5)</ion-label>
       <ion-progress-bar value="0.6" color="primary"></ion-progress-bar>
     </ion-item>
 
@@ -101,6 +101,86 @@
     </ion-list>
   </ion-card>
   
+  <!-- 健康数据记录 -->
+<ion-card class="health-data-card">
+  <ion-item lines="none">
+    <ion-label>健康数据记录</ion-label>
+    <ion-button fill="clear" size="small" (click)="loadHealthData()">
+      <ion-icon name="refresh" slot="icon-only"></ion-icon>
+    </ion-button>
+  </ion-item>
+
+  <!-- 加载状态 -->
+  <div *ngIf="healthData.loading" class="loading-spinner">
+    <ion-spinner name="crescent"></ion-spinner>
+  </div>
+
+  <!-- 血糖数据 -->
+  <ion-card *ngIf="healthData.bloodGlucose.length > 0" class="data-section">
+    <ion-card-header>
+      <ion-card-title>
+        <ion-icon name="water" color="primary"></ion-icon>
+        血糖记录
+      </ion-card-title>
+    </ion-card-header>
+    <ion-list lines="none">
+      <ion-item *ngFor="let item of healthData.bloodGlucose">
+        <ion-label>
+          <h3>{{item.get('glucoseValue')}} mmol/L</h3>
+          <p>{{item.get('measurementType')}} · {{item.get('measurementTime') | date: 'MM/dd HH:mm'}}</p>
+          <ion-text color="medium">{{item.get('notes')}}</ion-text>
+        </ion-label>
+        <ion-badge slot="end" color="success" *ngIf="item.get('glucoseValue') <= 6.1">正常</ion-badge>
+        <ion-badge slot="end" color="warning" *ngIf="item.get('glucoseValue') > 6.1 && item.get('glucoseValue') <= 7.0">偏高</ion-badge>
+        <ion-badge slot="end" color="danger" *ngIf="item.get('glucoseValue') > 7.0">过高</ion-badge>
+      </ion-item>
+    </ion-list>
+  </ion-card>
+
+  <!-- 血压数据 -->
+  <ion-card *ngIf="healthData.bloodPressure.length > 0" class="data-section">
+    <ion-card-header>
+      <ion-card-title>
+        <ion-icon name="speedometer" color="danger"></ion-icon>
+        血压记录
+      </ion-card-title>
+    </ion-card-header>
+    <ion-list lines="none">
+      <ion-item *ngFor="let item of healthData.bloodPressure">
+        <ion-label>
+          <h3>{{item.get('systolic')}}/{{item.get('diastolic')}} mmHg</h3>
+          <p>脉搏: {{item.get('pulse')}} · {{item.get('measurementTime') | date: 'MM/dd HH:mm'}}</p>
+          <ion-text color="medium">{{item.get('notes')}}</ion-text>
+        </ion-label>
+        <ion-badge slot="end" color="success" *ngIf="item.get('systolic') <= 120 && item.get('diastolic') <= 80">正常</ion-badge>
+        <ion-badge slot="end" color="warning" *ngIf="(item.get('systolic') > 120 && item.get('systolic') <= 140) || (item.get('diastolic') > 80 && item.get('diastolic') <= 90)">偏高</ion-badge>
+        <ion-badge slot="end" color="danger" *ngIf="item.get('systolic') > 140 || item.get('diastolic') > 90">过高</ion-badge>
+      </ion-item>
+    </ion-list>
+  </ion-card>
+
+  <!-- 心率数据 -->
+  <ion-card *ngIf="healthData.heartRate.length > 0" class="data-section">
+    <ion-card-header>
+      <ion-card-title>
+        <ion-icon name="heart" color="danger"></ion-icon>
+        心率记录
+      </ion-card-title>
+    </ion-card-header>
+    <ion-list lines="none">
+      <ion-item *ngFor="let item of healthData.heartRate">
+        <ion-label>
+          <h3>{{item.get('heartRate')}} 次/分</h3>
+          <p>{{item.get('measurementMethod')}} · {{item.get('measurementTime') | date: 'MM/dd HH:mm'}}</p>
+          <ion-text color="medium">{{item.get('notes')}}</ion-text>
+        </ion-label>
+        <ion-badge slot="end" color="success" *ngIf="item.get('heartRate') >= 60 && item.get('heartRate') <= 100">正常</ion-badge>
+        <ion-badge slot="end" color="warning" *ngIf="item.get('heartRate') < 60 || item.get('heartRate') > 100">异常</ion-badge>
+      </ion-item>
+    </ion-list>
+  </ion-card>
+</ion-card>
+
 <!--对话智能体-->
   <ion-card class="doctor-card">
   <div class="card-content">

+ 33 - 0
src/app/tab1/tab1.page.scss

@@ -127,4 +127,37 @@
   font-weight: bold;
   --padding-top: 12px;
   --padding-bottom: 12px;
+}
+// 健康数据卡片样式
+.health-data-card {
+  margin-top: 16px;
+  
+  .data-section {
+    margin: 8px 0;
+    box-shadow: none;
+    
+    ion-card-header {
+      padding-bottom: 0;
+      
+      ion-card-title {
+        font-size: 1.1rem;
+        display: flex;
+        align-items: center;
+        
+        ion-icon {
+          margin-right: 8px;
+        }
+      }
+    }
+  }
+  
+  .loading-spinner {
+    display: flex;
+    justify-content: center;
+    padding: 16px;
+  }
+  
+  ion-badge {
+    font-weight: normal;
+  }
 }

+ 91 - 8
src/app/tab1/tab1.page.ts

@@ -1,7 +1,9 @@
-import { Component } from '@angular/core';
+import { Component, OnInit } from '@angular/core';
 import{ChatPanelOptions,FmChatModalInput,FmodeChat,FmodeChatMessage,openChatPanelModal}from 'fmode-ng';
 import Parse from "parse";
 import{ModalController}from '@ionic/angular/standalone';
+import {  CloudUser, CloudQuery  } from 'src/lib/ncloud';
+import { importTestData } from 'src/lib/import.data';
 
 @Component({
   selector: 'app-tab1',
@@ -9,10 +11,95 @@ import{ModalController}from '@ionic/angular/standalone';
   styleUrls: ['tab1.page.scss'],
   standalone: false,
 })
-export class Tab1Page {
+export class Tab1Page implements OnInit{
+  healthData = {
+    bloodGlucose: [] as any[],
+    bloodPressure: [] as any[],
+    heartRate: [] as any[],
+    loading: true
+  };
   constructor(
     private modalCtrl:ModalController
   ){}
+
+  async ngOnInit() {
+    await this.loadHealthData();
+  }
+  // 加载健康数据
+  // 在 tab1.page.ts 中更新以下方法
+
+async loadHealthData() {
+  try {
+    this.healthData.loading = true;
+    
+    const user = new CloudUser();
+    const currentUser = await user.current();
+    
+    if (!currentUser?.id) {
+      console.warn('未获取到当前用户');
+      return;
+    }
+
+    console.log('当前用户ID:', currentUser.id);
+
+    // 查询最近30天数据
+    const timeAgo = new Date();
+    timeAgo.setDate(timeAgo.getDate() - 30);
+
+    const [glucose, pressure, heartRate] = await Promise.all([
+      this.queryData('BloodGlucose', currentUser, timeAgo),
+      this.queryData('BloodPressure', currentUser, timeAgo),
+      this.queryData('HeartRate', currentUser, timeAgo)
+    ]);
+
+    this.healthData = {
+      bloodGlucose: glucose,
+      bloodPressure: pressure,
+      heartRate: heartRate,
+      loading: false
+    };
+  } catch (error) {
+    console.error('加载失败:', error);
+    this.healthData.loading = false;
+  }
+}
+
+private async queryData(className: string, user: CloudUser, date: Date): Promise<any[]> {
+  const query = new CloudQuery(className);
+  query.equalTo('patient', {
+    __type: 'Pointer',
+    className: '_User',
+    objectId: user.id
+  });
+  query.greaterThan('measurementTime', date);
+  query.ascending('measurementTime');
+  return await query.find();
+}
+
+async importData() {
+  try {
+    this.healthData = {
+      bloodGlucose: [],
+      bloodPressure: [],
+      heartRate: [],
+      loading: true
+    };
+    
+    await importTestData();
+    await new Promise(resolve => setTimeout(resolve, 1000));
+    await this.loadHealthData();
+  } catch (error) {
+    console.error('导入失败:', error);
+  }
+}
+  // 刷新数据
+  async doRefresh(event: any) {
+    await this.loadHealthData();
+    setTimeout(() => {
+      event.target.complete();
+    }, 1000);
+  }
+  
 openConsult(chatId?:string){
     localStorage.setItem("company","E4KpGvTEto")
     let options:ChatPanelOptions = {
@@ -173,12 +260,8 @@ openConsult(chatId?:string){
   
 
 
-
-  doRefresh(event: any) {
-    setTimeout(() => {
-      event.target.complete();
-    }, 2000);
-  }
+ 
+  
 
   addData() {
     // 添加数据逻辑

+ 119 - 0
src/lib/import.data.ts

@@ -0,0 +1,119 @@
+import { CloudUser, CloudObject,CloudQuery } from './ncloud';
+
+// 测试数据导入函数
+export async function importTestData() {
+  try {
+    // 1. 创建或登录测试用户
+    const user = new CloudUser();
+    const testUsername = 'test_patient@111.com';
+    const testPassword = 'test123456';
+    
+    // 尝试登录,如果失败则注册新用户
+    let loggedInUser = await user.login(testUsername, testPassword);
+    if (!loggedInUser) {
+      loggedInUser = await user.signUp(testUsername, testPassword, {
+        firstName: '张',
+        lastName: '三',
+        email: testUsername,
+        birthDate: new Date('1970-05-15'),
+        gender: 'male',
+        medicalHistory: ['高血压', '2型糖尿病'],
+        currentMedications: ['二甲双胍', '阿司匹林']
+      });
+      console.log('新用户注册成功:', loggedInUser);
+    } else {
+      console.log('用户登录成功:', loggedInUser);
+    }
+    //用户存在性检查:
+    if (!loggedInUser) {
+     throw new Error('无法创建或登录测试用户');
+      }
+    //测试删除
+      await deleteUserHealthData(loggedInUser);
+    // 2. 创建血糖测试数据
+    const bloodGlucoseData = [
+      { glucoseValue: 5.2, measurementType: '空腹', measurementTime: new Date('2025-05-29T08:00:00') },
+      { glucoseValue: 7.8, measurementType: '餐后', measurementTime: new Date('2025-05-29T14:30:00') },
+      { glucoseValue: 6.5, measurementType: '随机', measurementTime: new Date('2025-05-29T10:15:00') }
+    ];
+
+    for (const data of bloodGlucoseData) {
+      const glucose = new CloudObject('BloodGlucose');
+      glucose.set({
+        patient: user.toPointer(),
+        ...data,
+        notes: '早餐后测量',
+        tags: ['早餐后', '正常范围']
+      });
+      await glucose.save();
+      console.log('血糖数据创建成功:', glucose.id);
+    }
+
+    // 3. 创建血压测试数据
+    const bloodPressureData = [
+      { systolic: 120, diastolic: 80, pulse: 72, measurementTime: new Date('2025-05-29T09:00:00'), measurementPosition: '坐姿' },
+      { systolic: 135, diastolic: 85, pulse: 76, measurementTime: new Date('2025-05-29T09:00:00'), measurementPosition: '坐姿' },
+      { systolic: 128, diastolic: 82, pulse: 74, measurementTime: new Date('2025-05-29T09:00:00'), measurementPosition: '坐姿' }
+    ];
+
+    for (const data of bloodPressureData) {
+      const pressure = new CloudObject('BloodPressure');
+      pressure.set({
+        patient: user.toPointer(),
+        ...data,
+        notes: '早晨服药前测量',
+        tags: ['早晨', '服药前']
+      });
+      await pressure.save();
+      console.log('血压数据创建成功:', pressure.id);
+    }
+
+    // 4. 创建心率测试数据
+    const heartRateData = [
+      { heartRate: 72, measurementTime: new Date('2025-05-29T08:30:00'), measurementMethod: '设备', rhythm: '规律' },
+      { heartRate: 68, measurementTime: new Date('2025-05-29T08:30:00'), measurementMethod: '设备', rhythm: '规律' },
+      { heartRate: 75, measurementTime: new Date('2025-05-29T08:30:00'), measurementMethod: '手动', rhythm: '规律' }
+    ];
+
+    for (const data of heartRateData) {
+      const heartRate = new CloudObject('HeartRate');
+      heartRate.set({
+        patient: user.toPointer(),
+        ...data,
+        notes: '静息心率测量',
+        tags: ['静息', '正常']
+      });
+      await heartRate.save();
+      console.log('心率数据创建成功:', heartRate.id);
+    }
+
+    console.log('所有测试数据导入完成!');
+  } catch (error) {
+    console.error('导入测试数据时出错:', error);
+  }
+}
+async function deleteUserHealthData(user: CloudUser) {
+  try {
+    const classes = ['BloodGlucose', 'BloodPressure', 'HeartRate'];
+    
+    for (const className of classes) {
+      const query = new CloudQuery(className);
+      query.equalTo('patient', user.toPointer());
+      const results = await query.find();
+      
+      // 逐条删除记录
+      if (results.length > 0) {
+        for (const record of results) {
+          await record.destroy();
+        }
+        console.log(`已删除 ${results.length} 条 ${className} 记录`);
+      }
+    }
+    return true;
+  } catch (error) {
+    console.error('删除用户数据时出错:', error);
+    throw error;
+  }
+}
+// 执行导入
+importTestData();

+ 12 - 0
src/lib/ncloud.ts

@@ -86,6 +86,7 @@ export class CloudObject {
 }
 
 // CloudQuery.ts
+
 export class CloudQuery {
     className: string;
     queryParams: Record<string, any> = { where: {} };
@@ -222,6 +223,17 @@ export class CloudQuery {
         existsObject.updatedAt = exists.updatedAt;
         return existsObject;
     }
+    // 在 CloudQuery 类中添加
+ascending(key: string) {
+  this.queryParams["order"] = key;
+  return this; // 支持链式调用
+}
+
+// 如果需要降序排序,也可以添加
+descending(key: string) {
+  this.queryParams["order"] = `-${key}`;
+  return this;
+}
 }
 
 // CloudUser.ts