فهرست منبع

fix(@six/smart-pharmacy): 智慧药事系统第一版处方详情页面修改

cmj 1 ماه پیش
والد
کامیت
beaadc9bc5

+ 15 - 0
apps/smart-pharmacy/src/api/method/dict.ts

@@ -58,3 +58,18 @@ export function listDeliveryMethodDictMethod() {
 export function listLogisticsCompanyDictMethod() {
   return listDictByCodeMethod('logistics_company');
 }
+
+/** 中药剂型字典(zyjx) */
+export function listZyjxDictMethod() {
+  return listDictByCodeMethod('zyjx');
+}
+
+/** 用药途径字典(zy_route) */
+export function listZyRouteDictMethod() {
+  return listDictByCodeMethod('zy_route');
+}
+
+/** 中药特殊煎煮法字典(mat_usage_name) */
+export function listMatUsageNameDictMethod() {
+  return listDictByCodeMethod('mat_usage_name');
+}

+ 27 - 5
apps/smart-pharmacy/src/api/model/prescription-detail.ts

@@ -7,6 +7,12 @@ const BELONG_MAP: Record<string, string> = {
   '2': '住院',
 };
 
+/** 页面「中药类型」← zhongyaoType */
+const ZHONGYAO_TYPE_MAP: Record<string, string> = {
+  '1': '饮片',
+  '2': '颗粒剂',
+};
+
 function pickValue(data: TransformData | undefined, ...keys: string[]): unknown {
   if (!data) return undefined;
   for (const key of keys) {
@@ -37,6 +43,16 @@ function toNumber(value: unknown, fallback = 0): number {
   return Number.isFinite(num) ? num : fallback;
 }
 
+function resolveEnum(
+  value: unknown,
+  map: Record<string, string>,
+  fallback = '-',
+): string {
+  const key = String(value ?? '');
+  if (!key) return fallback;
+  return map[key] ?? toDisplay(value, fallback);
+}
+
 function resolveYesNo(value: unknown): string {
   if (value === 1 || value === '1') return '是';
   if (value === 2 || value === '2') return '否';
@@ -44,6 +60,7 @@ function resolveYesNo(value: unknown): string {
   return toDisplay(value, '-');
 }
 
+/** 页面「代煎代码」展示代煎/自煎代配 ← isBehalf */
 function resolveDecoctionLabel(data: TransformData): string {
   const isBehalf = pickValue(data, 'isBehalf');
   if (isBehalf === 1 || isBehalf === '1') return '代煎';
@@ -55,6 +72,7 @@ function resolveGender(data: TransformData): string {
   const sex = pickValue(data, 'sex', 'gender');
   if (sex === 1 || sex === '1') return '男';
   if (sex === 2 || sex === '2') return '女';
+  if (sex === 0 || sex === '0') return '未知';
   return toDisplay(sex, '-');
 }
 
@@ -135,11 +153,12 @@ function fromProcessNode(item: TransformData): PrescriptionModel.ProcessFlowItem
     operator: toDisplay(pickValue(item, 'operatorName'), '-'),
     operationTime: toDisplay(pickValue(item, 'scanTime'), '-'),
     note: toDisplay(pickValue(item, 'remark'), ''),
-    water: '',
+    water:  toDisplay(pickValue(item, 'waterAddition'), ''),
     weightCheck: '',
     weight: weightText,
     hasPhoto: Boolean(photoUrl),
     photoUrl,
+    startConcentrating: toDisplay(pickValue(item, 'startConcentrating'), ''),
     deviceName: toDisplay(pickValue(item, 'deviceName'), ''),
   };
 }
@@ -178,7 +197,7 @@ export function createEmptyPrescriptionDetail(): PrescriptionModel.Detail {
       eachPackageCount: 0,
       totalCount: 0,
       decoctionMark: '',
-      decoctionTime: '',
+      packageCapacity: '',
       packageType: '',
       decoctionTimeMark: 0,
       decoctionTimeValue: 0,
@@ -255,13 +274,16 @@ export function fromPrescriptionDetail(
   };
 
   const prescriptionDetails: PrescriptionModel.DetailPrescriptionInfo = {
-    chineseMedicineType: toDisplay(pickValue(info, 'zhongyaoType'), '-'),
-    chineseMedicineForm: toDisplay(pickValue(info, 'packagingType', 'zyjx'), '-'),
+    chineseMedicineType: resolveEnum(
+      pickValue(info, 'zhongyaoType'),
+      ZHONGYAO_TYPE_MAP,
+    ),
+    chineseMedicineForm: toDisplay(pickValue(info, 'zyjx'), '-'),
     prescriptionCount: toNumber(pickValue(info, 'quantity')),
     eachPackageCount: toNumber(pickValue(info, 'packagePaste')),
     totalCount: toNumber(pickValue(info, 'totalPackagePaste')),
     decoctionMark: resolveYesNo(pickValue(info, 'thick')),
-    decoctionTime: toDisplay(pickValue(info, 'packType'), '-'),
+    packageCapacity: toDisplay(pickValue(info, 'packType'), '-'),
     packageType: toDisplay(pickValue(info, 'packingName'), '-'),
     decoctionTimeMark: toNumber(pickValue(info, 'soakTime')),
     decoctionTimeValue: toNumber(pickValue(info, 'boilTime')),

+ 4 - 1
apps/smart-pharmacy/src/api/model/prescription.ts

@@ -40,7 +40,8 @@ export namespace PrescriptionModel {
     eachPackageCount: number;
     totalCount: number;
     decoctionMark: string;
-    decoctionTime: string;
+    /** 每包容量 packType,单位 ml */
+    packageCapacity: string;
     packageType: string;
     decoctionTimeMark: number;
     decoctionTimeValue: number;
@@ -120,6 +121,7 @@ export namespace PrescriptionModel {
     hasPhoto: boolean;
     photoUrl?: string;
     deviceName?: string;
+    startConcentrating?: string;
   }
 
   export interface DetailLogisticsInfo {
@@ -232,6 +234,7 @@ export function fromPrescription(
     }),
     id,
     date:
+      data?.dealDate ??
       data?.recipeDate ??
       data?.prescriptionDate ??
       data?.createTime ??

+ 17 - 0
apps/smart-pharmacy/src/api/model/process-node-dict.ts

@@ -1,7 +1,10 @@
 import {
   listDeliveryMethodDictMethod,
   listLogisticsCompanyDictMethod,
+  listMatUsageNameDictMethod,
   listProcessNodeDictMethod,
+  listZyjxDictMethod,
+  listZyRouteDictMethod,
 } from '#/api/method/dict';
 
 import {
@@ -16,6 +19,9 @@ export { buildDictLabelMap as buildProcessNodeLabelMap };
 export { resolveDictLabel as resolveProcessNodeLabel };
 export { resolveDictLabel as resolveDeliveryMethodLabel };
 export { resolveDictLabelIgnoreCase as resolveLogisticsCompanyLabel };
+export { resolveDictLabel as resolveZyjxLabel };
+export { resolveDictLabel as resolveZyRouteLabel };
+export { resolveDictLabel as resolveMatUsageNameLabel };
 
 /** 获取流程节点字典映射(带缓存) */
 export const getProcessNodeLabelMap = createDictLabelMapGetter(
@@ -27,6 +33,17 @@ export const getDeliveryMethodLabelMap = createDictLabelMapGetter(
   listDeliveryMethodDictMethod,
 );
 
+/** 获取中药剂型字典映射(带缓存) */
+export const getZyjxLabelMap = createDictLabelMapGetter(listZyjxDictMethod);
+
+/** 获取用药途径字典映射(带缓存) */
+export const getZyRouteLabelMap = createDictLabelMapGetter(listZyRouteDictMethod);
+
+/** 获取中药特殊煎煮法字典映射(带缓存) */
+export const getMatUsageNameLabelMap = createDictLabelMapGetter(
+  listMatUsageNameDictMethod,
+);
+
 let cachedLogisticsCompanyMap: Map<string, string> | null = null;
 let loadingLogisticsCompanyPromise: Promise<Map<string, string>> | null = null;
 

+ 13 - 0
apps/smart-pharmacy/src/utils/mask-phone.ts

@@ -0,0 +1,13 @@
+/** 手机号中间四位脱敏,如 133****3825 */
+export function maskPhone(phone?: string): string {
+  if (!phone || phone === '-') return phone ?? '-';
+
+  const digits = phone.replace(/\D/g, '');
+  if (digits.length < 8) return phone;
+
+  if (digits.length >= 11) {
+    return `${digits.slice(0, 3)}****${digits.slice(-4)}`;
+  }
+
+  return `${digits.slice(0, 3)}****${digits.slice(-4)}`;
+}

+ 71 - 18
apps/smart-pharmacy/src/views/prescription/management/detail.vue

@@ -13,11 +13,18 @@ import {
   getDeliveryMethodLabelMap,
   getLogisticsCompanyLabelMap,
   getProcessNodeLabelMap,
+  getMatUsageNameLabelMap,
+  getZyjxLabelMap,
+  getZyRouteLabelMap,
   resolveDeliveryMethodLabel,
   resolveLogisticsCompanyLabel,
+  resolveMatUsageNameLabel,
   resolveProcessNodeLabel,
+  resolveZyjxLabel,
+  resolveZyRouteLabel,
 } from '#/api/model/process-node-dict';
 import { getPrescriptionDetailMethod } from '#/api';
+import { maskPhone } from '#/utils/mask-phone';
 
 const route = useRoute();
 const activeTab = ref('prescription');
@@ -47,17 +54,45 @@ function formatMoney(value?: number): string {
   return num.toFixed(2);
 }
 
+function formatPackageCapacity(value?: string): string {
+  if (!value || value === '-') return '-';
+  const text = String(value).trim();
+  if (/ml$/i.test(text)) return text;
+  return `${text}ml`;
+}
+
 function applyDictLabels(
   data: PrescriptionModel.Detail,
   processNodeMap: Map<string, string>,
   deliveryMethodMap: Map<string, string>,
   logisticsCompanyMap: Map<string, string>,
+  zyjxMap: Map<string, string>,
+  zyRouteMap: Map<string, string>,
+  matUsageNameMap: Map<string, string>,
 ): PrescriptionModel.Detail {
   return {
     ...data,
+    herbalDetails: data.herbalDetails.map((item) => ({
+      ...item,
+      specialMethod: resolveMatUsageNameLabel(
+        item.specialMethod,
+        matUsageNameMap,
+      ),
+    })),
     header: {
       ...data.header,
       status: resolveProcessNodeLabel(data.header.status, processNodeMap),
+      phone: maskPhone(data.header.phone),
+    },
+    prescriptionDetails: {
+      ...data.prescriptionDetails,
+      chineseMedicineForm: resolveZyjxLabel(
+        data.prescriptionDetails.chineseMedicineForm,
+        zyjxMap,
+      ),
+      packageCapacity: formatPackageCapacity(
+        data.prescriptionDetails.packageCapacity,
+      ),
     },
     deliveryInfo: {
       ...data.deliveryInfo,
@@ -69,6 +104,11 @@ function applyDictLabels(
         data.deliveryInfo.logisticsCompany,
         logisticsCompanyMap,
       ),
+      recipientPhone: maskPhone(data.deliveryInfo.recipientPhone),
+    },
+    usageInfo: {
+      ...data.usageInfo,
+      usageRoute: resolveZyRouteLabel(data.usageInfo.usageRoute, zyRouteMap),
     },
     processFlowDetails: data.processFlowDetails.map((item) => ({
       ...item,
@@ -95,18 +135,31 @@ async function loadDetail() {
 
   loading.value = true;
   try {
-    const [data, processNodeMap, deliveryMethodMap, logisticsCompanyMap] =
-      await Promise.all([
-        getPrescriptionDetailMethod(id),
-        getProcessNodeLabelMap(),
-        getDeliveryMethodLabelMap(),
-        getLogisticsCompanyLabelMap(),
-      ]);
+    const [
+      data,
+      processNodeMap,
+      deliveryMethodMap,
+      logisticsCompanyMap,
+      zyjxMap,
+      zyRouteMap,
+      matUsageNameMap,
+    ] = await Promise.all([
+      getPrescriptionDetailMethod(id),
+      getProcessNodeLabelMap(),
+      getDeliveryMethodLabelMap(),
+      getLogisticsCompanyLabelMap(),
+      getZyjxLabelMap(),
+      getZyRouteLabelMap(),
+      getMatUsageNameLabelMap(),
+    ]);
     detail.value = applyDictLabels(
       data,
       processNodeMap,
       deliveryMethodMap,
       logisticsCompanyMap,
+      zyjxMap,
+      zyRouteMap,
+      matUsageNameMap,
     );
   } finally {
     loading.value = false;
@@ -172,7 +225,7 @@ watch(prescriptionId, loadDetail, { immediate: true });
           <Descriptions.Item label="代煎中心" :label-style="{ width: '120px' }">
             {{ header.decoctionCenter }}
           </Descriptions.Item>
-          <Descriptions.Item label="代煎代" :label-style="{ width: '120px' }">
+          <Descriptions.Item label="代煎代" :label-style="{ width: '120px' }">
             <span
               class="rounded bg-blue-100 px-2 py-0.5 text-sm text-blue-700"
             >
@@ -214,11 +267,11 @@ watch(prescriptionId, loadDetail, { immediate: true });
                   <Descriptions.Item label="总包数">
                     {{ prescriptionDetails.totalCount }} 包
                   </Descriptions.Item>
-                  <Descriptions.Item label="煎标记">
+                  <Descriptions.Item label="煎标记">
                     {{ prescriptionDetails.decoctionMark }}
                   </Descriptions.Item>
-                  <Descriptions.Item label="煎药时间">
-                    {{ prescriptionDetails.decoctionTime }}
+                  <Descriptions.Item label="每包容量">
+                    {{ prescriptionDetails.packageCapacity }}
                   </Descriptions.Item>
                   <Descriptions.Item label="包装类型">
                     {{ prescriptionDetails.packageType }}
@@ -451,18 +504,18 @@ watch(prescriptionId, loadDetail, { immediate: true });
                             <span v-else>有</span>
                           </span>
                         </div>
-                        <div v-if="item.water" class="text-xs text-gray-500">
-                          加水量: {{ item.water }}
+                        <!-- <div v-if="item.water" class="text-xs text-gray-500">
+                          加水量: {{ item.water }}ml
                         </div>
                         <div v-if="item.weightCheck" class="text-xs text-gray-500">
                           复核重量: {{ item.weightCheck }}
                         </div>
-                        <div v-if="item.weight" class="text-xs text-gray-500">
-                          实际重量: {{ item.weight }}
-                        </div>
-                        <div v-if="item.deviceName" class="text-xs text-gray-500">
+                        <div v-if="item.startConcentrating" class="text-xs text-gray-500">
+                          开始浓缩药量: {{ item.startConcentrating }}ml
+                        </div> -->
+                        <!-- <div v-if="item.deviceName" class="text-xs text-gray-500">
                           设备: {{ item.deviceName }}
-                        </div>
+                        </div> -->
                         <div v-if="item.note" class="mt-1 text-xs text-gray-500">
                           备注: {{ item.note }}
                         </div>