Procházet zdrojové kódy

健康分析报告 添加脉象分析

cc12458 před 3 měsíci
rodič
revize
1afa3b782b

+ 1 - 1
.prettierrc.json

@@ -3,6 +3,6 @@
   "semi": true,
   "tabWidth": 2,
   "singleQuote": true,
-  "printWidth": 120,
+  "printWidth": 180,
   "trailingComma": "es5"
 }

+ 4 - 20
@types/bridge.d.ts

@@ -1,11 +1,4 @@
-interface HandSummary {
-  chi: string;
-  cun: string;
-  guan: string;
-  summary: string[];
-}
-
-type HandKeys = 'chen' | 'chi' | 'fu' | 'hua' | 'kong' | 'ruan' | 'shi' | 'shu' | 'xi' | 'xian';
+import type { SimplePulseModel } from './pulse';
 
 interface ScanData {
   code: string;
@@ -20,20 +13,9 @@ export interface BridgeEventMap {
 export class Bridge extends EventTarget {
   public static getInstance(): Bridge;
 
-  public static pulse(userId: string): Promise<{
-    measureId: string;
-    summaryLabel: {
-      summary?: HandSummary['summary'];
-      left?: HandSummary;
-      right?: HandSummary;
-    };
-    summaryValue: Record<HandKeys, number[]>;
-    time: string;
-
+  public static pulse(userId: string): Promise<SimplePulseModel & { report: string; time: string; } & {
     appId?: string;
     userId?: string;
-    url: string;
-    report: string;
   }>;
 
   public static print(): Promise<void>;
@@ -47,6 +29,8 @@ export class Bridge extends EventTarget {
    */
   addEventListener<T extends keyof BridgeEventMap>(type: T, listener: (event: BridgeEventMap[T]) => void, options?: boolean | AddEventListenerOptions): () => void;
   removeEventListener<T extends keyof BridgeEventMap>(type: T, listener: (event: BridgeEventMap[T]) => void, options?: boolean | AddEventListenerOptions): () => void;
+
+  postMessage(...args: any[]): Promise<void>;
 }
 
 export interface globalAIO {

+ 20 - 0
@types/pulse.d.ts

@@ -0,0 +1,20 @@
+interface HandSummary {
+  chi: string;
+  cun: string;
+  guan: string;
+  summary: string[];
+}
+
+type HandKeys = 'chen' | 'chi' | 'fu' | 'hua' | 'kong' | 'ruan' | 'shi' | 'shu' | 'xi' | 'xian';
+
+export interface SimplePulseModel {
+  measureId: string;
+  summaryLabel: {
+    summary?: HandSummary['summary'];
+    left?: HandSummary;
+    right?: HandSummary;
+  };
+  summaryValue: Record<HandKeys, number[]>;
+  hand?: number;
+  url?: string;
+}

+ 58 - 0
src/components/AnalysisPulseComponent.vue

@@ -0,0 +1,58 @@
+<script setup lang="ts">
+import type { SimplePulseModel } from '../../@types/pulse';
+
+import HandLeft from '@/assets/images/pulse-hand-left.png?url';
+import HandRight from '@/assets/images/pulse-hand-right.png?url';
+import { useVisitor } from '@/stores';
+
+type Props = SimplePulseModel & { title?: string; results?: string };
+
+const { title = '分析', results, ..._report } = defineProps<Props>();
+
+const Visitor = useVisitor();
+const report = computed(() => unref(results) ? _report : Visitor.pulseReport)
+</script>
+
+<template>
+  <van-skeleton class="analysis" :row="5" :loading="results == null" v-if="results !== ''">
+    <slot>
+      <div class="card m-6 text-lg">
+        <div v-if="title" class="card__title mb-3 text-primary text-2xl font-bold">{{ title }}</div>
+        <slot name="content" :results="results" :report="report">
+          <div class="card__content">
+            <div v-if="report?.summaryLabel" class="flex justify-evenly">
+              <div v-if="report?.summaryLabel?.left" class="flex flex-row-reverse justify-center">
+                <img style="width: 100px;height: 200px;" :src="HandLeft" alt="左手" />
+                <div class="flex flex-col justify-evenly translate-y-2 h-40 text-xl">
+                  <div>寸:<span style="letter-spacing: 4px">{{ report?.summaryLabel.left.cun }}</span></div>
+                  <div>关:<span style="letter-spacing: 4px">{{ report?.summaryLabel.left.guan }}</span></div>
+                  <div>尺:<span style="letter-spacing: 4px">{{ report?.summaryLabel.left.chi }}</span></div>
+                </div>
+              </div>
+              <div v-if="report?.summaryLabel?.right">
+                <div class="flex justify-center">
+                  <img style="width: 100px;height: 200px;"  :src="HandRight" alt="右手" />
+                  <div class="flex flex-col justify-evenly translate-y-2 h-40 text-xl">
+                    <div>寸:<span style="letter-spacing: 4px">{{ report?.summaryLabel.right.cun }}</span></div>
+                    <div>关:<span style="letter-spacing: 4px">{{ report?.summaryLabel.right.guan }}</span></div>
+                    <div>尺:<span style="letter-spacing: 4px">{{ report?.summaryLabel.right.chi }}</span></div>
+                  </div>
+                </div>
+              </div>
+            </div>
+            <p v-if="results" class="text-2xl text-center">
+              总体脉象:<span class="text-primary-400" style="letter-spacing: 4px">{{ results }}</span>
+            </p>
+          </div>
+        </slot>
+      </div>
+      <slot name="exception">
+
+      </slot>
+    </slot>
+  </van-skeleton>
+</template>
+
+<style scoped lang="scss">
+
+</style>

+ 4 - 39
src/modules/pulse/pulse.page.vue

@@ -79,7 +79,8 @@ const {
   data: report,
   loading: submitting,
   send: submit,
-} = useRequest((id, result) => putPulseMethod(id, result), { immediate: false }).onSuccess(() => {
+} = useRequest((id, result) => putPulseMethod(id, result), { immediate: false }).onSuccess(({ data }) => {
+  Visitor.updatePulseReport(data);
   finished.value = true;
   start();
 });
@@ -128,50 +129,14 @@ tryOnUnmounted(() => {
     </div>
     <div class="page-content flex flex-col">
       <header></header>
-      <main class="flex flex-col justify-evenly px-8">
+      <main class="flex flex-col justify-evenly">
         <template v-if="finished && report">
           <img class="size-40 mx-auto" src="@/assets/images/tips.png" alt="" />
           <div>
             <div class="text-3xl text-center">恭喜您!</div>
             <div class="text-3xl text-center my-8">完成脉诊采集</div>
           </div>
-          <div v-if="report">
-            <div v-if="report.summaryLabel" class="flex justify-evenly">
-              <div v-if="report.summaryLabel?.left" class="flex flex-row-reverse justify-center">
-                <img style="width: 100px;height: 200px;" :src="HandLeft" alt="左手" />
-                <div class="flex flex-col justify-evenly translate-y-2 h-40 text-xl">
-                  <div>
-                    寸:<span style="letter-spacing: 4px">{{ report.summaryLabel.left.cun }}</span>
-                  </div>
-                  <div>
-                    关:<span style="letter-spacing: 4px">{{ report.summaryLabel.left.guan }}</span>
-                  </div>
-                  <div>
-                    尺:<span style="letter-spacing: 4px">{{ report.summaryLabel.left.chi }}</span>
-                  </div>
-                </div>
-              </div>
-              <div v-if="report.summaryLabel?.right">
-                <div class="flex justify-center">
-                  <img style="width: 100px;height: 200px;"  :src="HandRight" alt="右手" />
-                  <div class="flex flex-col justify-evenly translate-y-2 h-40 text-xl">
-                    <div>
-                      寸:<span style="letter-spacing: 4px">{{ report.summaryLabel.right.cun }}</span>
-                    </div>
-                    <div>
-                      关:<span style="letter-spacing: 4px">{{ report.summaryLabel.right.guan }}</span>
-                    </div>
-                    <div>
-                      尺:<span style="letter-spacing: 4px">{{ report.summaryLabel.right.chi }}</span>
-                    </div>
-                  </div>
-                </div>
-              </div>
-            </div>
-            <p v-if="report.results" class="text-2xl text-center">
-              总体脉象:<span class="text-primary-400" style="letter-spacing: 4px">{{ report.results }}</span>
-            </p>
-          </div>
+          <AnalysisPulseComponent title="" v-bind="report"></AnalysisPulseComponent>
         </template>
       </main>
       <footer class="flex flex-col justify-center items-center">

+ 2 - 0
src/modules/report/report.page.vue

@@ -20,6 +20,7 @@ const { data, loading } = useWatcher(() => getReportMethod(id.value), [ id ], {
     descriptionsTable: { column: [], data: [] },
     tongue: {},
     face: {},
+    pulse: {},
   },
   immediate: true,
 }).onSuccess(({ data }) => {
@@ -181,6 +182,7 @@ const scrollable = computed(() => !data.value.payLock &&
             </template>
             <template #exception><div><!--空占位符--></div></template>
           </AnalysisComponent>
+          <AnalysisPulseComponent title="脉象分析" v-bind="data.pulse"></AnalysisPulseComponent>
           <div class="card m-6 text-lg" v-if="data['中医证素']?.length">
             <div class="card__title mb-3 text-primary text-2xl font-bold">中医证素</div>
             <div class="card__content">

+ 13 - 4
src/request/api/pulse.api.ts

@@ -1,18 +1,27 @@
 import HTTP from '@/request/alova';
+import type { PulseAnalysisModel } from '@/request/model';
 
-export type PulseResult = Awaited<ReturnType<typeof Bridge.pulse>> & { patientId: string; results: string };
 const getSummary = (value?: string[]) => (Array.isArray(value) && value.length ? value : void 0);
 
-export function putPulseMethod(patientId: string, result: PulseResult) {
+export function putPulseMethod(patientId: string, result: PulseAnalysisModel) {
   const summary =
     getSummary(result.summaryLabel?.summary) ??
     getSummary(result.summaryLabel?.left?.summary) ??
     getSummary(result.summaryLabel?.right?.summary) ??
     [];
   const data = Object.assign(result, { patientId, results: summary.join(',') });
-  return HTTP.Post<PulseResult, any>(`/fdhb-tablet/analysisManage/savePulseAnalysisReport`, data, {
+  return HTTP.Post<PulseAnalysisModel, any>(`/fdhb-tablet/analysisManage/savePulseAnalysisReport`, data, {
     transform() {
-      return data;
+      return {
+        measureId: data.measureId,
+        hand: [
+          data.summaryLabel?.left?.summary?.length,
+          data.summaryLabel?.right?.summary?.length,
+        ].filter(Boolean).length,
+        summaryValue: data.summaryValue,
+        summaryLabel: data.summaryLabel,
+        results: data.results,
+      };
     },
   });
 }

+ 4 - 1
src/request/api/report.api.ts

@@ -33,11 +33,14 @@ export function getAnalysisResultsMethod() {
 
 export function getReportMethod(id: string) {
   const Visitor = useVisitor();
-  const params = { healthAnalysisReportId: id, patientId: Visitor.patientId };
+  const params = { healthAnalysisReportId: id, patientId: Visitor.patientId?.toString() };
   return HTTP.Get(`/fdhb-tablet/analysisManage/getHealRepDetailById`, {
     params,
     async transform(data, headers) {
+      const patientId = (<any>data)?.patientId?.toString()
+      if (params.patientId !== patientId ) Visitor.$reset()
       const report = fromReportData(<any> data);
+      Visitor.updatePulseReport(report.pulse, patientId);
       const { show, force } = await miniProgramMethod();
       if ( !show ) { report.miniProgramURL = void 0; }
       report.payLock = show && force;

+ 41 - 6
src/request/model/analysis.model.ts

@@ -1,24 +1,34 @@
 import { groupBy } from '@/tools';
 
-
-export function fromAnalysisModel(mode: 'tongue' | 'face', data: Record<string, any>): AnalysisModel {
+export function fromAnalysisModel(mode: 'tongue' | 'face', data: Record<string, any>): AnalysisModel;
+export function fromAnalysisModel(mode: 'pulse', data: Record<string, any>): PulseAnalysisModel;
+export function fromAnalysisModel(
+  mode: 'tongue' | 'face' | 'pulse',
+  data: Record<string, any>
+): AnalysisModel | PulseAnalysisModel {
   let model: AnalysisModel;
-  switch ( mode ) {
+  switch (mode) {
     case 'tongue':
       model = fromTongueAnalysisModel(data);
       break;
     case 'face':
       model = fromFaceAnalysisModel(data);
       break;
+    case 'pulse':
+      return fromPulseAnalysisModel(data);
   }
 
   const group = groupBy<AnalysisException>(model.exception, (item) => item.cover ?? '');
-  model.exceptionGroup = Object.entries(group).map(([ key, exception ]) => (
-    { key, exception }
-  ));
+  model.exceptionGroup = Object.entries(group).map(([key, exception]) => ({ key, exception }));
   return model;
 }
 
+export interface PulseAnalysisModel extends Pick<Awaited<ReturnType<typeof Bridge.pulse>>, 'measureId' | 'summaryLabel' | 'summaryValue'> {
+  hand?: number;
+  results?: string;
+  url?: string;
+}
+
 export interface AnalysisModel {
   table: {
     columns: string[];
@@ -41,6 +51,31 @@ export interface AnalysisException {
   tags: string[];
 }
 
+function fromPulseAnalysisModel(data: Record<string, any>): PulseAnalysisModel {
+  const pulse = (function (value) {
+    if (typeof value === 'string')
+      try {
+        value = JSON.parse(value);
+      } catch (e) {}
+    return typeof value === 'object' ? value : {};
+  })(data.pulse);
+
+  const getSummary = (value?: string[]) => (Array.isArray(value) && value.length ? value : void 0);
+  const summary =
+    getSummary(pulse?.summary_desc?.summary) ??
+    getSummary(pulse?.summary_desc?.left?.summary) ??
+    getSummary(pulse?.summary_desc?.right?.summary) ??
+    [];
+
+  return {
+    measureId: data?.measureId,
+    hand: pulse?.hand ?? 0,
+    summaryValue: pulse?.summary,
+    summaryLabel: pulse?.summary_desc,
+    results: summary.join(','),
+  };
+}
+
 function fromTongueAnalysisModel(data: Record<string, any>): AnalysisModel {
   const exception: AnalysisException[] = [];
   const fromTongueException = fromAnalysisException(exception);

+ 1 - 0
src/request/model/report.model.ts

@@ -29,6 +29,7 @@ export function fromReportData(data: Record<string, any>) {
 
     tongue: fromAnalysisModel('tongue', data),
     face: fromAnalysisModel('face', data),
+    pulse: fromAnalysisModel('pulse', data),
 
     [ '中医证素' ]: data?.factorItems?.map?.((item: Record<string, any>) => {
       return { label: item?.factorItemName, value: item?.factorItemDescription, score: +item?.score };

+ 11 - 1
src/stores/visitor.store.ts

@@ -1,16 +1,26 @@
 import { defineStore } from 'pinia';
+import type { PulseAnalysisModel } from '@/request/model';
 
 
 export const useVisitor = defineStore('visitor', () => {
   const patientId = ref<string>();
   const resultId = ref<string>();
   const reportId = ref<string>();
+  const pulseReport = shallowRef<PulseAnalysisModel>();
 
   const $reset = () => {
     patientId.value = '';
     resultId.value = '';
     reportId.value = '';
+    pulseReport.value = void 0;
   };
 
-  return { patientId, resultId, reportId, $reset };
+  function updatePulseReport(report: PulseAnalysisModel, patient?: string) {
+    if (patientId.value?.toString() !== patient || pulseReport.value == null) {
+      if (patient) patientId.value = patient;
+      pulseReport.value = report;
+    }
+  }
+
+  return { patientId, resultId, reportId, pulseReport, $reset, updatePulseReport };
 });