<script setup lang="ts">
import {computed, onBeforeUnmount, onMounted, ref, watch} from 'vue';

import {Page, useVbenDrawer, useVbenModal} from '@vben/common-ui';
import {useUserStore} from '@vben/stores';

import {
  BookOutlined,
  ClearOutlined,
  DeleteTwoTone,
  FileTextOutlined,
  HistoryOutlined,
  MedicineBoxOutlined,
  CheckCircleFilled,
  MenuFoldOutlined,
  MenuUnfoldOutlined,
  PlusOutlined,
  QrcodeOutlined,
  ReloadOutlined,
  RobotOutlined,
  UserAddOutlined,
  SaveOutlined,
  StopOutlined,
  SwapOutlined,
  UserOutlined,
} from '@ant-design/icons-vue';
import {
  Button,
  Card,
  Col,
  Empty,
  Image,
  ImagePreviewGroup,
  Input,
  InputNumber,
  message,
  RadioButton,
  RadioGroup,
  Row,
  Select,
  SelectOption,
  Modal as AntModal,
  Tag,
  Tabs,
  TabPane,
  Textarea,
  notification,
  Spin,
} from 'ant-design-vue';
import {debounce} from 'lodash-es'; // 或者使用自定义防抖函数

import {getRegisterStatus} from '#/util/tool';
import {
  useVipPermission,
  type StoreVipInfo,
} from '#/utils/vip';
import MedicalRecordPanel from '#/views/doctor/medical-record/MedicalRecordPanel.vue';
import EntryKeywordBubble from '#/views/doctor/medical-record/components/EntryKeywordBubble.vue';
import CommonDxOrderChips from '#/views/doctor/medical-record/components/CommonDxOrderChips.vue';
import { saveMedicalRecord } from '#/views/doctor/medical-record/api';
import {
  clearMedicalRecordDraft,
  loadMedicalRecordDraft,
  loadRxMrTab,
  saveRxMrTab,
} from '#/views/doctor/medical-record/utils/localDraft';
import {
  addWestPrescription, checkChineseMedicineConflictApi,
  endOfDiagnosisApi,
  getDrugUseList,
  getMyStoreListApi,
  getCurrentStoreTypeApi,
  getPrescriptionTypeOptionsApi,
  getPatientItem,
  getPatientList,
  getPrescriptionInfoApi,
  getProcessRuleList,
  getProductListDoctorReception,
  receptionApi,
  applySpecialPrescriptionApi,
  switchStoreApi,
  withdrawPrescriptionApi,
} from '#/views/doctor/doctor-reception/api';

import SpecialPrescriptionImportCard from './components/SpecialPrescriptionImportCard.vue';
import PatientBriefBar from './components/PatientBriefBar.vue';
import PatientInfoDrawer from './components/PatientInfoDrawer.vue';
import PatientPrescriptionHistoryDrawer from './components/PatientPrescriptionHistoryDrawer.vue';
import PatientMedicalRecordDrawer from '#/views/doctor/medical-record/components/PatientMedicalRecordDrawer.vue';
import PrescriptionDetail from './components/PrescriptionDetail.vue';
import WesternModal from './components/WesternModal.vue';
import SimpleProductModal from './components/SimpleProductModal.vue';
import RefusalOfTreatmentModal
  from "#/views/doctor/doctor-reception/components/RefusalOfTreatmentModal.vue";
import CreateUserPatientModal from './components/CreateUserPatientModal.vue';
import ClaimQrcodeModal from './components/ClaimQrcodeModal.vue';
import ProxyPayQrcodeModal from './components/ProxyPayQrcodeModal.vue';
// 常用方选择弹窗组件
import CommonPrescriptionModal from './components/CommonPrescriptionModal.vue';
import GoldenFormulaModal from './components/GoldenFormulaModal.vue';
import AiPrescriptionDrawer from './components/AiPrescriptionDrawer.vue';
// 确认模态框组件
import ConfirmModal from './components/ConfirmModal.vue';
// 信息提示模态框组件
import InfoModal from '#/components/modal/InfoModal.vue';
import SensitiveText from '#/components/sensitive-text/SensitiveText.vue';
import { detailDoctorOrderToText } from '#/utils/prescriptionDoctorOrder';
// 药品搜索选择组件
import { DrugSearchSelect } from '#/components/drug-search-select';
// 中药药名气泡（对齐诊断/医嘱浮层交互）
import { ChineseDrugNameBubble } from '#/components/chinese-drug-name-bubble';
// 保存常用方API
import {
  saveChineseCommonPrescriptionApi,
  saveWestCommonPrescriptionApi,
} from '#/views/doctor/settings/api';
// 转诊相关
import TransferPrescriptionCard from '#/views/doctor/online-consultation/components/TransferPrescriptionCard.vue';
import SalespersonTransferDrawer from '#/views/doctor/doctor-reception/components/SalespersonTransferDrawer.vue';
import { getTransferPrescriptionByRegisterApi } from '#/views/business/chat/api/transferPrescription';
import { getSalespersonTransferByRegisterApi, prepareDoctorImportApi } from '#/views/business/salesperson-transfer-prescription/api';
import {
  registerDoctorTransferImportHandler,
  unregisterDoctorTransferImportHandler,
} from '#/views/doctor/doctor-reception/composables/useDoctorReceptionTransferImport';
import { parseSalespersonTransferDrugList } from '#/views/doctor/doctor-reception/utils/parseSalespersonTransferDrugList';
import {
  calcItemMarginPercent,
  calcTotalMarginPercent,
  isSeeRateEnabled,
} from '#/utils/chinesePrescriptionMargin';
import OrderPricePercentAdjustDrawer from '#/views/business/order/components/OrderPricePercentAdjustDrawer.vue';
import { useOrderPriceAdjust } from '#/composables/useOrderPriceAdjust';
import {
  applyRatioToDrugs,
  formatPriceDiscountLabel,
  normalizeQuickOptions,
} from '#/utils/pricePercentAdjust';
import { calculateChineseProductPriceLikeBackend, calculateProcessingFee, formatPriceDisplay, parsePriceValue } from '#/utils/formatPrice';
import {
  applySingleChildProcessRuleAutoSelect,
  resolveProcessRuleLoadedLevel,
} from '#/utils/processRuleCascade';
import ChineseMedicineConfig, { type ChineseMedicineConfigChange } from './components/ChineseMedicineConfig.vue';

interface Patient {
  id: number;
  name: string;
  mobile: string;
  status: number;
  user_patient?: {
    id: number;
    name: string;
    age?: number;
    sex?: number;
    mobile?: string;
  };
  special_prescription_patient_record?: {
    id: number;
    status: number;
    special_prescription_id: number;
    dose_count: number;
    sku_id?: number;
    sku_name?: string;
    special_prescription?: {
      id: number;
      name: string;
      cover_image?: string;
    };
  };
}

interface UserPatientHealthInquiry {
  id: number;
  user_patient_id: number;
  liver_function: number;
  renal_function: number;
  liver_index: string;
  renal_index: string;
  present_status?: number;
  present_history?: string;
  person_history: string;
  allergic_history: string;
  person_status: number;
  allergic_status: number;
  family_status: number;
  family_history: string;
  epidemic_status?: number;
  epidemic_history?: string;
  personal_status?: number;
  personal_history?: string;
  menstrual_status?: number;
  menstrual_history?: string;
  marital_status?: number;
  marital_history?: string;
  is_delete: number;
}

const tabType = ref(0);
/** 处方|病历 Tab（v-show 切换，保持两侧状态；按挂号落本地） */
const rxMrTab = ref<'rx' | 'mr'>('rx');
const medicalRecordPanelRef = ref<InstanceType<typeof MedicalRecordPanel> | null>(null);
/** 当前接诊挂号对应履约诊所 VIP（来自 getCurrentStoreType） */
const receptionVip = ref<StoreVipInfo | null>(null);
/** 统一用全局 useVipPermission，避免各处手写 hasVipPermission 字符串 */
const {
  canUseMedicalRecord,
  canUseAiMedicalRecord,
  canUseAiPrescription,
  canUseGoldenFormula,
} = useVipPermission(receptionVip);

watch(rxMrTab, (tab) => {
  const rid = getRegisterId();
  if (rid) saveRxMrTab(rid, tab);
});

/** 按挂号恢复处方|病历 Tab */
function restoreRxMrTab(registerId: number) {
  if (!canUseMedicalRecord.value) {
    rxMrTab.value = 'rx';
    return;
  }
  const saved = loadRxMrTab(registerId);
  rxMrTab.value = saved || 'rx';
}
const category = ref(1);
const listType = ref(1);
const receptionStatus = ref(0);
const updateTabType = ref(false);
// 患者数据
const patients = ref<Patient[]>([]);

// 药品使用相关数据
const drugUseNum = ref([]);
const drugUseFrequency = ref([]);
const drugUseType = ref([]);
const drugUnit = ref([]);
const drugTime = ref([]);
const drugUseWay = ref([]);
const myStoreList = ref([]);

/**
 * 获取我的诊所列表
 */
function getMyStoreList() {
  getMyStoreListApi().then((res) => {
    myStoreList.value = res;
  });
}

getMyStoreList();

/** 开方种类权限校验中 */
const prescriptionTypeLoading = ref(false);
/** 当前门店是否有可开方种类 */
const prescriptionTypeAllowed = ref(true);
const prescriptionTypeDenyMessage = ref('');

/** 同参处方类型请求去重（setup + selectPatient 易双打） */
let prescriptionTypeInflight: {
  key: string;
  promise: Promise<boolean>;
} | null = null;

/** 拉取处方类型列表与默认选中；无权限时清空并返回 false */
async function loadPrescriptionTypeOptions(registerId?: number) {
  const key = `${Number(registerId || 0)}_${Number(myStoreId.value || 0)}`;
  if (prescriptionTypeInflight?.key === key) {
    return prescriptionTypeInflight.promise;
  }
  prescriptionTypeLoading.value = true;
  const run = (async () => {
  try {
    const params: { register_id?: number; store_id?: number } = {};
    if (registerId) params.register_id = registerId;
    if (myStoreId.value) params.store_id = myStoreId.value;
    const res = await getPrescriptionTypeOptionsApi(params);
    const list = Array.isArray(res?.list) ? res.list : [];
    categories.value = list.map((item) => ({
      value: Number(item.value),
      label: item.label || '',
      icon: item.icon || '',
      icon_text: item.icon_text || '',
    }));
    const def = Number(res?.default) || 0;
    prescriptionTypeDefault.value = def;
    const allowed = res?.allowed !== false && list.length > 0;
    prescriptionTypeAllowed.value = allowed;
    prescriptionTypeDenyMessage.value = allowed
      ? ''
      : (res?.message || '当前门店未开通开方权限');
    if (allowed && def && !categories.value.some((c) => c.value === activeCategory.value)) {
      activeCategory.value = def;
    }
    return allowed;
  } catch (e) {
    console.error('加载处方类型失败', e);
    categories.value = [];
    prescriptionTypeAllowed.value = false;
    prescriptionTypeDenyMessage.value = '处方类型加载失败，请稍后重试';
    message.warning('处方类型加载失败，请稍后重试');
    return false;
  } finally {
    prescriptionTypeLoading.value = false;
    if (prescriptionTypeInflight?.key === key) {
      prescriptionTypeInflight = null;
    }
  }
  })();
  prescriptionTypeInflight = { key, promise: run };
  return run;
}

/** 将当前分类 Tab 滚入可视区 */
function focusActiveCategoryTab() {
  const el = document.getElementById(`rx-pc-tab-${activeCategory.value}`);
  el?.scrollIntoView({ behavior: 'smooth', inline: 'center', block: 'nearest' });
}

const userStore = useUserStore();
const myStoreId = ref(userStore.userInfo.store_id);
/** 当前选中门店名称，供开方抬头居中展示 */
const currentStoreName = computed(() => {
  const list = myStoreList.value as Array<{ id: number; name?: string }>;
  const hit = list.find((s) => Number(s.id) === Number(myStoreId.value));
  return hit?.name || '';
});
loadPrescriptionTypeOptions();
/** 当前取价门店是否允许查看毛利率（0/1） */
const seeRate = ref(0);
/** 开方是否可选医保（0=仅自费） */
const allowInsuranceCategory = ref(0);
/** 是否开启订单百分比调价 */
const priceAdjustEnabled = ref(false);
/** 开方购物车整单价格比例，100=原价 */
const priceDiscount = ref(100);
const { config: priceAdjustConfig, loadByStoreId, applyRatioToDrugs: applyRatioDrugs } = useOrderPriceAdjust();
const [PriceAdjustDrawer, priceAdjustDrawerApi] = useVbenDrawer({
  connectedComponent: OrderPricePercentAdjustDrawer,
});

/** 推广员传方导入关联ID */
const salespersonTransferPrescriptionId = ref(0);
const salespersonTransferDrawerOpen = ref(false);
const hasSalespersonTransfer = ref(false);

/**
 * 当前接诊挂号 ID
 * 优先用响应式的 selectPatientId；勿只读 localStorage（computed 不追踪 storage，会卡死旧挂号 id）
 */
const doctorReceptionRegisterId = computed(() => {
  if (selectPatientId.value > 0) {
    return selectPatientId.value;
  }
  if (typeof window === 'undefined' || !window.localStorage) {
    return 0;
  }
  const raw = window.localStorage.getItem('doctorReception-id') || '0';
  // 兼容历史 JSON.stringify(number) 写入
  try {
    const parsed = JSON.parse(raw);
    const n = Number(parsed);
    if (Number.isFinite(n) && n > 0) return n;
  } catch {
    /* ignore */
  }
  return Number.parseInt(raw, 10) || 0;
});

/** 门店类型接口短时缓存，供毛利率 / 转诊提示共用，避免进页双打 */
let storeTypeCache: { key: string; data: any; at: number } | null = null;
const STORE_TYPE_CACHE_TTL = 30_000;

async function getCurrentStoreTypeCached(params: {
  register_id?: number;
  store_id?: number;
}) {
  const key = `${Number(params.store_id || 0)}_${Number(params.register_id || 0)}`;
  const now = Date.now();
  if (
    storeTypeCache &&
    storeTypeCache.key === key &&
    now - storeTypeCache.at < STORE_TYPE_CACHE_TTL
  ) {
    return storeTypeCache.data;
  }
  const data = await getCurrentStoreTypeApi(params);
  storeTypeCache = { key, data, at: now };
  return data;
}

async function fetchStoreSeeRate() {
  try {
    const registerId = Number.parseInt(
      localStorage.getItem('doctorReception-id') || '0',
      10,
    );
    const params: { register_id?: number; store_id?: number } = {
      store_id: myStoreId.value,
    };
    if (registerId > 0) {
      params.register_id = registerId;
    }
    const res = await getCurrentStoreTypeCached(params);
    seeRate.value = Number(res?.see_rate ?? 0);
    allowInsuranceCategory.value = Number(res?.allow_insurance_category ?? 0);
    priceAdjustEnabled.value = Number(res?.enable_order_price_percent_adjust ?? 0) === 1;
    // 有挂号时 vip 已按履约诊所返回，供病历/AI/金方门控
    receptionVip.value = res?.vip ?? null;
    await loadByStoreId(myStoreId.value);
    if (allowInsuranceCategory.value !== 1) {
      category.value = 1;
    }
  } catch (error) {
    console.error('获取毛利率权限失败:', error);
  }
}

async function checkSalespersonTransfer() {
  const registerId = Number.parseInt(
    localStorage.getItem('doctorReception-id') || '0',
    10,
  );
  if (!registerId || activeCategory.value !== 1) {
    hasSalespersonTransfer.value = false;
    return;
  }
  try {
    const res = await getSalespersonTransferByRegisterApi(registerId);
    hasSalespersonTransfer.value = Array.isArray(res) && res.length > 0;
  } catch {
    hasSalespersonTransfer.value = false;
  }
}

function handleSalespersonTransferImport(payload: {
  transferId: number;
  clinical_diagnose: string;
  doctor_order: string;
  drugList: any[];
  dosage?: number;
  dayDosage?: number;
}) {
  salespersonTransferPrescriptionId.value = payload.transferId;
  diagnosis.value = payload.clinical_diagnose || '';
  medicalAdvice.value = payload.doctor_order || '';
  activeCategory.value = 1;
  tabType.value = 2;
  if (payload.dosage != null) {
    dosage.value = Number(payload.dosage) || 7;
  }
  if (payload.dayDosage != null) {
    dayDosage.value = Number(payload.dayDosage) || 2;
  }
  packageMethodId.value = 2;
  currentDrugs.value = payload.drugList.map((drug: any) => ({
    index_id: drug.index_id ?? drug.drug_id ?? drug.id,
    id: drug.drug_id || drug.id,
    drug_id: drug.drug_id || drug.id,
    drug_name: drug.drug_name || drug.name,
    name: drug.drug_name || drug.name,
    number: drug.number || 1,
    way_id: drug.way_id || 0,
    price: drug.price ?? 0,
    buy_price: drug.buy_price,
  }));
  updateLocalStorage();
  message.success('传方已导入，请确认后发送处方');
}

/** 悬浮窗触发导入：拉取补价后的传方数据并写入当前患者 */
async function handleFloatTransferImport(payload: {
  transferId: number;
  registerId: number;
}) {
  try {
    const item = await prepareDoctorImportApi(payload.transferId, payload.registerId);
    const drugList = parseSalespersonTransferDrugList(item);
    if (!drugList.length) {
      message.warning('传方药品为空');
      return;
    }
    const content = item.content ?? {};
    handleSalespersonTransferImport({
      transferId: payload.transferId,
      clinical_diagnose: item.clinical_diagnose || content.clinical_diagnose || '',
      doctor_order: item.doctor_order || content.doctor_order || '',
      drugList,
      dosage: content.dosage ?? item.dosage,
      dayDosage: content.day_dosage ?? item.day_dosage,
    });
  } catch (e: any) {
    message.error(e?.message || '导入失败');
  }
}

onMounted(() => {
  registerDoctorTransferImportHandler(handleFloatTransferImport);
});

onBeforeUnmount(() => {
  unregisterDoctorTransferImportHandler();
});

watch(myStoreId, () => {
  fetchStoreSeeRate();
});

const chineseGrossMarginPercent = computed(() => {
  if (!isSeeRateEnabled(seeRate.value) || activeCategory.value !== 1) {
    return null;
  }
  return calcTotalMarginPercent(currentDrugs.value, dosage.value);
});

function getChineseItemMargin(drug: {
  price?: number | string;
  buy_price?: number | string;
}) {
  if (!isSeeRateEnabled(seeRate.value)) {
    return null;
  }
  return calcItemMarginPercent(drug.price, drug.buy_price);
}

fetchStoreSeeRate();
// userStore.userInfo?.nick_name

/**
 * 获取患者列表
 */
function getPatientListByReception() {
  getPatientList({
    type: listType.value,
  }).then((res) => {
    patients.value = res;

    if (updateTabType.value === false) {
      const activePatientId = localStorage.getItem(`doctorReception-id`);

      if (activePatientId !== null) {
        activeCategory.value =
          Number.parseInt(
            localStorage.getItem(`activeCategory${activePatientId}`),
          ) || 1;
        // 从patients.value中找到当前选中的id并且触发selectPatient方法
        patients.value.forEach((patient) => {
          if (patient.id === Number.parseInt(activePatientId)) {
            selectPatient(patient, false);
            updateTabType.value = true;
          }
        });
      }
    }
  });
}

function updatePatientList() {
  updateTabType.value = true;
  getPatientListByReception();
}

/** 患者列表手动刷新中（与轮询区分，避免连点） */
const patientListRefreshing = ref(false);

/**
 * 手动刷新左侧患者列表
 * 为什么单独抽：工具栏刷新需 loading，且不改动当前/历史 tab 的 updateTabType 语义
 */
function refreshPatientList() {
  if (patientListRefreshing.value) return;
  patientListRefreshing.value = true;
  getPatientList({
    type: listType.value,
  })
    .then((res) => {
      patients.value = res;
    })
    .finally(() => {
      patientListRefreshing.value = false;
    });
}

getPatientListByReception();
// 每 30 秒轮询刷新患者列表
setInterval(getPatientListByReception, 30_000);

// 药品分类（后端下发；失败时用本地兜底）
const categories = ref([
  {label: '中药', value: 1, icon: '', icon_text: ''},
  {label: '中成(西)药', value: 2, icon: '', icon_text: ''},
  {label: '保健食品', value: 3, icon: '', icon_text: ''},
  {label: '产品服务包', value: 5, icon: '', icon_text: ''},
  {label: '非药品', value: 6, icon: '', icon_text: ''},
  {label: '医疗器械', value: 7, icon: '', icon_text: ''},
]);
/** 后端默认处方类型 */
const prescriptionTypeDefault = ref(2);

// 当前状态
const activePatient = ref<null | Patient>(null);
const patientInfo = ref<null | Patient>(null);
const userPatientHealthInquiry = ref<null | UserPatientHealthInquiry>(null);
const activeCategory = ref(2);
/** 仅中药/西药支持常用方模板（保健食品不提供常用方） */
const canUseCommonPrescription = computed(() =>
  [1, 2].includes(activeCategory.value),
);
/** 当前挂号是否有关联的特色方选方记录（可重复导入） */
const hasSpecialPrescriptionRecord = computed(
  () => !!patientInfo.value?.special_prescription_patient_record,
);
const specialPrescriptionRecord = computed(
  () => patientInfo.value?.special_prescription_patient_record ?? null,
);
/** 导入卡片规格：SKU 名或单剂 */
function resolveSpecialPrescriptionPurchaseLabel(
  record?: { sku_id?: number; sku_name?: string } | null,
) {
  if (!record) return '';
  return Number(record.sku_id) > 0
    ? (record.sku_name || 'SKU套餐')
    : '单剂';
}
const specialPrescriptionPurchaseLabel = computed(() =>
  resolveSpecialPrescriptionPurchaseLabel(specialPrescriptionRecord.value),
);
const applyingSpecialPrescription = ref(false);
/** 医生已导入的特色方 ID，仅 >0 时提交走特色方计价 */
const appliedSpecialPrescriptionId = ref(0);
/** apply 返回的 SKU/贴数套餐总价，用于底部合计 */
const appliedSpecialPrescriptionExpectedTotal = ref<number | null>(null);
function clearAppliedSpecialPrescription() {
  appliedSpecialPrescriptionId.value = 0;
  appliedSpecialPrescriptionExpectedTotal.value = null;
}
/** 已应用特色方时锁定药方（不可改删增） */
const isSpecialPrescriptionCartLocked = computed(
  () => appliedSpecialPrescriptionId.value > 0,
);
const SP_CART_LOCK_MSG = '特色方药方不可修改，请先清空药方';
/** 特色方锁定中则提示并返回 true */
function guardSpecialPrescriptionCartEdit(): boolean {
  if (isSpecialPrescriptionCartLocked.value) {
    message.warning(SP_CART_LOCK_MSG);
    return true;
  }
  return false;
}
const diagnosis = ref('');
const medicalAdvice = ref('');
const treatmentPrice = ref(0);
const selectPatientId = ref(0);
const ruleType = ref(1);
const prescriptionList = ref([]);
const drugList = ref([]);

// ==================== 保存常用方相关状态 ====================
/** 保存常用方弹窗是否显示 */
const showSaveCommonPrescriptionModal = ref(false);
/** 常用方名称输入 */
const commonPrescriptionName = ref('');
/** 是否正在保存常用方 */
const isSavingCommonPrescription = ref(false);

// ==================== 转诊相关状态 ====================
/** 转诊处方信息 */
const transferPrescription = ref(null);
/** 是否正在加载转诊信息 */
const loadingTransfer = ref(false);

/**
 * 获取药品使用方式列表
 */
function getDrugUseListByWesternModal() {
  getDrugUseList().then((res) => {
    // 更新各种药品使用相关数据
    drugUseNum.value = res.drug_use_num;
    drugUseFrequency.value = res.drug_use_frequency;
    drugUseType.value = res.drug_use_type;
    drugUnit.value = res.drug_unit;
    drugTime.value = res.drug_time;
    drugUseWay.value = res.drug_use_way;
    // drugProcessRule.value = res.drug_process_rule;
  });
}

getDrugUseListByWesternModal();

const selectProductIndex = ref(-1);

function selectProductChange(id) {
  selectProductIndex.value = id;
}

/**
 * 选择中药用法
 * @param id
 */
function selectDrugUseWayChange(id) {
  if (guardSpecialPrescriptionCartEdit()) return;
  if (
    selectProductIndex.value < 0 ||
    selectProductIndex.value >= currentDrugs.value.length
  ) {
    return;
  }
  const targetDrug = currentDrugs.value[selectProductIndex.value];
  if (!targetDrug) {
    return;
  }
  targetDrug.way_id = id;
  targetDrug.use_ways = drugUseWay.value.find((value) => value.id === id);
  updateLocalStorage();
}

/**
 * 计算商品总价
 */
const totalProductCost = computed(() => {
  const expected = appliedSpecialPrescriptionExpectedTotal.value;
  if (
    expected != null
    && !Number.isNaN(Number(expected))
    && Number(expected) > 0
  ) {
    return Number(expected);
  }
  if (currentDrugs.value.length === 0) {
    return 0;
  }
  // 中药：与后端 PrescriptionService / format_price 口径一致
  if (activeCategory.value === 1) {
    return calculateChineseProductPriceLikeBackend(
      currentDrugs.value,
      dosage.value,
    );
  }
  return currentDrugs.value.reduce(
    (sum, drug) => sum + drug.price * (drug.select_number || 1),
    0,
  );
});
/**
 * 计算总价
 */
const totalCost = computed(() => {
  return totalProductCost.value + processingFee.value;
});

/**
 * 计算加工费（委托调剂）
 */
const processingFee = computed(() => {
  if (ruleType.value !== 2 || currentDrugs.value.length === 0) {
    return 0;
  }
  const processRule = childProcessRuleList.value.find(
    (item) => item.id === childProcessRuleId.value,
  );
  const totalQty = currentDrugs.value.reduce(
    (sum, drug) => sum + parsePriceValue(drug.number ?? 1),
    0,
  );
  return calculateProcessingFee(processRule, dosage.value, totalQty);
});

const visible = ref<boolean>(false);
const previewImage = ref([]);
/**
 * 说明书预览
 * @param value
 * @param instruction
 */
const setVisible = (value, instruction = ''): void => {
  previewImage.value = [];
  if (instruction == '') {
    message.error('该产品没有说明书！');
  } else {
    if (typeof instruction === 'string') {
      // 如果有逗号，则进行分割 没有则追加到previewImage
      if (instruction.includes(',')) {
        instruction = instruction.split(',');
        previewImage.value = instruction;
      } else {
        previewImage.value.push(instruction);
      }
    }
    visible.value = value;
  }
};

/**
 * 处方发送成功页数据
 * 发送成功后右区切到成功面板（tabType=3）展示本单摘要，
 * 「代付收款」直接用这里的 order_id 拉代付码，医生不用再去处方记录抽屉里找
 */
const sentPrescriptionInfo = ref<any>(null);

/**
 * 选择患者：已接诊直接进开方工作台；未接诊进轻量接诊操作区（不再进旧患者信息大页）
 */
const selectPatient = async (patient: Patient, isUpdateTabType = true) => {
  clearAppliedSpecialPrescription();
  selectPatientId.value = patient.id;
  receptionStatus.value = patient.status;
  if (isUpdateTabType === true) {
    // 已接诊 → 工作台；待接诊 → 轻量接诊区
    tabType.value = patient.status === 2 ? 2 : 1;
  } else {
    // 获取doctorReception-type并赋值
    if (localStorage.getItem(`doctorReception-type`) !== null) {
      tabType.value = Number.parseInt(
        localStorage.getItem(`doctorReception-type`) || '0',
      );
    }
    // 状态与本地缓存纠偏：已接诊不应停在旧信息页
    if (patient.status === 2 && tabType.value === 1) {
      tabType.value = 2;
    }
    if (patient.status !== 2 && tabType.value === 2) {
      tabType.value = 1;
    }
    // 发送成功页数据不跨刷新：缓存里是成功页但数据已丢时，按接诊状态回落
    if (tabType.value === 3 && !sentPrescriptionInfo.value) {
      tabType.value = patient.status === 2 ? 2 : 1;
    }
  }
  activePatient.value = patient.user_patient;

  const registerId = patient.id;
  // 先拉类型，再恢复草稿/默认 Tab
  const allowed = await loadPrescriptionTypeOptions(registerId);
  if (!allowed) {
    message.error(prescriptionTypeDenyMessage.value || '当前门店未开通开方权限');
  }
  // 优先恢复完整草稿（诊断、医嘱、诊疗费、中药配置等）
  const hasDraft = await restoreReceptionDraft(registerId);
  if (!hasDraft) {
    const savedCategory = localStorage.getItem(`activeCategory${registerId}`);
    if (savedCategory) {
      activeCategory.value = Number.parseInt(savedCategory);
    } else {
      const chineseData = localStorage.getItem(getStorageKey(registerId, 1));
      const westData = localStorage.getItem(getStorageKey(registerId, 2));
      if (chineseData && JSON.parse(chineseData).length > 0) {
        activeCategory.value = 1;
      } else if (westData && JSON.parse(westData).length > 0) {
        activeCategory.value = 2;
      } else if (prescriptionTypeDefault.value) {
        // 无草稿时使用后端下发的默认类型
        activeCategory.value = prescriptionTypeDefault.value;
      }
    }
  }
  // 恢复的 Tab 若不在权限内，强制切到默认
  if (
    allowed &&
    categories.value.length &&
    !categories.value.some((c) => c.value === activeCategory.value)
  ) {
    activeCategory.value = prescriptionTypeDefault.value || categories.value[0].value;
  }

  // 如果恢复的处方类型是中药，检测并显示转诊提示
  if (activeCategory.value === 1) {
    checkAndShowTransferTip();
    checkSalespersonTransfer();
  }
  // 恢复处方|病历 Tab
  restoreRxMrTab(registerId);

  getPatientItem(patient.id).then((value) => {
    patientInfo.value = value;
    userPatientHealthInquiry.value = value.user_patient_health_inquiry;
    prescriptionList.value = value.prescription;
    // 详情里的就诊人字段更全（含手机脱敏明文），同步到顶栏
    if (value?.user_patient) {
      activePatient.value = value.user_patient;
    }
  });

  // 存纯数字字符串，避免 JSON.stringify 造成读取歧义
  localStorage.setItem(`doctorReception-id`, String(patient.id));
  // 切换患者后 AI 采纳关联失效，重置避免跨患者误关联
  aiRxGenerationId.value = 0;
  getCurrentDrugs();
};

// 数量增加
const increment = (index: number) => {
  if (guardSpecialPrescriptionCartEdit()) return;
  currentDrugs.value[index].select_number++;
  saveToLocalStorage();
};

// 数量减少
const decrement = (index: number) => {
  if (guardSpecialPrescriptionCartEdit()) return;
  if (currentDrugs.value[index].select_number > 1) {
    currentDrugs.value[index].select_number--;
    saveToLocalStorage();
  }
};

// 切换药品用法编辑状态
const toggleEditDrug = (index: number) => {
  if (guardSpecialPrescriptionCartEdit()) return;
  currentDrugs.value[index].isEditing = !currentDrugs.value[index].isEditing;
};

// 保存药品用法编辑
const saveEditDrug = (index: number) => {
  const drug = currentDrugs.value[index];
  // 更新 ID 字段
  drug.type_id = drug.use_type?.id;
  drug.frequency_id = drug.use_frequency?.id;
  drug.time_id = drug.use_num?.id;
  drug.unit_id = drug.unit?.id;
  drug.isEditing = false;
  updateLocalStorage();
};

// 更新药品用法字段
const updateDrugUsage = (index: number, field: string, value: any) => {
  currentDrugs.value[index][field] = value;
};

/**
 * 获取当前挂号 ID（与 doctorReception-id 一致，用于 localStorage 键）
 */
function getRegisterId(): number {
  if (selectPatientId.value > 0) {
    return selectPatientId.value;
  }
  return Number.parseInt(localStorage.getItem('doctorReception-id') || '0', 10);
}

/** 接诊草稿 key：诊断、医嘱、诊疗费、中药配置等 */
function getDraftKey(registerId: number | string) {
  return `doctorReceptionDraft_${registerId}`;
}

/** 保存接诊表单草稿（刷新后恢复） */
function saveReceptionDraft() {
  const registerId = getRegisterId();
  if (!registerId) return;
  localStorage.setItem(
    getDraftKey(registerId),
    JSON.stringify({
      activeCategory: activeCategory.value,
      diagnosis: diagnosis.value,
      medicalAdvice: medicalAdvice.value,
      treatmentPrice: treatmentPrice.value,
      ruleType: ruleType.value,
      packageMethodId: packageMethodId.value,
      processRuleId: processRuleId.value,
      childProcessRuleId: childProcessRuleId.value,
      processRuleNoteId: processRuleNoteId.value,
      dosage: dosage.value,
      dayDosage: dayDosage.value,
      priceDiscount: priceDiscount.value,
    }),
  );
  localStorage.setItem(`activeCategory${registerId}`, String(activeCategory.value));
}

/** 恢复接诊草稿 */
async function restoreReceptionDraft(registerId: number) {
  if (!registerId) return false;
  const raw = localStorage.getItem(getDraftKey(registerId));
  if (!raw) return false;
  try {
    const draft = JSON.parse(raw);
    if (draft.activeCategory != null) {
      activeCategory.value = Number(draft.activeCategory);
    }
    diagnosis.value = draft.diagnosis ?? '';
    medicalAdvice.value = draft.medicalAdvice ?? '';
    treatmentPrice.value = draft.treatmentPrice ?? 0;
    ruleType.value = Number(draft.ruleType ?? 1);
    if (draft.packageMethodId != null) {
      packageMethodId.value = Number(draft.packageMethodId);
    }
    if (draft.processRuleId != null) {
      processRuleId.value = Number(draft.processRuleId);
    }
    if (draft.childProcessRuleId != null) {
      childProcessRuleId.value = Number(draft.childProcessRuleId);
    }
    if (draft.processRuleNoteId != null) {
      processRuleNoteId.value = Number(draft.processRuleNoteId);
    }
    if (draft.dosage != null) dosage.value = draft.dosage;
    if (draft.dayDosage != null) dayDosage.value = draft.dayDosage;
    if (draft.priceDiscount != null) priceDiscount.value = draft.priceDiscount;
    if (activeCategory.value === 1 && ruleType.value === 2) {
      await hydrateChineseProcessRuleListsFromConfig();
    }
    return true;
  } catch {
    return false;
  }
}

function clearReceptionDraft(registerId?: number) {
  const id = registerId || getRegisterId();
  if (id) {
    localStorage.removeItem(getDraftKey(id));
    clearMedicalRecordDraft(String(id));
  }
}

let draftSaveTimer: ReturnType<typeof setTimeout> | null = null;
function debouncedSaveReceptionDraft() {
  if (draftSaveTimer) clearTimeout(draftSaveTimer);
  draftSaveTimer = setTimeout(() => saveReceptionDraft(), 300);
}

/**
 * 获取药品数据的存储key（按挂号ID + 类型分开存储）
 * @param registerId 挂号ID
 * @param category 类型：1-中药，2-西药
 */
const getStorageKey = (registerId: number | string | undefined, category: number) => {
  return `prescriptionData_${category}_${registerId}`;
};

// 保存到本地存储（按类型分开存储）
const saveToLocalStorage = () => {
  localStorage.setItem(
    getStorageKey(getRegisterId(), activeCategory.value),
    JSON.stringify(currentDrugs.value),
  );
  saveReceptionDraft();
};

function snapshotDrugOrigins(drugs: any[]) {
  return drugs.map((drug) => ({
    ...drug,
    origin_price: drug.origin_price ?? drug.price,
    origin_buy_price: drug.origin_buy_price ?? drug.buy_price,
  }));
}

function applyCartPriceDiscount(discount: number) {
  priceDiscount.value = discount;
  const scope = priceAdjustConfig.value.order_price_adjust_scope;
  currentDrugs.value = applyRatioDrugs(snapshotDrugOrigins(currentDrugs.value), discount, scope);
  saveToLocalStorage();
  message.success(discount === 100 ? '已清除价格浮动' : '价格已更新');
}

function clearCartPriceDiscount() {
  applyCartPriceDiscount(100);
}

const priceDiscountLabel = computed(() => formatPriceDiscountLabel(priceDiscount.value));

function openOrderPriceAdjust() {
  if (guardSpecialPrescriptionCartEdit()) return;
  if (!priceAdjustEnabled.value || !currentDrugs.value.length) return;
  currentDrugs.value = snapshotDrugOrigins(currentDrugs.value);
  const discount = Number(priceDiscount.value);
  priceAdjustDrawerApi.setData({
    stage: 'pre_send',
    priceDiscount: discount,
    price_discount: discount,
    previewOriginPrice: 100,
    quickOptions: normalizeQuickOptions(priceAdjustConfig.value.order_discount_quick_options),
    onApplyPreSend: (payload: { priceDiscount: number }) => applyCartPriceDiscount(payload.priceDiscount),
  });
  priceAdjustDrawerApi.open();
}

/**
 * 删除药品（本地）
 * @param index
 */
const removeDrug = (index: number) => {
  if (guardSpecialPrescriptionCartEdit()) return;
  currentDrugs.value.splice(index, 1);
  updateLocalStorage();
};
/**
 * 修改缓存的处方信息（按类型分开存储）
 */
const updateLocalStorage = () => {
  localStorage.setItem(
    getStorageKey(getRegisterId(), activeCategory.value),
    JSON.stringify(currentDrugs.value),
  );
  saveReceptionDraft();
  getCurrentDrugs();
};

const currentDrugs = ref([]);
/** P4：最近一次 AI 导入的生成记录 ID，发处方时回传后端做采纳率/修改率统计（清空/切换/发送后重置） */
const aiRxGenerationId = ref(0);
/**
 * 获取缓存的处方信息（按类型分开存储）
 */
const getCurrentDrugs = () => {
  currentDrugs.value = JSON.parse(
    localStorage.getItem(getStorageKey(getRegisterId(), activeCategory.value)) || '[]',
  );
};
getCurrentDrugs();

const doctorSecondSign = ref(0);
const checkData = ref([]);
/**
 * 检查中药的相冲
 */
const checkChineseMedicineConflict = () => {
  if (activeCategory.value === 2) {
    // eslint-disable-next-line no-use-before-define
    sendPrescription();
    return;
  }
  notification.info({
    message: '正在检查药物相冲',
    duration: 1,
    description: '正在检查药物相冲，请稍等...',
  })
  const names = currentDrugs.value.map((item) => item.drug_name);
  checkChineseMedicineConflictApi({names: names}).then((res) => {
    if (res.is_exist === true) {
      checkData.value.message = res.message;
      doctorSecondSignModal.value = true;
    } else {
      notification.success({
        message: '检查成功',
        duration: 3,
        description: '暂无相冲药品',
      })
      // eslint-disable-next-line no-use-before-define
      sendPrescription();
    }
  })
  return;
}
/**
 * 发送处方
 */
const sendPrescription = () => {
  if (currentDrugs.value.length === 0) {
    message.error('请选择药品');
    return;
  }
  if (activeCategory.value === 1) {
    if (ruleType.value === 1) {
      if (packageMethodId.value == null) {
        message.error('请选择包法');
        return;
      }
    } else {
      if (processRuleId.value == null) {
        message.error('请选择制剂');
        return;
      }
      if (childProcessRuleId.value == null) {
        message.error('请选择煎法');
        return;
      }
      if (processRuleNoteId.value == null) {
        message.error('请选择备注');
        return;
      }
    }
  }
  if (diagnosis.value === '') {
    message.error('诊断结果不能为空');
    return;
  }
  if (medicalAdvice.value === '') {
    message.error('医嘱不能为空');
    return;
  }
  // 发送处方逻辑
  addWestPrescription({
    // 当前活动患者的个人信息
    patient: activePatient.value,
    // 当前处方中的药品列表
    drugs: currentDrugs.value,
    // 诊断信息
    diagnosis: diagnosis.value,
    // 医嘱信息
    medicalAdvice: medicalAdvice.value,
    // 总费用
    total: totalCost.value,
    // 费用类别
    category: category.value,
    // 药品类型
    drug_type: tabType.value,
    // 从本地存储获取的挂号ID
    register_id: Number.parseInt(localStorage.getItem(`doctorReception-id`)),
    // 治疗费用
    treatment_price: treatmentPrice.value,
    // 包装方式ID
    package_method_id: packageMethodId.value,
    // 加工规则ID
    process_rule_id: processRuleId.value,
    // 加工规则备注ID
    process_rule_note_id: processRuleNoteId.value,
    // 子加工规则ID
    child_process_rule_id: childProcessRuleId.value,
    // 加工规则类型
    process_rule_type: ruleType.value,
    // 处方类型
    prescription_type: activeCategory.value,
    // 加工费
    processing_fee: processingFee.value,
    // 用药剂量
    dosage: dosage.value,
    // 每日用药次数
    day_dosage: dayDosage.value,
    // 是否二次签名
    doctor_second_sign: doctorSecondSign.value,
    salesperson_transfer_prescription_id: salespersonTransferPrescriptionId.value || undefined,
    price_discount: priceDiscount.value,
    special_prescription_id: appliedSpecialPrescriptionId.value || 0,
    // P4：AI 导入来源生成 ID，后端据此统计采纳率/修改率（非 AI 导入时为 undefined 不传）
    ai_generation_id: aiRxGenerationId.value || undefined,
  }).then(async (res) => {
    message.success('处方已发送');
    // 处方已提交，重置 AI 关联，避免下一张处方误关联
    aiRxGenerationId.value = 0;
    // 先记录本次发送结果（下面会清空诊断/购物车，成功页要用的数据在这里先落住）
    sentPrescriptionInfo.value = {
      order_id: Number(res?.order_id || 0),
      order_no: res?.order_no || '',
      total_pay_price: res?.total_pay_price || '',
      patient_name: activePatient.value?.name || '',
      diagnosis: diagnosis.value,
    };
    // 有 VIP 时同步保存病历（诊断/医嘱已与处方同源）
    if (canUseMedicalRecord.value) {
      try {
        const registerId = Number(localStorage.getItem('doctorReception-id') || 0);
        const payload = medicalRecordPanelRef.value?.getPayload?.() || {
          diagnosis: diagnosis.value,
          doctor_order: medicalAdvice.value,
        };
        await saveMedicalRecord({
          ...payload,
          register_id: registerId,
          store_id: Number(myStoreId.value || 0),
          user_patient_id: Number(
            activePatient.value?.user_patient?.id ||
              activePatient.value?.user_patient_id ||
              0,
          ),
          diagnosis: diagnosis.value,
          doctor_order: medicalAdvice.value,
          medicalAdvice: medicalAdvice.value,
        });
      } catch (e) {
        console.error('同步保存病历失败', e);
      }
    }

    // 检查是否需要转诊
    const needTransfer = res?.result?.need_transfer || res?.data?.need_transfer || res?.need_transfer;
    const transferPrescriptionId = res?.result?.transfer_prescription_id || res?.data?.transfer_prescription_id || res?.transfer_prescription_id;

    if (needTransfer && transferPrescriptionId) {
      // 如果需要转诊，获取转诊信息
      fetchTransferPrescription(transferPrescriptionId);
      message.info('该处方需要转诊，请等待中医诊所确认');
    } else {
      // 不需要转诊，清空转诊信息
      transferPrescription.value = null;
    }

    // 清空当前数据
    clearPrescriptionCart(false);
    clearReceptionDraft(getRegisterId());
    // 转诊单要等中医诊所确认，留在开方工作台展示转方卡；
    // 普通发送进入成功页（tabType=3）：摘要 + 代付入口，不自动打开处方记录抽屉
    tabType.value = needTransfer && transferPrescriptionId ? 2 : 3;
    salespersonTransferPrescriptionId.value = 0;
    checkSalespersonTransfer();

    // 刷新患者信息
    if (selectPatientId.value) {
      getPatientItem(selectPatientId.value).then((value) => {
        patientInfo.value = value;
        userPatientHealthInquiry.value = value.user_patient_health_inquiry;
        prescriptionList.value = value.prescription;
      });
    }
  }).catch((error) => {
    console.error('发送处方失败:', error);
    message.error('发送处方失败，请重试');
  });
};

// 进入处方界面
const showPrescription = () => {
  // 打开处方模态框逻辑
  tabType.value = 2;
};

// 监听tabType.value变化；进入开方面板时强制拉一次处方类型
watch(
  () => tabType.value,
  (newValue) => {
    if (newValue === 1) {
      getPatientItem(selectPatientId.value).then((value) => {
        patientInfo.value = value;
        userPatientHealthInquiry.value = value.user_patient_health_inquiry;
        prescriptionList.value = value.prescription;
      });
    }
    if (newValue === 2) {
      const rid = getRegisterId() || selectPatientId.value || 0;
      loadPrescriptionTypeOptions(Number(rid) || undefined);
    }
    newDrugInfo.value = {};
    localStorage.setItem(
      `doctorReception-type`,
      // JSON.stringify(selectData),
      JSON.stringify(newValue),
    );
  },
);


const [WesternDrugModal, WesternDrugModalApi] = useVbenModal({
  connectedComponent: WesternModal,
});

const [SimpleProductModalComponent, SimpleProductModalApi] = useVbenModal({
  connectedComponent: SimpleProductModal,
});

/**
 * 诊断/医嘱追加（中文逗号拼接，与病历面板一致）
 */
function appendCommaText(base: string, add: string) {
  if (!add) return base || '';
  const parts = (base || '').split('，').map((s) => s.trim()).filter(Boolean);
  if (parts.includes(add)) return parts.join('，');
  parts.push(add);
  return parts.join('，');
}

/** 气泡/常用标签选中诊断 */
function onPickDiagnosis(text: string) {
  const t = String(text || '').trim();
  if (!t) return;
  diagnosis.value = appendCommaText(diagnosis.value, t);
}

/** 气泡/常用标签选中医嘱 */
function onPickDoctorOrder(text: string) {
  const t = String(text || '').trim();
  if (!t) return;
  medicalAdvice.value = appendCommaText(medicalAdvice.value, t);
}

const [PrescriptionDetailModal, PrescriptionDetailModalApi] = useVbenModal({
  connectedComponent: PrescriptionDetail,
});


const [RefusalOfTreatmentModals, RefusalOfTreatmentModalApi] = useVbenModal({
  connectedComponent: RefusalOfTreatmentModal,
});

/** 新建就诊人弹窗 */
const [CreateUserPatientModals, CreateUserPatientModalApi] = useVbenModal({
  connectedComponent: CreateUserPatientModal,
});

/** 就诊人认领码弹窗 */
const [ClaimQrcodeModals, ClaimQrcodeModalApi] = useVbenModal({
  connectedComponent: ClaimQrcodeModal,
});

/** 医生代支付码弹窗 */
const [ProxyPayQrcodeModals, ProxyPayQrcodeModalApi] = useVbenModal({
  connectedComponent: ProxyPayQrcodeModal,
});

// ==================== 常用方弹窗 ====================
const [CommonPrescriptionModals, CommonPrescriptionModalApi] = useVbenModal({
  connectedComponent: CommonPrescriptionModal,
});

/** 金方导入弹窗 */
const [GoldenFormulaModals, GoldenFormulaModalApi] = useVbenModal({
  connectedComponent: GoldenFormulaModal,
});

// ==================== 确认模态框 ====================
const [ConfirmModalComponent, confirmModalApi] = useVbenModal({
  connectedComponent: ConfirmModal,
});
// ==================== 信息提示模态框 ====================
const [InfoModalComponent, infoModalApi] = useVbenModal({
  connectedComponent: InfoModal,
});

/**
 * 打开常用方选择弹窗
 * @description 打开常用方弹窗，选择后自动填充药品到处方中
 */
function openCommonPrescriptionModal() {
  CommonPrescriptionModalApi.setData({
    type: activeCategory.value,
    onSelect: handleSelectCommonPrescription,
  });
  CommonPrescriptionModalApi.open();
}

/**
 * 打开新建就诊人弹窗
 * 成功后按 is_pay 分情况：已支付 → 切当前列表并自动选中；未支付 → 弹认领码
 */
function openCreateUserPatientModal() {
  CreateUserPatientModalApi.setData({
    onSuccess: (res: {
      user_patient_id?: number;
      register_id?: number;
      is_pay?: number;
    }) => {
      const isPay = Number(res?.is_pay || 0) === 1;
      const registerId = Number(res?.register_id || 0);
      const userPatientId = Number(res?.user_patient_id || 0);
      if (isPay) {
        // 新人 status=1，落在「当前」列表
        listType.value = 1;
        getPatientList({ type: listType.value })
          .then((list) => {
            patients.value = Array.isArray(list) ? list : [];
            const hit = patients.value.find(
              (p) => Number(p.id) === registerId,
            );
            if (hit) {
              selectPatient(hit);
            } else {
              message.warning('已创建，请在列表中手动选择');
            }
          })
          .catch((e: any) => {
            message.error(e?.message || '刷新患者列表失败');
          });
        return;
      }
      // 未支付进不了左侧列表：直接弹认领码并选中刚创建的就诊人
      ClaimQrcodeModalApi.setData({
        user_patient_id: userPatientId || undefined,
      });
      ClaimQrcodeModalApi.open();
      refreshPatientList();
    },
  });
  CreateUserPatientModalApi.open();
}

/**
 * 当前就诊人是否未认领（user_id=0）
 * 认领码入口仅在未认领时出现在右侧工具栏
 */
const isActivePatientUnclaimed = computed(() => {
  const up = activePatient.value as any;
  if (!up?.id) return false;
  return Number(up.user_id || 0) === 0;
});

/** 打开就诊人认领二维码（优先当前选中患者） */
function openClaimQrcodeModal() {
  const upId = Number(activePatient.value?.id || patientInfo.value?.user_patient_id || 0);
  ClaimQrcodeModalApi.setData({ user_patient_id: upId || undefined });
  ClaimQrcodeModalApi.open();
}

/** 打开医生代支付小程序码 */
function openProxyPayQrcode(orderId: number) {
  if (!orderId) {
    message.error('订单ID无效');
    return;
  }
  ProxyPayQrcodeModalApi.setData({ order_id: orderId });
  ProxyPayQrcodeModalApi.open();
}

/**
 * 打开金方导入弹窗（VIP：golden_formula）；仅中药处方可用
 */
function openGoldenFormulaModal() {
  if (Number(activeCategory.value) !== 1) {
    message.warning('金方仅支持中药处方');
    return;
  }
  if (!canUseGoldenFormula.value) {
    message.warning('当前门店未开通金方 VIP 功能');
    return;
  }
  if (guardSpecialPrescriptionCartEdit()) return;
  const registerId = Number.parseInt(
    localStorage.getItem(`doctorReception-id`) || '0',
  );
  GoldenFormulaModalApi.setData({
    storeId: Number(myStoreId.value || 0),
    registerId,
    category: activeCategory.value,
  });
  GoldenFormulaModalApi.open();
}

/**
 * 金方确认导入：复用 AI 出方写入购物车逻辑
 */
function handleImportGoldenFormula(payload: { rows?: any[]; formulaName?: string }) {
  handleImportAiPrescription({ rows: payload?.rows || [] });
}

const aiPrescriptionDrawerRef = ref<InstanceType<typeof AiPrescriptionDrawer> | null>(null);

/** 打开 AI 给处方抽屉：先确认患者与主诉，再生成预览 */
function openAiPrescriptionDrawer() {
  if (!canUseAiPrescription.value) {
    message.warning('当前门店未开通AI辅助出方VIP功能');
    return;
  }
  if (guardSpecialPrescriptionCartEdit()) return;
  const registerId = Number.parseInt(
    localStorage.getItem(`doctorReception-id`) || '0',
  );
  if (!registerId) {
    message.warning('请先选择患者');
    return;
  }
  if (!activeCategory.value) {
    message.warning('请先选择处方类型');
    return;
  }
  // 病历面板用 v-show 保活；仍兜底合并本地草稿，避免偶发空表单
  let payload: Record<string, any> =
    medicalRecordPanelRef.value?.getPayload?.() || {};
  const draft = loadMedicalRecordDraft(registerId);
  if (draft && typeof draft === 'object') {
    payload = { ...draft, ...payload };
  }
  // 诊断/医嘱以处方侧当前值为准（与病历双向绑定）
  if (diagnosis.value) payload.diagnosis = diagnosis.value;
  if (medicalAdvice.value) payload.doctor_order = medicalAdvice.value;
  aiPrescriptionDrawerRef.value?.open({
    registerId,
    storeId: Number(myStoreId.value || 0) || undefined,
    prescriptionType: Number(activeCategory.value),
    patientName: String(activePatient.value?.name || ''),
    patientSex: Number(activePatient.value?.sex || 0),
    patientAge: Number(activePatient.value?.age || 0),
    chiefComplaint: String(payload.chief_complaint || ''),
    medicalRecord: { ...payload },
  });
}

/**
 * AI 出方预览里改病历字段时，回写到当前病历面板（不强制保存）
 */
function handleSyncAiMedicalRecord(partial: Record<string, any>) {
  medicalRecordPanelRef.value?.patchFields?.(partial || {});
}

/**
 * 将 AI 对照结果覆盖导入当前处方（非追加）
 * 中药会同步剂数/每日次数，并按 usage 匹配先煎后下 way_id
 */
async function handleImportAiPrescription(payload: {
  rows?: any[];
  dosage?: number;
  day_dosage?: number;
  rule_type?: number;
  process_rule_id?: number;
  child_process_rule_id?: number;
  process_rule_note_id?: number;
  generation_id?: number;
}) {
  if (guardSpecialPrescriptionCartEdit()) return;
  const list = Array.isArray(payload?.rows) ? payload.rows : [];
  if (!list.length) {
    message.warning('没有可导入的药品');
    return;
  }
  const resolveWayId = (usage: string) => {
    const u = String(usage || '').trim();
    if (!u) return 0;
    const found = (drugUseWay.value || []).find(
      (w: any) =>
        String(w.name || '') === u || String(w.name || '').includes(u),
    );
    return found ? Number(found.id || 0) : 0;
  };
  /** AI 返回委托调剂时，同步 ruleType 并级联加载制剂/煎法/备注选项 */
  const applyAiProcessRules = async () => {
    if (activeCategory.value !== 1) return;
    const prId = Number(payload.process_rule_id || 0);
    if (prId <= 0 && payload.rule_type !== 2) return;
    ruleType.value = 2;
    if (prId > 0) {
      processRuleId.value = prId;
      await loadProcessRuleData(prId, 0);
    }
    const childId = Number(payload.child_process_rule_id || 0);
    if (childId > 0) {
      childProcessRuleId.value = childId;
      await loadProcessRuleData(0, childId);
    }
    const noteId = Number(payload.process_rule_note_id || 0);
    if (noteId > 0) {
      processRuleNoteId.value = noteId;
    }
  };
  const doOverwrite = async () => {
    clearAppliedSpecialPrescription();
    const next: any[] = [];
    for (const row of list) {
      const c = row?.candidate || {};
      const drugId = Number(c.drug_id || 0);
      if (!drugId) continue;
      if (next.find((item: any) => Number(item.id) === drugId)) continue;
      const doseNum = parseFloat(row.dose);
      const qty = !Number.isNaN(doseNum) && doseNum > 0 ? doseNum : 1;
      const drug = c.drug || {};
      if (activeCategory.value === 1) {
        const wayId = resolveWayId(row.usage || '');
        next.push({
          index_id: c.id || drugId,
          id: drugId,
          drug_name: c.drug_name || row.ai_name,
          number: qty,
          price: parseFloat(c.price) || 0,
          way_id: wayId,
          use_ways: drugUseWay.value.find((item: any) => item.id === wayId),
          select_number: 1,
          unit: c.unit || { id: 0, name: row.unit || 'g' },
        });
        continue;
      }
      if (activeCategory.value === 2) {
        next.push({
          index_id: c.id || drugId,
          id: drugId,
          drug_name: c.drug_name || drug.drug_name || row.ai_name,
          number: qty,
          select_number: qty,
          price: parseFloat(c.price) || 0,
          image: c.image || drug.image || '',
          instruction: drug.instruction || '',
          time_id: c.time_id || drug.time_id || 0,
          type_id: c.type_id || drug.type_id || 0,
          frequency_id: c.frequency_id || drug.frequency_id || 0,
          unit_id: c.unit_id || drug.unit_id || 0,
          use_num: drugTime.value.find(
            (item) => item.id === (c.time_id || drug.time_id || 0),
          ),
          use_type: drugUseType.value.find(
            (item) => item.id === (c.type_id || drug.type_id || 0),
          ),
          use_frequency: drugUseFrequency.value.find(
            (item) => item.id === (c.frequency_id || drug.frequency_id || 0),
          ),
          unit:
            c.unit ||
            drugUnit.value.find(
              (item) => item.id === (c.unit_id || drug.unit_id || 0),
            ),
          type: 2,
        });
        continue;
      }
      next.push({
        index_id: c.id || drugId,
        id: drugId,
        drug_name: c.drug_name || row.ai_name,
        number: 1,
        select_number: 1,
        price: parseFloat(c.price) || 0,
        image: c.image || '',
        type: activeCategory.value,
      });
    }
    if (!next.length) {
      message.warning('没有可导入的药品');
      return;
    }
    currentDrugs.value = next;
    // P4：记录 AI 生成 ID（金方导入等无 ID 场景会重置为 0，避免误关联）
    aiRxGenerationId.value = Number(payload.generation_id || 0);
    if (activeCategory.value === 1) {
      // 中药剂数/每日次数：有值用返回值，否则保留处方页默认 7/2
      dosage.value = Number(payload.dosage) > 0 ? Number(payload.dosage) : 7;
      dayDosage.value = Number(payload.day_dosage) > 0 ? Number(payload.day_dosage) : 2;
      await applyAiProcessRules();
    }
    updateLocalStorage();
    message.success(`已覆盖导入 ${next.length} 个药品`);
  };
  if (currentDrugs.value.length > 0) {
    AntModal.confirm({
      title: '覆盖当前处方',
      content: '导入将清空并覆盖现有处方药品，是否继续？',
      okText: '继续覆盖',
      cancelText: '取消',
      onOk: () => doOverwrite(),
    });
    return;
  }
  await doOverwrite();
}

/** 未对照药名：提示手动搜索 */
function handleAiSearchUnmatchedDrug(keyword: string) {
  const key = String(keyword || '');
  if (activeCategory.value === 2) {
    openWesternModal();
    return;
  }
  if (key) {
    message.info(`请手动搜索：${key}`);
  }
}

/**
 * 处理选择常用方
 * @param data 常用方数据，包含prescription和recipes
 * @param type 类型：1-西药，2-中药，3-颗粒药
 * @description 选择常用方后，将药品列表填充到当前处方中
 */
async function handleSelectCommonPrescription(data: any, type: number) {
  clearAppliedSpecialPrescription();
  const { prescription, recipes } = data;

  // 根据类型处理药品：整表覆盖为常用方内容，不与当前处方按药品 ID 去重合并
  if (type === 1) {
    currentDrugs.value = (recipes || []).map((recipe: any) => ({
      index_id: recipe.id,
      id: recipe.drug_id,
      drug_name: recipe.drug_name,
      number: recipe.number || 1,
      use_num: recipe.use_time,
      use_type: recipe.use_type,
      use_frequency: recipe.use_frequency,
      unit: recipe.west_unit,
      price: recipe.price || 0,
      time_id: recipe.time_id,
      type_id: recipe.type_id,
      frequency_id: recipe.frequency_id,
      unit_id: recipe.unit_id,
      image: recipe.image,
      instruction: recipe.instruction,
      type: recipe.type,
      select_number: recipe.select_number ?? 1,
    }));
  } else {
    currentDrugs.value = (recipes || []).map((recipe: any) => {
      const drugId = recipe.drug_id || recipe.id;
      return {
        index_id: recipe.id,
        id: drugId,
        drug_name: recipe.drug_name || recipe.name,
        number: recipe.number || 1,
        price: recipe.price || 0,
        buy_price: recipe.buy_price,
        way_id: recipe.way_id || 0,
        select_number: recipe.select_number ?? 1,
      };
    });

    // 写入规则类型和剂量信息（中药）- 使用 ?? 运算符提供默认值
    ruleType.value = prescription.rule_type ?? 1;
    dosage.value = prescription.dosage ?? 7;
    dayDosage.value = prescription.day_dosage ?? 2;
    packageMethodId.value = prescription.package_method_id ?? 2;

    // 如果是委托调剂，写入完整加工规则配置 - 只有有效值才写入（大于0），级联加载
    if (prescription.process_rule_id && prescription.process_rule_id > 0) {
      processRuleId.value = prescription.process_rule_id;
      // 加载煎法选项
      await loadProcessRuleData(prescription.process_rule_id, 0);
    }
    if (prescription.child_process_rule_id && prescription.child_process_rule_id > 0) {
      childProcessRuleId.value = prescription.child_process_rule_id;
      // 加载备注选项
      await loadProcessRuleData(0, prescription.child_process_rule_id);
    }
    if (prescription.process_rule_note_id && prescription.process_rule_note_id > 0) {
      processRuleNoteId.value = prescription.process_rule_note_id;
    }
  }

  // 更新诊断和医嘱 - 允许空字符串覆盖
  if (prescription.clinical_diagnose !== undefined && prescription.clinical_diagnose !== null) {
    diagnosis.value = prescription.clinical_diagnose;
  }
  if (prescription.doctor_order !== undefined && prescription.doctor_order !== null) {
    medicalAdvice.value = detailDoctorOrderToText(prescription.doctor_order);
  }

  // 保存到本地存储
  updateLocalStorage();
}

/**
 * 应用患者选择的特色方到处方购物车
 * @param switchToPrescription 是否切换到开方 Tab（患者信息页导入时为 true）
 */
async function handleApplySpecialPrescription(switchToPrescription = false) {
  const registerId = doctorReceptionRegisterId.value;
  if (!registerId) {
    message.warning('请先选择患者');
    return;
  }
  applyingSpecialPrescription.value = true;
  try {
    const res = await applySpecialPrescriptionApi({ register_id: registerId });
    const typeMap: Record<string, number> = {
      west: 1,
      chinese: 2,
      granular: 3,
    };
    const categoryMap: Record<string, number> = {
      west: 2,
      chinese: 1,
      granular: 1,
    };
    const prescriptionType = res.prescription_type || 'chinese';
    activeCategory.value = categoryMap[prescriptionType] || 1;
    if (switchToPrescription) {
      tabType.value = 2;
    }

    await handleSelectCommonPrescription(
      {
        prescription: {
          dosage: res.dosage ?? res.dose_count ?? 7,
          day_dosage: res.day_dosage ?? 2,
          rule_type: res.rule_type ?? 1,
          package_method_id: res.package_method_id ?? 2,
          clinical_diagnose: res.clinical_diagnose ?? '',
          doctor_order: res.doctor_order ?? '',
        },
        recipes: res.recipes || [],
      },
      typeMap[prescriptionType] || 2,
    );

    appliedSpecialPrescriptionId.value = Number(res.special_prescription_id) || 0;
    appliedSpecialPrescriptionExpectedTotal.value =
      res.expected_total_price != null ? Number(res.expected_total_price) : null;

    if (selectPatientId.value) {
      const value = await getPatientItem(selectPatientId.value);
      patientInfo.value = value;
    }
    message.success(`已应用特色方：${res.special_prescription_name || ''}`);
  } catch (error) {
    console.error('应用特色方失败:', error);
    message.error('应用特色方失败，请稍后重试');
  } finally {
    applyingSpecialPrescription.value = false;
  }
}

// ==================== 保存常用方相关方法 ====================

/**
 * 打开保存常用方弹窗
 * @description 检查是否有药品可保存，然后打开弹窗
 */
const openSaveCommonPrescriptionModal = () => {
  // 检查是否有药品
  if (currentDrugs.value.length === 0) {
    message.warning('请先添加药品后再保存为常用方');
    return;
  }
  // 清空输入框
  commonPrescriptionName.value = '';
  // 打开弹窗
  showSaveCommonPrescriptionModal.value = true;
};

/**
 * 保存当前处方为常用方
 * @description 根据当前药品类型（中药/西药）调用不同的保存接口
 */
const saveAsCommonPrescription = async () => {
  // 验证名称
  if (!commonPrescriptionName.value.trim()) {
    message.warning('请输入常用方名称');
    return;
  }

  // 验证是否有药品
  if (currentDrugs.value.length === 0) {
    message.warning('没有可保存的药品');
    return;
  }

  if (![1, 2].includes(activeCategory.value)) {
    message.warning('当前分类不支持保存为常用方');
    return;
  }

  isSavingCommonPrescription.value = true;

  try {
    // 根据处方类型选择不同的保存接口
    if (activeCategory.value === 1) {
      // 中药处方 - 构建药品详细信息数组
      const drugs = currentDrugs.value.map((drug) => ({
        drug_id: drug.id,
        drug_name: drug.drug_name,
        number: drug.number || 1,
        price: drug.price || 0,
        way_id: drug.way_id || 0,
      }));

      await saveChineseCommonPrescriptionApi({
        name: commonPrescriptionName.value.trim(),
        drugs,
        store_id: myStoreId.value,
        clinical_diagnose: diagnosis.value || '',
        doctor_order: medicalAdvice.value || '',
        category: String(category.value),
        dosage: dosage.value,
        day_dosage: dayDosage.value,
        rule_type: ruleType.value,
        package_method_id: ruleType.value === 1 ? packageMethodId.value : undefined,
        process_rule_id: ruleType.value === 2 ? (processRuleId.value || undefined) : undefined,
        child_process_rule_id: ruleType.value === 2 ? (childProcessRuleId.value || undefined) : undefined,
        process_rule_note_id: ruleType.value === 2 ? (processRuleNoteId.value || undefined) : undefined,
      });
    } else {
      // 西药处方 - 构建药品详细信息数组
      const drugs = currentDrugs.value.map((drug) => ({
        drug_id: drug.id,
        drug_name: drug.drug_name,
        number: drug.number || 1,
        price: drug.price || 0,
        image: drug.image || '',
        instruction: drug.instruction || '',
        use_type_id: drug.use_type?.id || 0,
        use_frequency_id: drug.use_frequency?.id || 0,
        use_time_id: drug.use_num?.id || 0,
        unit_id: drug.unit?.id || 0,
        select_number: drug.select_number || 1,
      }));

      await saveWestCommonPrescriptionApi({
        name: commonPrescriptionName.value.trim(),
        drugs,
        store_id: myStoreId.value,
        clinical_diagnose: diagnosis.value || '',
        doctor_order: medicalAdvice.value || '',
        category: String(category.value),
      });
    }

    message.success('常用方保存成功');
    showSaveCommonPrescriptionModal.value = false;
    commonPrescriptionName.value = '';
  } catch (error) {
    console.error('保存常用方失败:', error);
    message.error('保存常用方失败，请稍后重试');
  } finally {
    isSavingCommonPrescription.value = false;
  }
};

/**
 * 取消保存常用方
 */
const cancelSaveCommonPrescription = () => {
  showSaveCommonPrescriptionModal.value = false;
  commonPrescriptionName.value = '';
};

const openWesternModal = () => {
  if (guardSpecialPrescriptionCartEdit()) return;
  // 判断是否为简单产品类型（3,5,6,7）
  const simpleProductTypes = [3, 5, 6, 7];
  if (simpleProductTypes.includes(activeCategory.value)) {
    // 使用简单产品模态框
    SimpleProductModalApi.setData({
      values: activeCategory.value,
      activePatient_id: getRegisterId(), // 与主页面 storage key 保持一致，使用挂号 ID
      getCurrentDrugs,
      storagePrefix: '', // 接诊页面不加前缀
    });
    SimpleProductModalApi.open();
  } else {
    // 使用原有的西药/中药模态框
  WesternDrugModalApi.setData({
    values: activeCategory.value,
    activePatient_id: getRegisterId(), // 与主页面 storage key 保持一致，使用挂号 ID
    getCurrentDrugs,
    storagePrefix: '', // 接诊页面不加前缀
  });
  WesternDrugModalApi.open();
  }
};
const openPrescriptionDetail = (values) => {
  // 打开西药处方模态框逻辑
  PrescriptionDetailModalApi.setData({
    values,
  });
  PrescriptionDetailModalApi.open();
};

/**
 * 切换tab（中药/西药切换）
 * @param id 类型：1-中药，2-西药
 * @description 切换Tab时：
 *              1. 先保存当前Tab的药品数据
 *              2. 更新activeCategory
 *              3. 加载新Tab对应的药品数据
 *              4. 如果切换到中药且当前诊所为西医诊所，显示转诊提示
 */
function tabChange(id) {
  const registerId = getRegisterId();
  localStorage.setItem(
    getStorageKey(registerId, activeCategory.value),
    JSON.stringify(currentDrugs.value),
  );
  saveReceptionDraft();
  localStorage.setItem(`activeCategory${registerId}`, String(id));
  activeCategory.value = id;
  if (id === 1) {
    checkSalespersonTransfer();
  }
  currentDrugs.value = JSON.parse(
    localStorage.getItem(getStorageKey(registerId, id)) || '[]',
  );
  if (id === 1) {
    checkAndShowTransferTip();
  }
  focusActiveCategoryTab();
}


/**
 * 检测并显示转诊提示
 * @description 当切换到中药处方时，如果当前诊所为西医诊所，显示转诊提示
 * 半小时内只提醒一次
 */
async function checkAndShowTransferTip() {
  try {
    // 检查上次提醒时间，如果距离上次提醒不足30分钟，则不显示警告
    const storageKey = `transferTipLastShown_${myStoreId.value}`;
    const lastShownTime = localStorage.getItem(storageKey);
    const now = Date.now();
    const thirtyMinutes = 30 * 60 * 1000; // 30分钟 = 1800000 毫秒

    if (lastShownTime) {
      const timeDiff = now - Number.parseInt(lastShownTime);
      if (timeDiff < thirtyMinutes) {
        // 距离上次提醒不足30分钟，不显示警告
        return;
      }
    }

    // 调用新接口获取当前诊所类型和委托诊所信息
    const registerId = Number.parseInt(
      localStorage.getItem('doctorReception-id') || '0',
      10,
    );
    const storeInfo = await getCurrentStoreTypeCached({
      store_id: myStoreId.value,
      ...(registerId > 0 ? { register_id: registerId } : {}),
    });

    if (!storeInfo) {
      return;
    }

    // 检测是否为西医诊所（clinic_type === 1）
    if (storeInfo.clinic_type === 1 && storeInfo.delegate_store) {
      const delegateStore = storeInfo.delegate_store;
      const doctorName = delegateStore.doctor?.name || '委托医生';
      const storeName = delegateStore.name || '委托诊所';

      infoModalApi.setState({ title: '转诊提示', width: 500 });
      infoModalApi.setData({
          content: `检测到当前诊所为西医诊所，本次处方开具后自动转接到【${storeName}】的【${doctorName}】的在线复诊中`,
        });
      infoModalApi.open();

      // 更新上次提醒时间戳
      localStorage.setItem(storageKey, String(now));
    }
  } catch (error) {
    console.error('获取诊所信息失败:', error);
  }
}

/**
 * 接诊成功后直接进入开方工作台
 */
function reception() {
  receptionApi(localStorage.getItem(`doctorReception-id`)).then((value) => {
    message.success('接诊成功');
    updateTabType.value = false;
    getPatientListByReception();
    receptionStatus.value = 2;
    tabType.value = 2;
  });
}

const updateReceptionStatus = () => {
  receptionStatus.value = 0;
  tabType.value = 0;
}

/**
 * 拒诊
 */
function refuseReception() {
  RefusalOfTreatmentModalApi.setData({
    values: {
      register_id: localStorage.getItem(`doctorReception-id`)
    },
    getPatientListByReception,
    updateReceptionStatus,
    // 在patients中循环查询id = selectPatientId.value的

    // let patient = patients.
    // selectPatient(localStorage.getItem(`doctorReception-id`));
  })

  RefusalOfTreatmentModalApi.open();
}

/**
 * 结束诊断
 */
function endOfDiagnosis() {
  endOfDiagnosisApi(localStorage.getItem(`doctorReception-id`)).then(
    (value) => {
      message.success('接诊成功');
      updateTabType.value = false;
      getPatientListByReception();
      receptionStatus.value = 2;
      tabType.value = 0;
    },
  );
}

// 基础配置
const processRuleList = ref([]);
// 子配置
const childProcessRuleList = ref([]);
// 规格
const processRuleNoteList = ref([]);
const processRuleId = ref();
const processRuleNoteId = ref();
const childProcessRuleId = ref();

async function loadProcessRuleData(pid = 0, ruleId = 0) {
  const data = ruleId === 0 ? { pid } : { rule_id: ruleId };
  const value = await getProcessRuleList(data);
  if (ruleId !== 0) {
    processRuleNoteList.value = value;
  } else if (pid === 0) {
    processRuleList.value = value;
  } else {
    childProcessRuleList.value = value;
  }
  await applySingleChildProcessRuleAutoSelect(
    resolveProcessRuleLoadedLevel(pid, ruleId),
    {
      ruleType: ruleType.value,
      disabled: isSpecialPrescriptionCartLocked.value,
      processRuleId: processRuleId.value,
      childProcessRuleId: childProcessRuleId.value,
      processRuleNoteId: processRuleNoteId.value,
      processRuleList: processRuleList.value,
      childProcessRuleList: childProcessRuleList.value,
      processRuleNoteList: processRuleNoteList.value,
      load: loadProcessRuleData,
      setProcessRuleId: (id) => {
        processRuleId.value = id;
      },
      setChildProcessRuleId: (id) => {
        childProcessRuleId.value = id;
      },
      setProcessRuleNoteId: (id) => {
        processRuleNoteId.value = id;
      },
      clearBelowProcessRule: () => {
        childProcessRuleId.value = undefined;
        processRuleNoteId.value = undefined;
        childProcessRuleList.value = [];
        processRuleNoteList.value = [];
      },
      clearBelowChild: () => {
        processRuleNoteId.value = undefined;
        processRuleNoteList.value = [];
      },
    },
  );
}

/**
 * 从草稿 ID 级联拉取委托调剂选项列表（刷新恢复用，对齐移动端 hydrateChineseProcessRuleListsFromConfig）
 */
async function hydrateChineseProcessRuleListsFromConfig() {
  if (activeCategory.value !== 1 || ruleType.value !== 2) {
    return;
  }
  if (processRuleList.value.length === 0) {
    await loadProcessRuleData();
  }
  if (processRuleId.value) {
    await loadProcessRuleData(Number(processRuleId.value));
  }
  if (childProcessRuleId.value) {
    await loadProcessRuleData(0, Number(childProcessRuleId.value));
  }
}

function parsePrescriptionDetailContent(detail: any): Record<string, any> {
  let c = detail?.content;
  if (typeof c === 'string') {
    try {
      c = JSON.parse(c);
    } catch {
      c = {};
    }
  }
  return c && typeof c === 'object' ? c : {};
}

function mapWestRepiceToProduct(recipe: any): Record<string, any> | null {
  if (!recipe) return null;
  let drugObj: Record<string, any> = {};
  try {
    const raw = recipe.content;
    drugObj = typeof raw === 'string' ? JSON.parse(raw) : (raw || {});
  } catch {
    return null;
  }
  const drugId = Number(drugObj.id);
  if (!drugId) return null;

  const selectNumber = Math.max(
    1,
    Number(recipe.number ?? drugObj.select_number ?? drugObj.number ?? 1) || 1,
  );
  const grainNumber = Math.max(
    1,
    Number(
      drugObj.number ?? drugObj.grain_number ?? recipe.grain_number ?? 1,
    ) || 1,
  );

  const timeId = recipe.time_id ?? drugObj.time_id;
  const typeId = recipe.type_id ?? drugObj.type_id;
  const freqId = recipe.f_id ?? drugObj.frequency_id;
  const unitId = recipe.wu_id ?? drugObj.unit_id;

  return {
    index_id: drugId,
    id: drugId,
    drug_name: drugObj.drug_name || drugObj.name || '',
    number: grainNumber,
    use_num: drugTime.value.find((item: any) => item.id === timeId),
    use_type: drugUseType.value.find((item: any) => item.id === typeId),
    use_frequency: drugUseFrequency.value.find(
      (item: any) => item.id === freqId,
    ),
    unit: drugObj.unit || drugUnit.value.find((item: any) => item.id === unitId),
    price: Number(drugObj.sell_price ?? drugObj.price ?? 0),
    way_id: drugObj.way_id,
    use_ways: drugUseWay.value.find((item: any) => item.id === drugObj.way_id),
    time_id: timeId,
    type_id: typeId,
    frequency_id: freqId,
    unit_id: unitId,
    image: drugObj.image || '',
    instruction: drugObj.instruction || '',
    type: drugObj.type,
    select_number: selectNumber,
  };
}

/**
 * 将历史处方详情写入当前接诊编辑区（不提交）
 */
async function applyHistoricalPrescriptionDetail(detail: any): Promise<boolean> {
  const content = parsePrescriptionDetailContent(detail);
  const pt = Number(detail.prescription_type);
  const supported = [1, 2, 3, 5, 6, 7];
  if (!supported.includes(pt)) {
    message.warning('该处方类型暂不支持复用');
    return false;
  }

  const pid = getRegisterId();
  if (!pid) {
    message.warning('请先选择患者');
    return false;
  }

  localStorage.setItem(
    getStorageKey(pid, activeCategory.value),
    JSON.stringify(currentDrugs.value),
  );

  activeCategory.value = pt;
  localStorage.setItem(`activeCategory${pid}`, String(pt));

  const repiceList = Array.isArray(content.repice) ? content.repice : [];

  if (pt === 1) {
    const rep0 = repiceList[0];
    if (!rep0) {
      message.warning('处方中药品数据为空');
      return false;
    }
    let rows: any[] = [];
    try {
      const raw = rep0.content;
      rows = typeof raw === 'string' ? JSON.parse(raw) : (raw || []);
    } catch {
      message.error('解析中药处方失败');
      return false;
    }
    if (!Array.isArray(rows) || rows.length === 0) {
      message.warning('处方中药品数据为空');
      return false;
    }

    currentDrugs.value = rows.map((d: any) => {
      const drugId = Number(d.drug_id ?? d.id);
      // 落库煎法在 ChineseMedicineModel.order，详情可能带 use_way / useWay
      const wayId =
        d.way_id ?? d.use_way?.id ?? d.useWay?.id ?? d.order;
      return {
        index_id: d.id ?? drugId,
        id: drugId,
        drug_name: d.name || d.drug_name || '',
        number: d.number ?? 1,
        price: Number(d.price ?? 0),
        way_id: wayId,
        use_ways:
          drugUseWay.value.find((item: any) => item.id === wayId) ??
          d.use_way ??
          d.useWay,
        use_num: drugTime.value.find((item: any) => item.id === d.time_id),
        use_type: drugUseType.value.find((item: any) => item.id === d.type_id),
        use_frequency: drugUseFrequency.value.find(
          (item: any) => item.id === d.frequency_id,
        ),
        unit: d.unit || drugUnit.value.find((item: any) => item.id === d.unit_id),
        time_id: d.time_id,
        type_id: d.type_id,
        frequency_id: d.frequency_id,
        unit_id: d.unit_id,
        image: d.image || '',
        instruction: d.instruction || '',
        type: d.type,
      };
    });

    ruleType.value = rep0.deployment === 2 ? 1 : 2;
    dosage.value = Number(rep0.dosage ?? 7);
    dayDosage.value = Number(rep0.consumption ?? 2);
    packageMethodId.value = rep0.package_method_id ?? 2;

    if (rep0.process_rule_id && Number(rep0.process_rule_id) > 0) {
      processRuleId.value = rep0.process_rule_id;
      await loadProcessRuleData(rep0.process_rule_id, 0);
    }
    if (rep0.child_process_rule_id && Number(rep0.child_process_rule_id) > 0) {
      childProcessRuleId.value = rep0.child_process_rule_id;
      await loadProcessRuleData(0, rep0.child_process_rule_id);
    }
    if (rep0.process_rule_note_id && Number(rep0.process_rule_note_id) > 0) {
      processRuleNoteId.value = rep0.process_rule_note_id;
    }

    if (!rep0.process_rule_id) {
      message.warning('历史处方未包含完整加工规则，请核对包法/制剂与规格');
    }
  } else {
    const mapped: any[] = [];
    for (const recipe of repiceList) {
      const row = mapWestRepiceToProduct(recipe);
      if (row) mapped.push(row);
    }
    if (mapped.length === 0) {
      message.warning('未解析到可复用的药品行');
      return false;
    }
    currentDrugs.value = mapped;
  }

  diagnosis.value =
    detail.clinical_diagnose ?? content.clinical_diagnose ?? '';
  medicalAdvice.value = content.doctor_order ?? detailDoctorOrderToText(detail.doctor_order) ?? '';
  category.value =
    detail.category === 2 || detail.category === '2' || content.category === '医保'
      ? 2
      : 1;
  doctorSecondSign.value = 0;

  localStorage.setItem(
    getStorageKey(pid, activeCategory.value),
    JSON.stringify(currentDrugs.value),
  );
  localStorage.setItem(`activeCategory${pid}`, String(activeCategory.value));
  saveReceptionDraft();
  getCurrentDrugs();
  return true;
}

async function reusePrescriptionFromList(prescriptionId: number) {
  if (!activePatient.value?.id) {
    message.warning('请先选择患者');
    return;
  }
  const draft = currentDrugs.value;
  const go = async () => {
    try {
      const detail = await getPrescriptionInfoApi(prescriptionId);
      const ok = await applyHistoricalPrescriptionDetail(detail);
      if (ok) {
        tabType.value = 2;
        message.success('已复用到开方页，请核对后发送');
      }
    } catch (e) {
      console.error(e);
      message.error('加载处方详情失败');
    }
  };

  if (draft.length > 0) {
    AntModal.confirm({
      title: '覆盖当前草稿？',
      content: '当前处方清单中有药品，复用将替换为所选历史处方内容。',
      onOk: go,
    });
  } else {
    await go();
  }
}

/** 患者信息抽屉（健康信息等） */
const [PatientInfoDrawerComp, patientInfoDrawerApi] = useVbenDrawer({
  connectedComponent: PatientInfoDrawer,
});

/** 历史病历引用抽屉（工具栏入口，与病历面板内入口共用组件） */
const [PatientMrDrawerComp, patientMrDrawerApi] = useVbenDrawer({
  connectedComponent: PatientMedicalRecordDrawer,
});

/** 处方记录抽屉（本次/历史 + 复用） */
const [PatientRxHistoryDrawerComp, patientRxHistoryDrawerApi] = useVbenDrawer({
  connectedComponent: PatientPrescriptionHistoryDrawer,
});

/**
 * 患者信息抽屉：健康档案导入病历（有 medical_record VIP 时）
 */
function importHealthHistoryToMedicalRecord(fields: Record<string, string>) {
  if (!canUseMedicalRecord.value) {
    message.warning('未开通病历功能');
    return;
  }
  rxMrTab.value = 'mr';
  medicalRecordPanelRef.value?.patchFields?.(fields || {});
}

/** 打开患者信息抽屉 */
function openPatientInfoDrawer() {
  patientInfoDrawerApi.setData({
    patient: activePatient.value,
    register: patientInfo.value,
    healthInquiry: userPatientHealthInquiry.value,
    patientName: activePatient.value?.name,
    canImportMedicalRecord: canUseMedicalRecord.value,
    onImportHistory: importHealthHistoryToMedicalRecord,
  });
  patientInfoDrawerApi.open();
}

/**
 * 打开病历引用抽屉：有 VIP 时切到病历 Tab，优先复用面板内引用逻辑
 */
function openPatientMrCiteDrawer() {
  const patientId = Number(activePatient.value?.id || 0);
  if (!patientId) {
    message.warning('无就诊人信息');
    return;
  }
  if (canUseMedicalRecord.value) {
    rxMrTab.value = 'mr';
  }
  const panel = medicalRecordPanelRef.value as any;
  if (panel?.openCiteHistory) {
    panel.openCiteHistory();
    return;
  }
  patientMrDrawerApi.setData({
    mode: 'cite',
    userPatientId: patientId,
    storeId: Number(myStoreId.value || 0) || undefined,
    patientName: activePatient.value?.name,
    excludeRegisterId: Number(doctorReceptionRegisterId.value || 0),
    onCite: (record: Record<string, any>) => {
      panel?.applyCitedRecord?.(record);
      if (record?.diagnosis) diagnosis.value = String(record.diagnosis);
      if (record?.doctor_order) medicalAdvice.value = String(record.doctor_order);
      if (!panel?.applyCitedRecord) {
        message.success('已引用诊断/医嘱');
      }
    },
  });
  patientMrDrawerApi.open();
}

/** 打开处方记录抽屉 */
function openPatientRxHistoryDrawer() {
  // 挂号 id 必须用 getRegisterId（当前选中挂号），禁止用就诊人 id 冒充
  const registerId = getRegisterId();
  if (!registerId) {
    message.warning('请先选择接诊患者');
    return;
  }
  patientRxHistoryDrawerApi.setData({
    registerId,
    userPatientId: Number(activePatient.value?.id || 0),
    patientName: activePatient.value?.name,
    allowWithdraw: true,
    onProxyPay: openProxyPayQrcode,
    onReuse: reusePrescriptionFromList,
    // 点击处方号打开详情（与医生名片/患者管理一致）
    onDetail: (prescriptionId: number) => openPrescriptionDetail(prescriptionId),
    onWithdrawn: () => {
      if (selectPatientId.value) {
        getPatientItem(selectPatientId.value).then((value) => {
          patientInfo.value = value;
          userPatientHealthInquiry.value = value.user_patient_health_inquiry;
          prescriptionList.value = value.prescription;
        });
      }
    },
  });
  patientRxHistoryDrawerApi.open();
}

function confirmWithdrawPrescription(item: any) {
  const registerId = Number.parseInt(
    localStorage.getItem(`doctorReception-id`) || '0',
    10,
  );
  if (!registerId || !item?.id) {
    message.error('参数错误');
    return;
  }
  AntModal.confirm({
    title: '确认撤回处方？',
    content:
      '撤回后患者将无法继续支付该订单，库存占用将释放。此操作不可撤销。',
    async onOk() {
      try {
        await withdrawPrescriptionApi({
          prescription_id: item.id,
          register_id: registerId,
        });
        message.success('处方已撤回');
        if (selectPatientId.value) {
          const value = await getPatientItem(selectPatientId.value);
          patientInfo.value = value;
          userPatientHealthInquiry.value = value.user_patient_health_inquiry;
          prescriptionList.value = value.prescription;
        }
      } catch (e: any) {
        message.error(
          e?.response?.data?.message || e?.message || '撤回失败',
        );
        return Promise.reject(e);
      }
    },
  });
}

loadProcessRuleData();

/**
 * 中药配置变更（对齐移动端级联逻辑）
 */
async function handleChineseConfigChange(payload: ChineseMedicineConfigChange) {
  if (guardSpecialPrescriptionCartEdit()) return;
  const oldRuleType = ruleType.value;
  const oldProcessRuleId = processRuleId.value;
  const oldChildProcessRuleId = childProcessRuleId.value;

  if (payload.ruleType === 2 && payload.ruleType !== oldRuleType) {
    if (processRuleList.value.length === 0) {
      await loadProcessRuleData();
    }
  }
  if (payload.ruleType === 1 && oldRuleType === 2) {
    processRuleId.value = undefined;
    childProcessRuleId.value = undefined;
    processRuleNoteId.value = undefined;
    processRuleList.value = [];
    childProcessRuleList.value = [];
    processRuleNoteList.value = [];
  }
  if (payload.processRuleId != null && payload.processRuleId !== oldProcessRuleId) {
    childProcessRuleId.value = undefined;
    processRuleNoteId.value = undefined;
    childProcessRuleList.value = [];
    processRuleNoteList.value = [];
  }
  if (payload.childProcessRuleId != null && payload.childProcessRuleId !== oldChildProcessRuleId) {
    processRuleNoteId.value = undefined;
    processRuleNoteList.value = [];
  }

  if (payload.ruleType != null) ruleType.value = payload.ruleType;
  if (payload.packageMethodId !== undefined) packageMethodId.value = payload.packageMethodId ?? 2;
  if (payload.processRuleId !== undefined) processRuleId.value = payload.processRuleId ?? undefined;
  if (payload.childProcessRuleId !== undefined) childProcessRuleId.value = payload.childProcessRuleId ?? undefined;
  if (payload.processRuleNoteId !== undefined) processRuleNoteId.value = payload.processRuleNoteId ?? undefined;
  if (payload.dosage != null) dosage.value = payload.dosage;
  if (payload.dayDosage != null) dayDosage.value = payload.dayDosage;

  if (payload.processRuleId != null && payload.processRuleId !== oldProcessRuleId) {
    await loadProcessRuleData(payload.processRuleId);
  }
  if (payload.childProcessRuleId != null && payload.childProcessRuleId !== oldChildProcessRuleId) {
    await loadProcessRuleData(0, payload.childProcessRuleId);
  }
}

const packageMethodId = ref(2);
const dosage = ref(7);
const dayDosage = ref(2);

watch(
  [
    diagnosis,
    medicalAdvice,
    treatmentPrice,
    ruleType,
    packageMethodId,
    processRuleId,
    childProcessRuleId,
    processRuleNoteId,
    dosage,
    dayDosage,
    priceDiscount,
    activeCategory,
  ],
  () => {
    if (getRegisterId()) {
      debouncedSaveReceptionDraft();
    }
  },
);

/**
 * 清空药方：退出特色方 SKU 计价状态，恢复可编辑
 * @param showToast 是否提示成功
 */
function clearPrescriptionCart(showToast = true) {
  currentDrugs.value = [];
  // 处方清空后 AI 导入内容已不存在，解除采纳关联
  aiRxGenerationId.value = 0;
  diagnosis.value = '';
  medicalAdvice.value = '';
  packageMethodId.value = 2;
  dosage.value = 7;
  dayDosage.value = 2;
  newDrugInfo.value = {};
  clearAppliedSpecialPrescription();
  priceDiscount.value = 100;
  updateLocalStorage();
  clearReceptionDraft(getRegisterId());
  if (showToast) {
    message.success('已清空药方');
  }
}

/** 清空药方（有药品时二次确认） */
function handleClearPrescriptionCart() {
  if (currentDrugs.value.length === 0 && !appliedSpecialPrescriptionId.value) {
    message.info('当前无药方内容');
    return;
  }
  AntModal.confirm({
    title: '清空药方',
    content: '确定清空当前药方吗？特色方将需重新应用。',
    okText: '确定',
    cancelText: '取消',
    onOk: () => clearPrescriptionCart(),
  });
}

function updateChineseNumber() {
  updateLocalStorage();
}

// 二次签名确认弹窗
const doctorSecondSignModal = ref(false);

/**
 * 在新的药品数量框失去焦点后弹出新药品弹窗
 * 中药克数不设默认值，未填写时不弹确认，避免误加 1g
 */
function newDrugBlur() {
  if (newDrugInfo.value.id && newDrugInfo.value.name && newDrugInfo.value.number > 0) {
    confirmModalApi.setData({
      title: '确认添加',
      content: `要把【${newDrugInfo.value.name}】添加到清单吗？`,
      onConfirm: addDrugByChinese,
    });
    confirmModalApi.open();
  }
}

function doctorSecondSignModalOk() {
  doctorSecondSign.value = 1;
  doctorSecondSignModal.value = false;
  sendPrescription();
}

function updateChineseNumberGoNewDrug(event: KeyboardEvent) {
  if (event.key === 'Enter') {
    updateLocalStorage();
    setTimeout(() => {
      // 获取新药品卡片中的克数输入框并聚焦
      const newDrugNumberInput = document.querySelector(
        '.new-select-drug-name input',
      );
      if (newDrugNumberInput) {
        (newDrugNumberInput as HTMLElement).focus();
      }
    }, 100);
  }
}

/**
 * 获取药品列表
 * @param {string} searchText - 搜索关键词
 */
const getDrugListByWesternModal = debounce(async (searchText = '') => {
  if (searchText === '' && activeCategory.value === 1) {
    drugList.value = [];
    return;
  }

  getCurrentDrugs();

  try {
    const registerId = Number.parseInt(
      localStorage.getItem('doctorReception-id') || '0',
      10,
    );
    const res = await getProductListDoctorReception({
      store_id: myStoreId.value,
      type: activeCategory.value,
      name: searchText,
      ...(registerId > 0 ? { register_id: registerId } : {}),
    });

    drugList.value = res.map((item) => {
      const matched = currentDrugs.value.find((v) => v.index_id === item.id);
      return {
        ...item,
        select_number: matched?.select_number || 0,
        drug: {
          ...item.drug,
          // 中药克数不默认 1，需医生手动填写；西药仍默认 1
          number:
            matched?.number ??
            (activeCategory.value === 1 ? undefined : 1),
        },
      };
    });
  } catch (error) {
    console.error('获取药品列表失败:', error);
    message.error('获取药品列表失败');
  }
}, 300);

// getDrugListByWesternModal();

/** 新行中药气泡选中的完整商品（添加时用，避免再依赖 drugList） */
const pendingNewChineseProduct = ref<any>(null);

/**
 * 中药气泡：选中新增行药名
 * @param item 商品检索完整行
 */
function onSelectNewChineseDrug(item: any) {
  const drugId = Number(item?.drug_id || item?.drug?.id || 0);
  if (!drugId) return;
  const check = currentDrugs.value.find((v) => Number(v.id) === drugId);
  if (check) {
    newDrugInfo.value.id = '';
    newDrugInfo.value.name = '';
    pendingNewChineseProduct.value = null;
    message.error('该药品已经在处方中了！');
    return;
  }
  pendingNewChineseProduct.value = item;
  newDrugInfo.value.id = drugId;
  newDrugInfo.value.price = item.price;
  newDrugInfo.value.name = item.drug?.drug_name || '';
  newDrugInfo.value.unit =
    item.drug?.unit ||
    drugUnit.value.find((u) => u.id === item.drug?.unit_id);
  newDrugInfo.value.unit_id = item.drug?.unit_id;
  setTimeout(() => {
    const newDrugNumberInput = document.querySelector(
      '.new-number-input input',
    );
    if (newDrugNumberInput) {
      (newDrugNumberInput as HTMLElement).focus();
    }
  }, 100);
}

/**
 * 中药气泡：替换已选行药名
 * @param index 行下标
 * @param item 商品检索完整行
 */
function onSelectOldChineseDrug(index: number, item: any) {
  if (guardSpecialPrescriptionCartEdit()) return;
  const drugId = Number(item?.drug?.id || item?.drug_id || 0);
  if (!drugId) return;
  const check = currentDrugs.value.find(
    (v, i) => i !== index && Number(v.id) === drugId,
  );
  if (check) {
    message.error('该药品已经在处方中了！');
    return;
  }
  const data = item;
  const newProduct = {
    index_id: data.id,
    id: data.drug.id,
    drug_name: data.drug.drug_name,
    number: data.drug.number,
    use_num: drugTime.value.find((u) => u.id === data.drug.time_id),
    use_type: drugUseType.value.find((u) => u.id === data.drug.type_id),
    use_frequency: drugUseFrequency.value.find(
      (u) => u.id === data.drug.frequency_id,
    ),
    unit:
      data.drug?.unit ||
      drugUnit.value.find((u) => u.id === data.drug.unit_id),
    price: data.price,
    buy_price: data.buy_price,
    way_id: data.drug?.way_id,
    use_ways: drugUseWay.value.find((u) => u.id === data.drug.way_id),
    time_id: data.drug.time_id,
    type_id: data.drug.type_id,
    frequency_id: data.drug.frequency_id,
    unit_id: data.drug.unit_id,
    image: data.drug.image,
    instruction: data.drug.instruction,
    type: data.drug.type,
  };
  currentDrugs.value[index] = newProduct;
  updateLocalStorage();
  setTimeout(() => {
    const numberInput = document.querySelector(
      `.old-number-input-${index} input`,
    );
    if (numberInput) {
      (numberInput as HTMLElement).focus();
    }
  }, 100);
}

/** 兼容西药等仍走 Select 的旧逻辑 */
function selectNewDrugInfo() {
  const check = currentDrugs.value.find((v) => v.id === newDrugInfo.value.id);
  if (check) {
    newDrugInfo.value.id = '';
    message.error('该药品已经在处方中了！');
    return;
  }
  const data = drugList.value.find((v) => v.drug_id === newDrugInfo.value.id);
  if (!data) return;
  pendingNewChineseProduct.value = data;
  newDrugInfo.value.price = data.price;
  newDrugInfo.value.name = data.drug.drug_name;
  newDrugInfo.value.unit =
    data.drug?.unit ||
    drugUnit.value.find((item) => item.id === data.drug?.unit_id);
  newDrugInfo.value.unit_id = data.drug?.unit_id;
  setTimeout(() => {
    const newDrugNumberInput = document.querySelector(
      '.new-number-input input',
    );
    if (newDrugNumberInput) {
      (newDrugNumberInput as HTMLElement).focus();
    }
  }, 100);
}

const selectChineseIndex = ref(-1);
const selectChineseId = ref(0);

/**
 * 选择药品（西药等 Select 仍用）
 * @param id
 */
function selectOldDrugInfo(id) {
  if (guardSpecialPrescriptionCartEdit()) return;
  const check = JSON.parse(
    localStorage.getItem(getStorageKey(getRegisterId(), activeCategory.value)) || '[]',
  ).find((v) => v.id === id);
  if (check) {
    currentDrugs.value[selectChineseIndex.value].id = selectChineseId.value;
    drugList.value = [];
    message.error('该药品已经在处方中了！');
    return;
  }
  const data = drugList.value.find((v) => v.drug_id === id);
  if (!data) return;
  const newProduct = {
    index_id: data.id,
    id: data.drug.id,
    drug_name: data.drug.drug_name,
    number: data.drug.number,
    use_num: drugTime.value.find((item) => item.id === data.drug.time_id),
    use_type: drugUseType.value.find((item) => item.id === data.drug.type_id),
    use_frequency: drugUseFrequency.value.find(
      (item) => item.id === data.drug.frequency_id,
    ),
    unit:
      data.drug?.unit ||
      drugUnit.value.find((item) => item.id === data.drug.unit_id),
    price: data.price,
    buy_price: data.buy_price,
    way_id: data.drug?.way_id,
    use_ways: drugUseWay.value.find((item) => item.id === data.drug.way_id),
    time_id: data.drug.time_id,
    type_id: data.drug.type_id,
    frequency_id: data.drug.frequency_id,
    unit_id: data.drug.unit_id,
    image: data.drug.image,
    instruction: data.drug.instruction,
    type: data.drug.type,
  };
  currentDrugs.value[selectChineseIndex.value] = newProduct;
  updateLocalStorage();
  setTimeout(() => {
    const newDrugNumberInput = document.querySelector(
      `.old-number-input-${selectChineseIndex.value} input`,
    );
    if (newDrugNumberInput) {
      (newDrugNumberInput as HTMLElement).focus();
    }
  }, 100);
}

/**
 * 写入当前修改的下标
 * @param index
 */
function setSelectChineseIndex(index, id) {
  selectChineseIndex.value = index;
  selectChineseId.value = id;
}

/**
 * 查询中药列表
 * @param inputValue
 */
function searchOption(inputValue) {
  getDrugListByWesternModal(inputValue);
}

/**
 * 添加中药
 */
function addDrugByChinese() {
  if (guardSpecialPrescriptionCartEdit()) return;
  const check = currentDrugs.value.find(
    (v) => v.id === newDrugInfo.value.id,
  );
  if (check) {
    message.error('该药品已经在处方中了！');
    return;
  }
  // 优先用气泡选中缓存，兼容西药 Select 仍写在 drugList 的场景
  const data =
    pendingNewChineseProduct.value ||
    drugList.value.find((v) => v.drug_id === newDrugInfo.value.id);
  if (data === null || data === undefined) {
    message.error('请选择药品');
    return;
  }
  data.drug.number = newDrugInfo.value.number;
  data.drug.way_id = newDrugInfo.value.way_id;
  addProducts(data);
  newDrugInfo.value = {};
  pendingNewChineseProduct.value = null;
}
/**
 * 添加操作
 */
function selectDrugByNewDrugInfo(event: KeyboardEvent, isNewDrug: boolean) {
  // 如果按下的是回车键
  if (event.key === 'Enter') {
    // 阻止默认行为（防止表单提交）
    event.preventDefault();

    if (isNewDrug) {
      // 如果是新药品输入框，调用添加新药品方法
      addDrugByChinese();
    } else {
      // 如果是已有药品输入框，调用更新数量方法
      updateChineseNumber();
    }
    setTimeout(() => {
      // 获取新药品卡片中的克数输入框并聚焦
      const newDrugNumberInput = document.querySelector(
        '.new-select-drug-name input',
      );
      if (newDrugNumberInput) {
        (newDrugNumberInput as HTMLElement).focus();
      }
    }, 100);
  }
}

/**
 * 添加商品到处方
 * @param {object} data - 商品对象
 */
function addProducts(data) {
  if (guardSpecialPrescriptionCartEdit()) return;
  // 查找是否已存在于选择列表中
  const existItem = currentDrugs.value.find(
    (item) => item.index_id === data.id,
  );

  if (existItem) {
    message.warn('已经存在了');
    return;
  }
  // 创建新的商品对象（避免直接修改原始数据）
  const newProduct = {
    // 索引ID（用于在列表中查找）
    index_id: data.id,
    // 药品ID
    id: data.drug.id,
    // 药品名称
    drug_name: data.drug.drug_name,
    // 药品数量
    number: data.drug.number,
    // 药品使用数量信息
    use_num: drugTime.value.find((item) => item.id === data.drug.time_id),
    // 药品使用类型信息
    use_type: drugUseType.value.find((item) => item.id === data.drug.type_id),
    // 药品使用频率信息
    use_frequency: drugUseFrequency.value.find(
      (item) => item.id === data.drug.frequency_id,
    ),
    // 药品单位：优先用选药接口返回的 unit，再回退本地字典
    unit:
      data.drug?.unit ||
      drugUnit.value.find((item) => item.id === data.drug.unit_id),
    // 药品价格
    price: data.price,
    buy_price: data.buy_price,
    // 药品使用方式ID
    way_id: data.drug?.way_id,
    // 药品使用方式信息
    use_ways: drugUseWay.value.find((item) => item.id === data.drug.way_id),
    // 药品使用时间ID
    time_id: data.drug.time_id,
    // 药品类型ID
    type_id: data.drug.type_id,
    // 药品使用频率ID
    frequency_id: data.drug.frequency_id,
    // 药品单位ID
    unit_id: data.drug.unit_id,
    // 药品图片
    image: data.drug.image,
    // 药品说明书
    instruction: data.drug.instruction,
    // 药品类型
    type: data.drug.type,
  };

  // 首次添加，初始化数量为1
  newProduct.select_number = 1;

  // 添加到选中列表
  currentDrugs.value.push(newProduct);

  // 更新本地存储
  updateLocalStorage();

  // 提示成功
  message.success(`已将${newProduct.drug_name}添加到清单中！`);
}

/**
 * 处理DrugSearchSelect组件的select事件（用于新类型：3,5,6,7）
 * @param drug 选中的药品数据
 */
function handleSimpleProductSelect(drug: any) {
  if (guardSpecialPrescriptionCartEdit()) return;
  // 检查是否已存在
  const existItem = currentDrugs.value.find(
    (item) => item.id === (drug._drugId || drug.drug_id || drug.drug?.id),
  );

  if (existItem) {
    message.warning('该商品已在列表中');
    return;
  }

  // 创建新的商品对象（简化版，不需要用法用量字段）
  const newProduct = {
    index_id: drug._id || drug.id,
    id: drug._drugId || drug.drug_id || drug.drug?.id,
    drug_name: drug._drugName || drug.drug?.drug_name || drug.drug_name,
    number: 1,
    price: drug._price || drug.price,
    image: drug._image || drug.drug?.image || drug.image,
    instruction: drug.drug?.instruction || drug.instruction || '',
    type: drug.drug?.type || drug.type || activeCategory.value,
    select_number: 1,
  };

  // 添加到选中列表
  currentDrugs.value.push(newProduct);

  // 更新本地存储
  updateLocalStorage();

  // 提示成功
  message.success(`已将${newProduct.drug_name}添加到清单中！`);
}

const newDrugInfo = ref({});

/**
 * 获取转诊信息
 * @param transferPrescriptionId 转诊处方ID
 */
const fetchTransferPrescription = async (transferPrescriptionId: number) => {
  if (!transferPrescriptionId) return;

  loadingTransfer.value = true;
  try {
    // 通过转诊处方ID获取转诊信息
    // 注意：这里需要根据实际API调整，可能需要通过register_id获取
    const registerId = Number.parseInt(localStorage.getItem(`doctorReception-id`));
    if (registerId) {
      const res = await getTransferPrescriptionByRegisterApi(registerId);
      const data = res?.result || res?.data || res;
      if (data && data.id) {
        transferPrescription.value = data;
      } else {
        transferPrescription.value = null;
      }
    }
  } catch (error) {
    console.error('获取转诊信息失败:', error);
    transferPrescription.value = null;
  } finally {
    loadingTransfer.value = false;
  }
};

/**
 * 处理转诊导入成功
 */
const handleTransferImportSuccess = () => {
  // 转诊导入成功后，可以刷新患者信息
  if (selectPatientId.value) {
    getPatientItem(selectPatientId.value).then((value) => {
      patientInfo.value = value;
      userPatientHealthInquiry.value = value.user_patient_health_inquiry;
      prescriptionList.value = value.prescription;
    });
  }
};

function switchStore(id) {
  switchStoreApi({store_id: id}).then(() => {
    myStoreId.value = id;
    updateLocalStorageStoreInfo();
    // 根据id在storeList中查找诊所名称
    const storeInfo = myStoreList.value.find((item) => item.id === id);
    message.success(`已经切换到【${storeInfo.name}】`);
  });
}

/**
 * 储存本地缓存
 */
function updateLocalStorageStoreInfo() {
  localStorage.setItem(`myStoreId`, myStoreId.value);
  userStore.userInfo.store_id = myStoreId.value;
  userStore.setUserInfo(userStore.userInfo);
  tabType.value = 0;
  getPatientListByReception();
}
/**
 * 患者列表：默认收起；鼠标悬停展开，移出自动收起；可点击钉住保持展开
 * leftShow = 钉住 || 悬停
 */
const leftPinned = ref(false);
const leftHover = ref(false);
let leftLeaveTimer: ReturnType<typeof setTimeout> | null = null;
/** 门店下拉打开时暂不因 mouseleave 收起（下拉挂到 body） */
const storeSelectOpen = ref(false);

const leftShow = computed(() => leftPinned.value || leftHover.value);

function getDoctorReceptionLeftPinned() {
  const v = localStorage.getItem('doctorReceptionLeftPinned');
  leftPinned.value = v === 'true';
}
getDoctorReceptionLeftPinned();

watch(
  () => leftPinned.value,
  (enable) => {
    localStorage.setItem('doctorReceptionLeftPinned', String(!!enable));
  },
);

/** 侧栏进入：取消待收起并展开 */
function onPatientSidebarEnter() {
  if (leftLeaveTimer) {
    clearTimeout(leftLeaveTimer);
    leftLeaveTimer = null;
  }
  leftHover.value = true;
}

/** 侧栏离开：短暂延迟后收起，避免点到下拉/滚动条误收 */
function onPatientSidebarLeave() {
  if (leftLeaveTimer) clearTimeout(leftLeaveTimer);
  leftLeaveTimer = setTimeout(() => {
    if (!storeSelectOpen.value) {
      leftHover.value = false;
    }
  }, 280);
}

/** 点击钉住/取消钉住（展开时显示） */
function toggleLeftPinned() {
  leftPinned.value = !leftPinned.value;
  if (leftPinned.value) {
    leftHover.value = true;
  }
}

/** 门店下拉显隐：打开时保持展开；关闭后若未钉住则按离开逻辑收起 */
function onStoreSelectOpenChange(open: boolean) {
  storeSelectOpen.value = open;
  if (open) {
    onPatientSidebarEnter();
  } else if (!leftPinned.value) {
    onPatientSidebarLeave();
  }
}
</script>

<template>
  <div class="reception-layout" :class="{ 'is-left-collapsed': !leftShow }">
    <RefusalOfTreatmentModals />
    <CreateUserPatientModals />
    <ClaimQrcodeModals />
    <ProxyPayQrcodeModals />
    <InfoModalComponent />
    <!-- 左侧患者列表：悬停展开、移出收起；收起态仅箭头+背景提示 -->
    <aside
      class="patient-sidebar"
      @mouseenter="onPatientSidebarEnter"
      @mouseleave="onPatientSidebarLeave"
    >
      <!-- 收起态：箭头图标 + 背景条，提示可悬停展开 -->
      <div
        v-show="!leftShow"
        class="patient-sidebar__collapsed"
        title="悬停展开患者列表"
      >
        <MenuUnfoldOutlined class="patient-sidebar__collapsed-icon" />
      </div>
      <div v-show="leftShow" class="patient-sidebar__toggle">
        <Button
          type="primary"
          size="small"
          class="patient-sidebar__toggle-btn"
          :title="leftPinned ? '取消固定，移出后收起' : '固定展开'"
          @click="toggleLeftPinned"
        >
          <MenuFoldOutlined v-if="leftPinned" />
          <MenuUnfoldOutlined v-else />
          <span class="patient-sidebar__toggle-text">{{
            leftPinned ? '取消固定' : '固定'
          }}</span>
        </Button>
      </div>
      <div class="patient-panel">
        <Select
          v-model:value="myStoreId"
          class="w-full"
          @change="switchStore"
          @dropdown-visible-change="onStoreSelectOpenChange"
        >
          <SelectOption v-for="item in myStoreList" :key="item.id" :value="item.id">
            {{ item.name }}
          </SelectOption>
        </Select>
        <div class="patient-list-toolbar flex items-center gap-1">
          <RadioGroup
            v-model:value="listType"
            class="min-w-0 flex-1"
            style="text-align: center"
            @change="updatePatientList"
          >
            <RadioButton :value="1" class="w-1/2">当前</RadioButton>
            <RadioButton :value="2" class="w-1/2">历史</RadioButton>
          </RadioGroup>
          <Button
            type="text"
            size="small"
            class="patient-list-refresh-btn shrink-0"
            title="刷新患者列表"
            :loading="patientListRefreshing"
            @click="refreshPatientList"
          >
            <ReloadOutlined />
          </Button>
        </div>
        <div class="patient-list-actions mb-2 mt-1 flex flex-wrap gap-1">
          <Button size="small" type="primary" ghost @click="openCreateUserPatientModal">
            <UserAddOutlined />
            就诊人
          </Button>
        </div>
        <div
          v-for="(patient, index) in patients"
          :key="index"
        >
          <div
            v-if="patient.user_patient"
            :class="{ active: selectPatientId === patient.id }"
            class="patient-card"
            @click="selectPatient(patient)"
          >
            <div class="patient-info">
              <h3 class="flex flex-wrap items-center gap-2">
                {{ patient.user_patient.name }}
                <Tag
                  v-if="patient.special_prescription_patient_record"
                  :color="patient.special_prescription_patient_record.status === 0 ? 'orange' : 'default'"
                >
                  特色方{{
                    patient.special_prescription_patient_record.status === 0
                      ? '·待导入'
                      : ''
                  }}
                </Tag>
              </h3>
              <p class="phone">
                <SensitiveText :record="patient.user_patient" field="mobile" :show-eye="false" />
              </p>
              <p class="text-sm text-gray-500">
                推广员：{{ patient.salesperson?.nick_name || '无' }}
              </p>
              <span :class="getRegisterStatus(patient.status)" class="status">{{
                  getRegisterStatus(patient.status)
                }}</span>
              {{ patient.updated_at }}
            </div>
          </div>
        </div>
      </div>
    </aside>

    <!-- 右侧主区域 -->
    <div class="reception-main">
    <!-- 开方页返回：右上角悬浮，不占布局高度 -->
    <!-- 右侧：未接诊轻量操作区 / 已接诊开方工作台 -->
    <Page v-if="tabType === 1" class="prescription-panel">
      <PatientBriefBar
        :register="patientInfo"
        :patient="activePatient"
        :category="category"
        :store-name="currentStoreName"
        :is-online="false"
      />
      <div class="prescription-header flex flex-wrap gap-2">
        <Button
          v-if="receptionStatus === 1"
          class="send-btn"
          type="primary"
          @click="reception"
        >
          接诊
        </Button>
        <Button
          v-if="receptionStatus === 1"
          class="send-btn"
          type="primary"
          danger
          @click="refuseReception"
        >
          拒诊
        </Button>
        <Button type="link" size="small" @click="openPatientInfoDrawer">患者信息</Button>
        <Button type="link" size="small" @click="openPatientMrCiteDrawer">患者病历</Button>
        <Button type="link" size="small" @click="openPatientRxHistoryDrawer">处方记录</Button>
        <Button
          v-if="isActivePatientUnclaimed"
          type="link"
          size="small"
          @click="openClaimQrcodeModal"
        >
          <QrcodeOutlined />
          认领码
        </Button>
      </div>
      <SpecialPrescriptionImportCard
        v-if="specialPrescriptionRecord && hasSpecialPrescriptionRecord"
        class="mt-4 max-w-xl"
        :record="specialPrescriptionRecord"
        :purchase-label="specialPrescriptionPurchaseLabel"
        :loading="applyingSpecialPrescription"
        @apply="handleApplySpecialPrescription(true)"
      />
      <div v-if="transferPrescription" class="transfer-section mt-5">
        <TransferPrescriptionCard
          :transfer-data="transferPrescription"
          :register-id="doctorReceptionRegisterId"
          @import-success="handleTransferImportSuccess"
        />
      </div>
    </Page>

    <Page v-if="tabType === 2" class="prescription-panel prescription-panel--rx">
      <Spin :spinning="prescriptionTypeLoading">
      <div class="rx-workspace">
      <!-- 顶栏固定：患者简要 + 一级 Tab + 处方工具栏 -->
      <div class="rx-workspace-sticky">
      <PatientBriefBar
        :register="patientInfo"
        :patient="activePatient"
        :category="category"
        :store-name="currentStoreName"
        :is-online="false"
      />
      <template v-if="prescriptionTypeAllowed">
      <!-- 一级 Tab + 右侧紧凑操作（吸顶） -->
      <Tabs
        v-model:active-key="rxMrTab"
        class="mb-0 rx-primary-tabs"
      >
        <TabPane key="rx" tab="处方" />
        <TabPane v-if="canUseMedicalRecord" key="mr" tab="病历" />
        <template #rightExtra>
          <div class="rx-tab-extra-actions">
            <Button type="link" size="small" @click="openPatientInfoDrawer">
              <UserOutlined />
              患者信息
            </Button>
            <Button type="link" size="small" @click="openPatientMrCiteDrawer">
              <FileTextOutlined />
              患者病历
            </Button>
            <Button type="link" size="small" @click="openPatientRxHistoryDrawer">
              <MedicineBoxOutlined />
              处方记录
            </Button>
            <Button
              v-if="isActivePatientUnclaimed"
              type="link"
              size="small"
              @click="openClaimQrcodeModal"
            >
              <QrcodeOutlined />
              认领码
            </Button>
            <Button
              v-if="receptionStatus === 2"
              type="link"
              size="small"
              danger
              @click="endOfDiagnosis"
            >
              <StopOutlined />
              结束诊断
            </Button>
          </div>
        </template>
      </Tabs>

      <!-- 处方工具栏：仅处方态吸顶 -->
      <div
        v-if="!canUseMedicalRecord || rxMrTab === 'rx'"
        class="rx-workspace-toolbar mt-1 mb-1 flex flex-wrap items-center gap-1"
      >
        <Button
          v-if="activeCategory === 2 && !isSpecialPrescriptionCartLocked"
          type="link"
          size="small"
          @click="openWesternModal"
        >
          <PlusOutlined />
          添加商品
        </Button>
        <Button
          v-if="canUseCommonPrescription"
          type="link"
          size="small"
          @click="openCommonPrescriptionModal"
        >
          <BookOutlined />
          选择常用方
        </Button>
        <Button
          v-if="activeCategory === 1 && !isSpecialPrescriptionCartLocked && canUseGoldenFormula"
          type="link"
          size="small"
          @click="openGoldenFormulaModal"
        >
          <MedicineBoxOutlined />
          导入金方
        </Button>
        <Button
          v-if="!isSpecialPrescriptionCartLocked && canUseAiPrescription"
          type="link"
          size="small"
          @click="openAiPrescriptionDrawer"
        >
          <RobotOutlined />
          AI辅助出方
        </Button>
        <Button
          v-if="canUseCommonPrescription"
          type="link"
          size="small"
          @click="openSaveCommonPrescriptionModal"
        >
          <SaveOutlined />
          保存常用方
        </Button>
        <Button
          type="link"
          size="small"
          danger
          @click="handleClearPrescriptionCart"
        >
          <ClearOutlined />
          清空药方
        </Button>
        <Button
          v-if="activeCategory === 1 && hasSalespersonTransfer"
          type="link"
          size="small"
          @click="salespersonTransferDrawerOpen = true"
        >
          <SwapOutlined />
          查看传方
        </Button>
        <RadioGroup
          v-if="allowInsuranceCategory === 1"
          v-model:value="category"
          size="small"
          class="ml-2"
        >
          <RadioButton :value="1">自费</RadioButton>
          <RadioButton :value="2">医保</RadioButton>
        </RadioGroup>
      </div>

      <!-- 病历工具栏：仅病历态吸顶 -->
      <div
        v-if="canUseMedicalRecord && rxMrTab === 'mr'"
        class="rx-workspace-toolbar mt-1 mb-1 flex flex-wrap items-center gap-1"
      >
        <Button
          type="link"
          size="small"
          danger
          @click="medicalRecordPanelRef?.clear?.()"
        >
          <ClearOutlined />
          清空病历
        </Button>
        <Button
          type="link"
          size="small"
          @click="medicalRecordPanelRef?.openCiteHistory?.()"
        >
          <HistoryOutlined />
          引用历史病历
        </Button>
        <Button
          v-if="canUseAiMedicalRecord"
          type="link"
          size="small"
          @click="medicalRecordPanelRef?.aiGenerate?.()"
        >
          <RobotOutlined />
          AI写病历
        </Button>
        <Button
          type="link"
          size="small"
          @click="medicalRecordPanelRef?.save?.()"
        >
          <SaveOutlined />
          保存病历
        </Button>
      </div>
      </template>
      </div>
      <!-- /rx-workspace-sticky -->

      <Empty
        v-if="!prescriptionTypeLoading && !prescriptionTypeAllowed"
        :description="prescriptionTypeDenyMessage || '当前门店未开通开方权限'"
        class="py-20"
      />

      <div
        v-else
        class="rx-workspace-scroll"
      >
      <div v-show="!canUseMedicalRecord || rxMrTab === 'rx'">
      <!-- 二级 Tab：处方类型，随内容区滚动，病历态不展示 -->
      <Tabs
        :active-key="String(activeCategory)"
        class="rx-secondary-tabs mb-2"
        size="small"
        @change="(key) => tabChange(Number(key))"
      >
        <TabPane
          v-for="categoryItem in categories"
          :key="String(categoryItem.value)"
        >
          <template #tab>
            <span
              :id="`rx-pc-tab-${categoryItem.value}`"
              class="rx-secondary-tab-label"
            >
              <img
                v-if="categoryItem.icon"
                class="tab-type-icon"
                :src="categoryItem.icon"
                alt=""
              />
              <span>{{ categoryItem.label }}</span>
              <span
                v-if="categoryItem.icon_text"
                class="tab-type-badge"
              >{{ categoryItem.icon_text }}</span>
            </span>
          </template>
        </TabPane>
      </Tabs>
      <div class="rx-swipe-panel">

      <SpecialPrescriptionImportCard
        v-if="hasSpecialPrescriptionRecord"
        class="mt-5 max-w-xl"
        :record="specialPrescriptionRecord"
        :purchase-label="specialPrescriptionPurchaseLabel"
        :loading="applyingSpecialPrescription"
        @apply="() => handleApplySpecialPrescription()"
      />

      <SalespersonTransferDrawer
        v-model:open="salespersonTransferDrawerOpen"
        :register-id="doctorReceptionRegisterId"
        @import="handleSalespersonTransferImport"
      />
      <div style="width: 0; height: 0; overflow: hidden">
        <ImagePreviewGroup
          :preview="{
            visible,
            onVisibleChange: setVisible,
          }"
          :style="{ display: 'none' }"
        >
          <Image
            v-for="image in previewImage"
            v-if="visible === true"
            :src="image"
            :width="200"
          />
        </ImagePreviewGroup>
      </div>
      <!-- 已选药品列表 -->
      <div v-if="activeCategory === 1" class="mb-3 mt-2 text-base font-medium text-gray-700">
        已选 {{ currentDrugs.length }} 种药
      </div>
      <!-- 中药 -->
      <div v-if="activeCategory === 1" class="mb-5 mt-3 flex" style="flex-wrap: wrap; width: 100%;">
        <Row>
          <Col
            v-for="(drug, index) in currentDrugs"
            :key="`${drug.index_id || drug.id}-${index}`"
            :lg="12"
            :md="24"
            :sm="24"
            :xl="leftShow ? 12 : 8"
            :xs="leftShow ? 12 : 8"
            :xxl="leftShow ? 8 : 6"
          >
            <Card class="mt-0" title="">
              <div>
                <span class="card-index">{{ index + 1 }}、</span>
                <p>
                  <ChineseDrugNameBubble
                    :display-name="drug.drug_name"
                    :disabled="isSpecialPrescriptionCartLocked"
                    :store-id="myStoreId"
                    :register-id="getRegisterId()"
                    :type="1"
                    compact
                    input-class="old-select-drug-name"
                    placeholder="药名"
                    @select="(item) => onSelectOldChineseDrug(index, item)"
                  />
                  ,
                  <InputNumber
                    v-model:value="drug.number"
                    :disabled="isSpecialPrescriptionCartLocked"
                    :class="`w-1/5 old-number-input-${index}`"
                    style="min-width: 100px"
                    :controls="false"
                    @blur="updateChineseNumber"
                    @keydown="updateChineseNumberGoNewDrug($event)"
                  >
                    <template #addonAfter>{{ drug.unit?.name || 'g' }}</template>
                  </InputNumber>
                  ,
                  <span>
                    <Select
                      :value="drug?.way_id"
                      :disabled="isSpecialPrescriptionCartLocked"
                      placeholder="用法"
                      @change="selectDrugUseWayChange"
                      @dropdown-visible-change="
                        selectProductChange(index)
                      "
                    >
                      <SelectOption :value="0">煎服</SelectOption>
                      <SelectOption
                        v-for="(value, index) in drugUseWay"
                        :key="index"
                        :value="value.id"
                      >
                        {{ value.name }}
                      </SelectOption>
                    </Select>
                  </span>
                  <p class="card-price">
                    ￥<span>{{ (drug.price * (drug.number || 0)).toFixed(2) }}</span>
                    <span
                      v-if="getChineseItemMargin(drug) && getChineseItemMargin(drug) !== '--'"
                      class="ml-2 text-gray-500 text-sm"
                    >
                      毛利率 {{ getChineseItemMargin(drug) }}%
                    </span>
                  </p>
                  <Button
                    v-if="!isSpecialPrescriptionCartLocked"
                    class="card-delete"
                    type="link"
                    @click="removeDrug(index)"
                  >
                    <DeleteTwoTone/>
                  </Button>
                </p>
              </div>
            </Card>
          </Col>
          <Col
            v-if="!isSpecialPrescriptionCartLocked"
            :lg="12"
            :md="12"
            :sm="12"
            :xl="leftShow ? 12 : 8"
            :xs="leftShow ? 12 : 8"
            :xxl="leftShow ? 8 : 6"
          >
            <Card title="">
              <div>
                <span class="card-index">{{ currentDrugs.length + 1 }}、</span>
                <div>
                  <ChineseDrugNameBubble
                    :display-name="newDrugInfo.name || ''"
                    :store-id="myStoreId"
                    :register-id="getRegisterId()"
                    :type="1"
                    compact
                    input-class="new-select-drug-name"
                    placeholder="药名"
                    @select="onSelectNewChineseDrug"
                  />
                  ,
                  <InputNumber
                    v-model:value="newDrugInfo.number"
                    class="new-number-input w-1/5"
                    style="min-width: 100px"
                    @blur="newDrugBlur"
                    @keydown="selectDrugByNewDrugInfo($event, true)"
                  >
                    <template #addonAfter>{{ newDrugInfo.unit?.name || 'g' }}</template>
                  </InputNumber>
                  ,
                  <span>
                    <Select
                      v-model:value="newDrugInfo.way_id"
                      placeholder="用法"
                      @keydown="selectDrugByNewDrugInfo($event, true)"
                    >
                      <SelectOption :value="0">煎服</SelectOption>
                      <SelectOption
                        v-for="(value, index) in drugUseWay"
                        :key="index"
                        :value="value.id"
                      >
                        {{ value.name }}
                      </SelectOption>
                    </Select>
                  </span>
                  <p class="card-price">
                    ￥<span>{{
                      (
                        (newDrugInfo.price || 0) * (newDrugInfo.number || 0)
                      ).toFixed(2)
                    }}元</span>
                  </p>
                </div>
              </div>
            </Card>
          </Col>
          <!-- 不知道为什么会出问题 -->
          <Col
            v-if="currentDrugs.length < 3"
            :lg="12"
            :md="24"
            :sm="24"
            :xl="12"
            :xs="24"
            :xxl="8"
          >

            <Card title="" style="opacity: 0">
              <div>
                <span class="card-index">{{ currentDrugs.length + 1 }}、</span>
                <div>
                  <Select
                    v-model:value="newDrugInfo.id"
                    :filter-option="false"
                    class="new-select-drug-name w-1/5"
                    style="min-width: 100px"
                    placeholder="药名"
                    show-search
                    @change="selectNewDrugInfo"
                    @search="searchOption"
                    disabled
                  >
                    <SelectOption
                      v-for="(value, index) in drugList"
                      :key="index"
                      :value="value.drug_id"
                      disabled
                    >
                      {{ value.drug.drug_name }}
                    </SelectOption>
                  </Select>
                  ,
                  <InputNumber
                    v-model:value="newDrugInfo.number"
                    class="new-number-input w-1/5"
                    style="min-width: 100px"
                    @blur="updateChineseNumber"
                    @keydown="selectDrugByNewDrugInfo($event, true)"
                    disabled
                  >
                    <template #addonAfter>{{ newDrugInfo.unit?.name || 'g' }}</template>
                  </InputNumber>
                  ,
                  <span>
                    <Select
                      v-model:value="newDrugInfo.way_id"
                      placeholder="用法"
                      @keydown="selectDrugByNewDrugInfo($event, true)"
                      disabled
                    >
                      <SelectOption :value="0">煎服</SelectOption>
                      <SelectOption
                        v-for="(value, index) in drugUseWay"
                        :key="index"
                        :value="value.id"
                      >
                        {{ value.name }}
                      </SelectOption>
                    </Select>
                  </span>
                  <p class="card-price">
                    ￥<span>{{
                      (
                        (newDrugInfo.price || 0) * (newDrugInfo.number || 0)
                      ).toFixed(2)
                    }}元</span>
                  </p>
                </div>
              </div>
            </Card>
          </Col>
          <Col
            v-if="currentDrugs.length < 3"
            :lg="12"
            :md="24"
            :sm="24"
            :xl="12"
            :xs="24"
            :xxl="8"
          >

            <Card title="" style="opacity: 0">
              <div>
                <span class="card-index">{{ currentDrugs.length + 1 }}、</span>
                <div>
                  <Select
                    v-model:value="newDrugInfo.id"
                    :filter-option="false"
                    class="new-select-drug-name w-1/5"
                    style="min-width: 100px"
                    placeholder="药名"
                    show-search
                    @change="selectNewDrugInfo"
                    @search="searchOption"
                    disabled
                  >
                    <SelectOption
                      v-for="(value, index) in drugList"
                      :key="index"
                      :value="value.drug_id"
                      disabled
                    >
                      {{ value.drug.drug_name }}
                    </SelectOption>
                  </Select>
                  ,
                  <InputNumber
                    v-model:value="newDrugInfo.number"
                    class="new-number-input w-1/5"
                    style="min-width: 100px"
                    @blur="updateChineseNumber"
                    @keydown="selectDrugByNewDrugInfo($event, true)"
                    disabled
                  >
                    <template #addonAfter>{{ newDrugInfo.unit?.name || 'g' }}</template>
                  </InputNumber>
                  ,
                  <span>
                    <Select
                      v-model:value="newDrugInfo.way_id"
                      placeholder="用法"
                      @blur="updateChineseNumber"
                      @keydown="selectDrugByNewDrugInfo($event, true)"
                      disabled
                    >
                      <SelectOption :value="0">煎服</SelectOption>
                      <SelectOption
                        v-for="(value, index) in drugUseWay"
                        :key="index"
                        :value="value.id"
                      >
                        {{ value.name }}
                      </SelectOption>
                    </Select>
                  </span>
                  <p class="card-price">
                    ￥<span>{{
                      (
                        (newDrugInfo.price || 0) * (newDrugInfo.number || 0)
                      ).toFixed(2)
                    }}元</span>
                  </p>
                </div>
              </div>
            </Card>
          </Col>
        </Row>
      </div>
      <!-- 西（中成）药列表（type=2） -->
      <div v-else-if="activeCategory === 2" class="selected-drugs">
        <div class="drug-table">
          <div class="table-header">
            <span v-if="activeCategory !== 1">商品图片</span>
            <span>商品名称</span>
            <span>数量</span>
            <span>单价</span>
            <span>操作</span>
          </div>
          <div class="table-body">
            <div
              v-for="(drug, index) in currentDrugs"
              :key="drug.id"
              class="table-row"
            >
              <div
                v-if="activeCategory !== 1"
                style="width: 120px; margin: 0 auto"
              >
                <Image :src="drug.image"/>
              </div>
              <div>
                <p>
                  <span>药品名称：{{ drug.drug_name }}</span>
                </p>
                <!-- 西药用法显示/编辑模式 -->
                <p v-if="activeCategory !== 1 && !drug.isEditing">
                  <span>用法：{{
                      `${drug.use_type?.name}，${drug.use_frequency?.name}，${drug.use_num?.name}，每次${drug.number}${drug.unit?.name}`
                    }}</span>
                </p>
                <div v-else-if="activeCategory !== 1 && drug.isEditing" class="edit-usage-form">
                  <span>用法：</span>
                  <Select
                    :value="drug.use_type?.id"
                    :disabled="isSpecialPrescriptionCartLocked"
                    size="small"
                    style="width: 80px"
                    @change="(val) => updateDrugUsage(index, 'use_type', drugUseType.find(item => item.id === val))"
                  >
                    <SelectOption v-for="item in drugUseType" :key="item.id" :value="item.id">
                      {{ item.name }}
                    </SelectOption>
                  </Select>
                  <Select
                    :value="drug.use_frequency?.id"
                    :disabled="isSpecialPrescriptionCartLocked"
                    size="small"
                    style="width: 100px; margin-left: 4px"
                    @change="(val) => updateDrugUsage(index, 'use_frequency', drugUseFrequency.find(item => item.id === val))"
                  >
                    <SelectOption v-for="item in drugUseFrequency" :key="item.id" :value="item.id">
                      {{ item.name }}
                    </SelectOption>
                  </Select>
                  <Select
                    :value="drug.use_num?.id"
                    :disabled="isSpecialPrescriptionCartLocked"
                    size="small"
                    style="width: 80px; margin-left: 4px"
                    @change="(val) => updateDrugUsage(index, 'use_num', drugTime.find(item => item.id === val))"
                  >
                    <SelectOption v-for="item in drugTime" :key="item.id" :value="item.id">
                      {{ item.name }}
                    </SelectOption>
                  </Select>
                  <span style="margin-left: 4px">每次</span>
                  <InputNumber
                    v-model:value="drug.number"
                    :disabled="isSpecialPrescriptionCartLocked"
                    :min="1"
                    size="small"
                    style="width: 60px; margin-left: 4px"
                  />
                  <Select
                    :value="drug.unit?.id"
                    :disabled="isSpecialPrescriptionCartLocked"
                    size="small"
                    style="width: 60px; margin-left: 4px"
                    @change="(val) => updateDrugUsage(index, 'unit', drugUnit.find(item => item.id === val))"
                  >
                    <SelectOption v-for="item in drugUnit" :key="item.id" :value="item.id">
                      {{ item.name }}
                    </SelectOption>
                  </Select>
                </div>
              </div>
              <div>
                <div v-if="activeCategory === 1" class="quantity-control">
                  <InputNumber
                    v-model:value="drug.select_number"
                    class="w-full"
                    @blur="updateChineseNumber"
                  >
                    <template #addonAfter>{{ drug.unit?.name || 'g' }}</template>
                  </InputNumber>
                </div>
                <div v-else class="quantity-control">
                  <Button type="primary" :disabled="isSpecialPrescriptionCartLocked" @click="decrement(index)">-</Button>
                  <span style="margin: 0 20px">{{ drug.select_number }}</span>
                  <Button type="primary" :disabled="isSpecialPrescriptionCartLocked" @click="increment(index)">+</Button>
                </div>
              </div>
              <span>{{ drug.price }}</span>
              <div>
                <Button
                  v-if="activeCategory !== 1 && !drug.isEditing && !isSpecialPrescriptionCartLocked"
                  type="link"
                  @click="toggleEditDrug(index)"
                >编辑</Button>
                <Button
                  v-if="activeCategory !== 1 && drug.isEditing"
                  type="link"
                  @click="saveEditDrug(index)"
                >保存</Button>
                <Button v-if="!isSpecialPrescriptionCartLocked" type="link" @click="removeDrug(index)">删除</Button>
                <Button
                  v-if="drug.instruction !== ''"
                  type="link"
                  @click="setVisible(true, drug.instruction)"
                >
                  查看说明书
                </Button>
              </div>
            </div>
          </div>
        </div>
      </div>
      <!-- 简单产品列表（type=3,5,6,7：保健食品、产品服务包、非药品、医疗器械） -->
      <div v-else-if="[3, 5, 6, 7].includes(activeCategory)" class="selected-drugs">
        <!-- 搜索组件 -->
        <div class="mb-5">
          <DrugSearchSelect
            v-if="!isSpecialPrescriptionCartLocked"
            :type="activeCategory"
            :store-id="myStoreId"
            :placeholder="`输入${categories.find(c => c.value === activeCategory)?.label || '商品'}名称搜索`"
            @select="handleSimpleProductSelect"
          />
        </div>
        <!-- 已选商品列表（表格形式，与西药一致） -->
        <div class="drug-table">
          <div class="table-header">
            <span>商品图片</span>
            <span>商品名称</span>
            <span>数量</span>
            <span>单价</span>
            <span>操作</span>
          </div>
          <div class="table-body">
            <div
              v-for="(drug, index) in currentDrugs"
              :key="drug.id"
              class="table-row"
            >
              <div style="width: 120px; margin: 0 auto">
                <Image :src="drug.image"/>
              </div>
              <div>
                <p>
                  <span>药品名称：{{ drug.drug_name }}</span>
                </p>
              </div>
              <div>
                <div class="quantity-control">
                  <Button type="primary" :disabled="isSpecialPrescriptionCartLocked" @click="decrement(index)">-</Button>
                  <span style="margin: 0 20px">{{ drug.select_number }}</span>
                  <Button type="primary" :disabled="isSpecialPrescriptionCartLocked" @click="increment(index)">+</Button>
                </div>
              </div>
              <span>{{ drug.price }}</span>
              <div>
                <Button v-if="!isSpecialPrescriptionCartLocked" type="link" @click="removeDrug(index)">删除</Button>
                <Button
                  v-if="drug.instruction !== ''"
                  type="link"
                  @click="setVisible(true, drug.instruction)"
                >
                  查看说明书
                </Button>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- 诊断和医嘱 -->
      <div class="diagnosis-area">
        <ChineseMedicineConfig
          v-if="activeCategory === 1"
          :rule-type="ruleType"
          :package-method-id="packageMethodId"
          :process-rule-id="processRuleId"
          :child-process-rule-id="childProcessRuleId"
          :process-rule-note-id="processRuleNoteId"
          :dosage="dosage"
          :day-dosage="dayDosage"
          :process-rule-list="processRuleList"
          :child-process-rule-list="childProcessRuleList"
          :process-rule-note-list="processRuleNoteList"
          :disabled="isSpecialPrescriptionCartLocked"
          class="mb-5 p-3"
          @change="handleChineseConfigChange"
        />
        <div class="mb-2">
          <div class="mr-field-head mb-1">
            <span class="mr-field-label font-medium">诊断</span>
            <div class="mr-field-search">
              <EntryKeywordBubble
                source="diagnosis"
                placeholder="诊断关键字"
                compact
                @select="(item) => onPickDiagnosis(item.content || item.title)"
              />
            </div>
          </div>
          <Textarea
            v-model:value="diagnosis"
            placeholder="输入诊断结果..."
          />
          <CommonDxOrderChips
            source="diagnosis"
            @select="onPickDiagnosis"
          />
        </div>
        <div class="mb-2">
          <div class="mr-field-head mb-1">
            <span class="mr-field-label font-medium">医嘱</span>
            <div class="mr-field-search">
              <EntryKeywordBubble
                source="doctor_order"
                placeholder="医嘱关键字"
                compact
                @select="(item) => onPickDoctorOrder(item.content || item.title)"
              />
            </div>
          </div>
          <Textarea
            v-model:value="medicalAdvice"
            placeholder="输入医嘱..."
          />
          <CommonDxOrderChips
            source="doctor_order"
            @select="onPickDoctorOrder"
          />
        </div>
        诊疗费用：
        <InputNumber
          v-model:value="treatmentPrice"
          placeholder="请输入诊疗价格"
        >
          <template #addonAfter> /元</template>
        </InputNumber>
      </div>

      <!-- 费用总计 -->
      <div class="price-box">
        <div class="total-cost">加工费：¥{{ formatPriceDisplay(processingFee) }}</div>
        <div class="total-cost">
          商品价格：
          <Button
            v-if="priceAdjustEnabled && currentDrugs.length && !isSpecialPrescriptionCartLocked"
            type="link"
            class="!p-0"
            @click="openOrderPriceAdjust"
          >
            ¥{{ formatPriceDisplay(totalProductCost) }}
          </Button>
          <template v-else>¥{{ formatPriceDisplay(totalProductCost) }}</template>
          <span
            v-if="chineseGrossMarginPercent !== null"
            class="ml-3 text-orange-600"
          >
            毛利率 {{ chineseGrossMarginPercent }}%
          </span>
        </div>
        <div class="total-cost">总计：¥{{ formatPriceDisplay(totalCost) }}</div>

        <div v-if="priceAdjustEnabled && currentDrugs.length" class="mt-2 text-sm text-gray-600">
          当前浮动：{{ priceDiscountLabel || '无' }}
          <Button v-if="priceDiscount !== 100" type="link" size="small" @click="clearCartPriceDiscount">
            清除浮动
          </Button>
        </div>

        <Button
          v-if="activeCategory === 1"
          class="mt-5 w-full"
          style="display: block"
          type="primary"
          @click="checkChineseMedicineConflict"
        >
          发送处方
        </Button>
        <Button
          v-else
          class="mt-5 w-full"
          style="display: block"
          type="primary"
          @click="sendPrescription"
        >
          发送处方
        </Button>
        <Button
          v-if="canUseCommonPrescription && currentDrugs.length"
          type="link"
          class="mt-2 w-full"
          @click="openSaveCommonPrescriptionModal"
        >
          保存为常用方
        </Button>
      </div>
      </div>
      </div>

      <!-- VIP 开通才挂载；Tab 用 v-show 保活，避免处方态 AI 出方 getPayload 拿不到病历 -->
      <div
        v-if="canUseMedicalRecord"
        v-show="rxMrTab === 'mr'"
        class="medical-record-wrap"
      >
        <MedicalRecordPanel
          ref="medicalRecordPanelRef"
          v-model:diagnosis="diagnosis"
          v-model:medical-advice="medicalAdvice"
          :register-id="doctorReceptionRegisterId"
          :store-id="Number(myStoreId || 0)"
          :user-patient-id="Number(activePatient?.id || 0)"
          :patient-sex="Number(activePatient?.sex || 0)"
          :patient-age="Number(activePatient?.age || 0)"
          :patient-name="String(activePatient?.name || '')"
          :store-vip="receptionVip"
          :show-toolbar="false"
        />
      </div>
      </div>
      <!-- /rx-workspace-scroll -->
      </div>
      <!-- /rx-workspace -->
      </Spin>
    </Page>
    <!-- 处方发送成功页：摘要与代付入口都在面板上，不自动打开处方记录抽屉 -->
    <Page v-else-if="tabType === 3" class="prescription-panel">
      <PatientBriefBar
        :register="patientInfo"
        :patient="activePatient"
        :category="category"
        :store-name="currentStoreName"
        :is-online="false"
      />
      <!-- 成功页布局对齐 C 端付款成功页（shop/paied.vue）：
           白色圆角卡居中大图标 + 胶囊小按钮，明细行复用 C 端收银台（record-pay.vue）的 label/value 形态 -->
      <div class="rx-sent-wrap">
        <!-- 卡 1：成功卡（大图标 + 标题 + 描边胶囊小按钮） -->
        <div class="rx-sent-card rx-sent-hero">
          <CheckCircleFilled class="rx-sent-icon" />
          <h3 class="rx-sent-title">处方已发送</h3>
          <p class="rx-sent-sub">已推送到患者微信 · 支付完成后门店按方发药</p>
          <div class="rx-sent-pills">
            <Button shape="round" size="small" @click="openPatientRxHistoryDrawer">处方记录</Button>
            <Button shape="round" size="small" danger @click="endOfDiagnosis">结束诊断</Button>
          </div>
        </div>
        <!-- 卡 2：订单明细（label 加粗深色 / 值灰色，合计行大号金额） -->
        <div class="rx-sent-card rx-sent-detail">
          <div class="rx-sent-row">
            <span>订单号</span>
            <b>{{ sentPrescriptionInfo?.order_no || '—' }}</b>
          </div>
          <div class="rx-sent-row">
            <span>患者</span>
            <b>{{ sentPrescriptionInfo?.patient_name || '—' }}</b>
          </div>
          <div v-if="sentPrescriptionInfo?.diagnosis" class="rx-sent-row">
            <span>诊断</span>
            <b>{{ sentPrescriptionInfo.diagnosis }}</b>
          </div>
          <div class="rx-sent-row">
            <span>订单状态</span>
            <Tag color="orange" class="rx-sent-tag">待患者支付</Tag>
          </div>
          <div class="rx-sent-total">
            <span>总金额</span>
            <span class="rx-sent-total-val">合计: <b>¥{{ sentPrescriptionInfo?.total_pay_price || '0.00' }}</b></span>
          </div>
        </div>
        <!-- 底部操作：胶囊主按钮（代付收款）+ 描边胶囊次按钮（继续开方），对齐 C 端底部通栏确认钮 -->
        <div class="rx-sent-ops">
          <!-- 代付入口：患者不便操作手机时，医生代其发起收款（复用代付码弹窗） -->
          <Button
            v-if="sentPrescriptionInfo?.order_id"
            type="primary"
            shape="round"
            size="large"
            class="rx-sent-main"
            @click="openProxyPayQrcode(Number(sentPrescriptionInfo.order_id))"
          >
            <QrcodeOutlined />
            代付收款
          </Button>
          <Button shape="round" size="large" class="rx-sent-next" @click="tabType = 2">继续开方</Button>
        </div>
      </div>
    </Page>
    <div v-else-if="tabType === 0" class="prescription-panel">
      <Empty/>
    </div>
    </div>
    <!-- /reception-main -->
    <PatientInfoDrawerComp />
    <PatientMrDrawerComp />
    <PatientRxHistoryDrawerComp />
    <WesternDrugModal/>
    <SimpleProductModalComponent/>
    <PrescriptionDetailModal/>
    <!-- 常用方选择弹窗 -->
    <CommonPrescriptionModals/>
    <GoldenFormulaModals @import="handleImportGoldenFormula" />
    <AiPrescriptionDrawer
      ref="aiPrescriptionDrawerRef"
      @import="handleImportAiPrescription"
      @search-drug="handleAiSearchUnmatchedDrug"
      @sync-medical-record="handleSyncAiMedicalRecord"
    />
    <!-- 确认添加药品弹窗 -->
    <ConfirmModalComponent />
    <PriceAdjustDrawer />
    <AntModal title="二次签名" v-model:open="doctorSecondSignModal" @ok="doctorSecondSignModalOk">
      <div class="doctor-second-sign-title">有毒：</div>
      <p v-for="item in checkData.message.poisonous || []">【{{ item }}】</p>
      <div class="doctor-second-sign-title">十八反：</div>
      <p v-for="item in checkData.message.opposition || []">【{{ item }}】</p>
      <div class="doctor-second-sign-title">十九畏：</div>
      <p v-for="item in checkData.message.conflict || []">【{{ item }}】</p>
      <p class="mt-5" style="color: red;">如需继续开方需要二次签名，确认要二次签名吗？</p>
    </AntModal>

    <!-- 保存常用方确认模态框 -->
    <AntModal
      v-model:open="showSaveCommonPrescriptionModal"
      title="保存为常用方"
      :confirm-loading="isSavingCommonPrescription"
      @ok="saveAsCommonPrescription"
      @cancel="cancelSaveCommonPrescription"
    >
      <div class="py-4">
        <p class="mb-4 text-gray-600">
          将当前处方（{{ currentDrugs.length }}种药品）保存为常用方模板
        </p>
        <div class="flex items-center">
          <span class="mr-2 whitespace-nowrap">常用方名称：</span>
          <Input
            v-model:value="commonPrescriptionName"
            placeholder="请输入常用方名称"
            :maxlength="50"
            allow-clear
          />
        </div>
        <p class="mt-2 text-xs text-gray-400">
          类型：{{ activeCategory === 1 ? '中药' : '西药（中成药）' }}
        </p>
      </div>
    </AntModal>
  </div>
</template>

<style scoped>
/* 覆盖antd */
:global(.ant-select-item-option-active)  {
  background-color: rgba(55, 71, 162, 0.71) !important;
  color: white !important;
}
.doctor-second-sign-title {
  font-size: 16px;
  margin: 10px 0;
  font-weight: bold;
  border-left: 5px solid rgb(55, 71, 162);
  padding-left: 10px;
}
.card-index {
  font-size: 20px;
  font-weight: bold;
  position: absolute;
  left: 10px;
  top: 0;
}
/* 中药卡片：药名气泡锁宽，与克数/用法保持同一行 */
:deep(.chinese-drug-name-bubble) {
  width: 100px !important;
  min-width: 88px !important;
  max-width: 110px !important;
  flex: 0 0 100px !important;
  vertical-align: middle;
}

.card-price {
  position: absolute;
  bottom: 10px;
  right: 8px;
  color: red;
}

.card-delete {
  position: absolute;
  top: 3px;
  right: 0;
}

.reception-layout {
  display: flex;
  /* 固定视口高度，保证右侧开方区内部可「顶栏固定 + 内容滚动」 */
  height: calc(100vh - 100px);
  min-height: 560px;
  width: 100%;
  align-items: stretch;
  overflow: hidden;
}
.patient-sidebar {
  flex-shrink: 0;
  width: 300px;
  overflow: hidden;
  border-right: 1px solid #e4e7ed;
  transition: width 0.28s ease;
  display: flex;
  flex-direction: column;
  background: hsl(var(--background));
  z-index: 20;
}
.reception-layout.is-left-collapsed .patient-sidebar {
  width: 44px;
}
.patient-sidebar__collapsed {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 12px 0 16px;
  min-height: 0;
  cursor: pointer;
  user-select: none;
  background: hsl(var(--muted) / 0.55);
  border-right: 1px solid hsl(var(--border));
}
.patient-sidebar__collapsed-icon {
  font-size: 16px;
  color: hsl(var(--muted-foreground));
}
.patient-sidebar__toggle {
  flex-shrink: 0;
  padding: 8px;
  display: flex;
  justify-content: flex-end;
}
.reception-layout.is-left-collapsed .patient-sidebar__toggle {
  justify-content: center;
  padding: 8px 4px;
}
.patient-sidebar__toggle-btn {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.patient-sidebar__toggle-text {
  margin-left: 2px;
}
.patient-panel {
  width: 300px;
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  opacity: 1;
  transition: opacity 0.2s ease;
  padding: 0 8px 12px;
}
.reception-layout.is-left-collapsed .patient-panel {
  opacity: 0;
  pointer-events: none;
}
.dark .patient-sidebar {
  border-right: 1px solid #333;
}
.reception-main {
  flex: 1;
  min-width: 0;
  min-height: 0;
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.rx-back-fab {
  position: absolute;
  top: 12px;
  right: 16px;
  z-index: 30;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
}
.prescription-panel--rx .prescription-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.container-box {
  min-height: 90vh;
}
.container-box-grid {
  min-height: 90vh;
  display: grid;
  grid-template-columns: 300px 1fr;
}

.dark .patient-panel {
  border-right: none;
}

.patient-card {
  padding: 1rem;
  border-bottom: 1px solid #eee;
  cursor: pointer;
  transition: all 0.3s;
}

.dark .patient-card {
  border-bottom: 1px solid #333;
}

.patient-card.active {
  border-left: 4px solid #455cda;
  background-color: rgba(69, 92, 218, 0.1);
}

.status {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 4px;
  font-size: 0.8em;
}

.status.待支付 {
  background: #f4f4f5;
  color: #909399;
}

.status.待接诊 {
  background: #fef0f0;
  color: #f56c6c;
}

.status.接诊中 {
  background: #f0f9eb;
  color: #67c23a;
}

.status.已结束 {
  background: #f4f4f5;
  color: #909399;
}

.status.已取消 {
  background: #fef0f0;
  color: #f56c6c;
}

.status.待评价 {
  background: #f4f4f5;
  color: #909399;
}

.status.已评价 {
  background: #f4f4f5;
  color: #909399;
}

.status.已拒诊 {
  background: #f4f4f5;
  color: #909399;
}

.dark .status.待接诊,
.dark .status.已接诊 {
  background: #333;
}

.prescription-panel {
  padding: 1rem;
  /* 轻量接诊面板（待接诊/空态）在锁高布局里自身滚动：
     健康信息、特殊处方导入卡、转方卡叠加后内容会超一屏，父级 overflow:hidden 会把超出部分裁掉 */
  min-height: 0;
  overflow-y: auto;
}
/* 开方工作台：占满右侧主区，内部再拆「固定顶栏 / 可滚动内容」 */
.prescription-panel--rx {
  flex: 1;
  min-height: 0;
  height: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  /* 内边距交给内部 content，避免双层 padding 挤掉高度 */
  padding: 0 !important;
}
/* 处方发送成功页：视觉对齐 C 端付款成功页（浅灰蓝底 + 白色圆角卡 + 胶囊按钮），
   颜色走主题变量保证暗色可用，主色用 --primary（与 C 端品牌蓝 #4175EE 同族） */
.rx-sent-wrap {
  max-width: 480px;
  margin: 20px auto 0;
  padding: 14px 14px 22px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  border-radius: 14px;
  /* 对应 C 端页面底色 #F8FAFC：用 muted 低透明度自动适配暗色 */
  background: hsl(var(--muted) / 0.45);
}
.rx-sent-card {
  border-radius: 10px;
  background: hsl(var(--card, var(--background)));
  border: 1px solid hsl(var(--border) / 0.55);
  box-shadow: 0 1px 6px rgb(15 23 42 / 4%);
}
/* 成功卡：C 端 paied.vue 头卡形态（大图标居中 + 加粗标题 + 描边胶囊小按钮） */
.rx-sent-hero {
  padding: 28px 20px 20px;
  text-align: center;
}
.rx-sent-icon {
  font-size: 52px;
  color: hsl(var(--primary));
  animation: rx-sent-pop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes rx-sent-pop {
  0% {
    transform: scale(0.4);
    opacity: 0;
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}
.rx-sent-title {
  margin: 14px 0 4px;
  font-size: 17px;
  font-weight: 700;
  color: hsl(var(--foreground));
}
.rx-sent-sub {
  margin: 0;
  font-size: 12.5px;
  color: hsl(var(--muted-foreground));
}
.rx-sent-pills {
  margin-top: 18px;
  display: flex;
  justify-content: center;
  gap: 10px;
}
/* 明细卡：C 端 record-pay.vue 的 good_ 行形态（label 加粗深色 / 值常规灰色） */
.rx-sent-detail {
  padding: 6px 18px 14px;
}
.rx-sent-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 42px;
}
.rx-sent-row > span {
  flex-shrink: 0;
  font-size: 13px;
  font-weight: 600;
  color: hsl(var(--foreground));
}
.rx-sent-row > b {
  font-weight: 400;
  font-size: 13px;
  color: hsl(var(--muted-foreground));
  text-align: right;
  word-break: break-all;
}
.rx-sent-tag {
  margin-inline-end: 0;
}
/* 合计行：C 端「合计:」小字 + 大号金额 */
.rx-sent-total {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-top: 12px;
  margin-top: 4px;
  border-top: 1px solid hsl(var(--border) / 0.55);
}
.rx-sent-total > span {
  font-size: 13px;
  font-weight: 600;
  color: hsl(var(--foreground));
}
.rx-sent-total-val {
  font-size: 12px;
  color: hsl(var(--muted-foreground));
}
.rx-sent-total-val b {
  margin-left: 4px;
  font-size: 19px;
  font-weight: 600;
  color: hsl(var(--foreground));
}
/* 底部操作：主按钮胶囊撑满（对齐 C 端底部通栏「确认」钮），次按钮等宽排布 */
.rx-sent-ops {
  display: flex;
  gap: 10px;
  margin-top: 2px;
}
.rx-sent-main {
  flex: 1.6;
}
.rx-sent-next {
  flex: 1;
}
/* Page 根下的内容区：未开 autoContentHeight 时 class 是 flex-1（开了才是 h-full），
   两种都要命中，否则「固定顶栏 + 内容滚动」的高度链路断裂，长处方整页无法滚动 */
.prescription-panel--rx :deep(> .h-full),
.prescription-panel--rx :deep(> .flex-1) {
  flex: 1;
  min-height: 0;
  height: 100% !important;
  display: flex;
  flex-direction: column;
  overflow: hidden !important;
  padding: 12px 16px !important;
}
.prescription-panel--rx :deep(.ant-spin-nested-loading),
.prescription-panel--rx :deep(.ant-spin-container) {
  flex: 1;
  height: 100%;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.rx-workspace {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  height: 100%;
  overflow: hidden;
}
.rx-workspace-sticky {
  flex-shrink: 0;
  z-index: 12;
  background: hsl(var(--background));
  padding-bottom: 4px;
  border-bottom: 1px solid hsl(var(--border) / 0.6);
}
/* 二级处方类型 Tab：仅作切换导航，内容仍由下方业务区渲染 */
.rx-secondary-tabs :deep(.ant-tabs-nav) {
  margin-bottom: 0;
}
.rx-secondary-tabs :deep(.ant-tabs-content-holder) {
  display: none;
}
.rx-secondary-tab-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.rx-workspace-scroll {
  flex: 1;
  min-height: 0;
  overflow-x: hidden;
  overflow-y: auto;
  padding-top: 8px;
  padding-bottom: 16px;
}

.drug-categories {
  display: flex;
  gap: 1rem;
  margin: 1rem 0;
  overflow-x: auto;
  flex-wrap: nowrap;
  padding-bottom: 4px;
}

.drug-categories button {
  padding: 8px 16px;
  border: 1px solid #ddd;
  border-radius: 10px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  white-space: nowrap;
}

.dark .drug-categories button {
  border: 1px solid #333;
}

.tab-type-icon {
  width: 16px;
  height: 16px;
  object-fit: contain;
}

.tab-type-badge {
  font-size: 11px;
  color: #e6a23c;
  background: #fdf6ec;
  padding: 0 6px;
  border-radius: 4px;
  line-height: 1.4;
}

.rx-swipe-panel {
  touch-action: pan-y;
}

.drug-categories button.active {
  color: #fff;
  border-color: transparent;
  animation: pulse 0.5s /*infinite*/;
  animation-fill-mode: forwards;
}

@keyframes pulse {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.1);
  }
  100% {
    background: #455cda;
    transform: scale(1);
  }
}

.drug-item {
  display: flex;
  justify-content: space-between;
  padding: 12px;
  margin: 8px 0;
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.2s;
}

.drug-item:hover {
  transform: translateX(4px);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.selected-drugs {
  margin: 1rem 0;
  border: 1px solid #eee;
  border-radius: 8px;
}

.dark .selected-drugs {
  border: 1px solid #333;
}

.table-body {
  max-height: 30vh;
  overflow-y: auto;
}

.table-header {
  display: grid;
  grid-template-columns: 0.5fr 1fr 1fr 1fr 1fr;
  padding: 12px;
  font-weight: bold;
  text-align: center;
  background-color: #fafafa;
}

.dark .table-header {
  background-color: #262626;
}

.table-row {
  display: grid;
  grid-template-columns: 0.5fr 1fr 1fr 1fr 1fr;
  padding: 12px;
  border-bottom: 1px solid #eee;
  text-align: center;
  height: auto;
  align-items: center;
}

.dark .table-row {
  border-bottom: 1px solid #333;
}

.send-btn {
  cursor: pointer;
  margin-right: 10px;
  float: right;
}

.mr-field-head {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 12px;
  align-items: center;
}
.mr-field-label {
  flex-shrink: 0;
  line-height: 24px;
}
.mr-field-search {
  min-width: 0;
  flex: 1 1 180px;
  max-width: 280px;
}
.rx-tab-extra-actions {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 0 2px;
  align-items: center;
}
.rx-tab-extra-actions :deep(.ant-btn) {
  padding-inline: 6px;
  height: 28px;
}
.rx-primary-tabs :deep(.ant-tabs-nav) {
  margin-bottom: 8px;
}

.diagnosis-area textarea {
  width: 100%;
  height: 100px;
  padding: 8px;
  margin: 8px 0;
  border: 1px solid #ddd;
  border-radius: 4px;
}

.dark .diagnosis-area textarea {
  border: 1px solid #333;
}

.price-box {
  position: fixed;
  right: 10px;
  bottom: 62px;
}

.total-cost {
  text-align: right;
  font-size: 1.2em;
  font-weight: bold;
  color: #f56c6c;
  margin-top: 1rem;
}

.prescription-content {
  margin-top: 3%;
}

.time-line-item-created {
  color: #909399;
  font-size: 0.8em;
}

/* 简单产品列表样式 */
.simple-product-list {
  margin: 1rem 0;
}

.selected-products-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 16px;
  margin-top: 16px;
}

.product-card {
  border: 1px solid #e4e7ed;
  border-radius: 8px;
}

.dark .product-card {
  border-color: #333;
}

.product-card-content {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.product-image {
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  margin-bottom: 8px;
}

.product-image-placeholder {
  width: 120px;
  height: 120px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #f5f5f5;
  border-radius: 6px;
  color: #999;
  font-size: 12px;
}

.dark .product-image-placeholder {
  background: #374151;
  color: #6b7280;
}

.product-info {
  flex: 1;
}

.product-name {
  font-size: 16px;
  font-weight: 500;
  margin-bottom: 8px;
  color: #333;
}

.dark .product-name {
  color: #f3f4f6;
}

.product-price {
  font-size: 14px;
  color: #666;
  margin-bottom: 12px;
}

.dark .product-price {
  color: #9ca3af;
}

.product-quantity {
  display: flex;
  align-items: center;
  margin-bottom: 12px;
}

.product-total {
  font-size: 16px;
  font-weight: 600;
  color: #ff4d4f;
}

.product-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding-top: 8px;
  border-top: 1px solid #e4e7ed;
}

.dark .product-actions {
  border-top-color: #333;
}
</style>
