<template>
    <!--
        处方业务订单详情抽屉（共享组件）
        使用方：
        1. consumer/prescription/order_list.vue —— 完整版（header 插槽注入审核/发货等操作）
        2. tcm/diagnosis/components/PatientOrderList.vue —— readonly 受限版
        注意：
        - 详情展示的任何字段/区块改动都必须改这里，不要回到页面里复制模板。
        - readonly 版是「选择性受限展示」：流程步骤条、顶部告警、挂号关联、内部成本、
          药材明细、收款「方式」列、京东接口更新等仅完整版展示（v-if="!readonly" 门控）；
          金额概览（含退款金额/需代收）、用量与服用方式主方辅方等基础信息两版共享。
    -->
    <el-drawer
        v-model="detailVisible"
        class="po-detail-drawer"
        size="80%"
        destroy-on-close
        :close-on-click-modal="false"
        :append-to-body="appendToBody"
    >
        <template #header>
            <div class="po-detail-drawer-head flex items-center justify-between">
                <div class="flex items-center">
                    <span class="po-detail-drawer-title text-gray-800 font-semibold text-lg">业务订单详情</span>
                    <el-tag v-if="detailData?.order_no" type="primary" effect="plain" round class="ml-3">{{ detailData.order_no }}</el-tag>
                    <el-tag
                        v-if="detailData?.gancao_reciperl_order_no"
                        type="success"
                        effect="plain"
                        round
                        class="ml-2"
                    >甘草 {{ detailData.gancao_reciperl_order_no }}</el-tag>
                    <el-tag
                        v-if="detailData?.ej_pharmacy_order_no"
                        type="warning"
                        effect="plain"
                        round
                        class="ml-2"
                    >洛阳 {{ detailData.ej_pharmacy_order_no }}</el-tag>
                    <!-- 完整版：发货类型切换等 -->
                    <slot v-if="detailData" name="header-extra" :detail="detailData" />
                </div>
                <div v-if="detailData" class="flex items-center gap-2 mr-6">
                    <!-- 完整版：处方审核 / 支付审核 / 发货 / 退款等操作按钮 -->
                    <slot name="header-actions" :detail="detailData" />
                </div>
            </div>
        </template>
        <el-skeleton v-if="detailLoading" :rows="12" animated class="px-6 py-4" />
        <div v-else-if="detailData" class="po-detail-body px-6 pb-6 h-full overflow-y-auto">

            <!-- 收货手机与处方手机不一致告警（仅完整版） -->
            <el-alert
                v-if="!readonly && detailRecipientRxPhoneMismatch"
                type="error"
                :closable="false"
                show-icon
                class="mb-4 !items-start"
                title="业务订单收货手机与处方登记手机不一致"
            >
                <template #default>
                    <div class="text-sm leading-relaxed">
                        <div>
                            处方手机：
                            <span class="font-mono font-semibold text-red-700">{{ detailPrescriptionPhoneDisplay }}</span>
                        </div>
                        <div>
                            订单收货手机：
                            <span class="font-mono font-semibold text-red-700">{{ detailOrderPhoneDisplay }}</span>
                        </div>
                        <div class="text-gray-600 mt-1">请核对是否代收货或录入错误，避免物流与回访联系错人。</div>
                    </div>
                </template>
            </el-alert>

            <!-- 物流轨迹含拒收/退回等：抽屉内强提示（仅完整版） -->
            <el-alert
                v-if="!readonly && detailLogisticsUrgent.show && String(detailData?.tracking_number || '').trim()"
                type="error"
                effect="dark"
                :closable="false"
                show-icon
                class="mb-4 !items-start ring-2 ring-red-600/90 shadow-lg"
                title="物流异常：轨迹中出现拒收 / 退回等字样，请优先跟进处理"
            >
                <template #default>
                    <div class="text-sm leading-relaxed space-y-1.5">
                        <div v-if="detailLogisticsUrgent.keywords.length" class="flex flex-wrap gap-1.5 items-center">
                            <span class="text-red-100 text-xs">命中关键词：</span>
                            <el-tag
                                v-for="k in detailLogisticsUrgent.keywords"
                                :key="k"
                                type="danger"
                                effect="plain"
                                size="small"
                                class="!border-white/40 !text-white"
                            >
                                {{ k }}
                            </el-tag>
                        </div>
                        <ul v-if="detailLogisticsUrgent.lines.length" class="list-disc pl-5 space-y-1 text-red-50">
                            <li v-for="(line, idx) in detailLogisticsUrgent.lines" :key="idx">{{ line }}</li>
                        </ul>
                        <div class="text-xs text-red-100/90 pt-1 border-t border-white/15">
                            请核实是否需改址重发、拦截退件或协调患者签收，并在备注中记录处理结果。
                        </div>
                    </div>
                </template>
            </el-alert>

            <!-- 审核与履约可视化步骤条（仅完整版） -->
            <div v-if="!readonly" class="bg-gray-50/80 border border-gray-100 rounded-lg p-5 mb-5 shadow-sm">
                <el-steps :active="workflowActiveStep" align-center finish-status="success">
                    <el-step title="业务订单创建" :description="formatTime(detailData.create_time)" />
                    <el-step title="处方单双审" :status="workflowRxStatus">
                        <template #description>
                            <span v-if="workflowRxStatus === 'error'" class="text-red-500 font-medium">处方被驳回</span>
                            <span v-else-if="workflowRxStatus === 'wait'">等待审核</span>
                            <span v-else-if="workflowRxStatus === 'success'" class="text-green-600">双审通过</span>
                            <span v-else class="text-gray-400">进行中</span>
                        </template>
                    </el-step>
                    <el-step title="支付单审核" :status="workflowPayStatus">
                        <template #description>
                            <span v-if="workflowPayStatus === 'error'" class="text-red-500 font-medium">支付审核驳回</span>
                            <span v-else-if="workflowPayStatus === 'wait'">等待审核</span>
                            <span v-else-if="workflowPayStatus === 'success'" class="text-green-600">审核通过</span>
                            <span v-else class="text-gray-400">进行中</span>
                        </template>
                    </el-step>
                    <el-step title="发货与履约" :status="workflowFulfillStatus">
                        <template #description>
                            <span
                                v-if="workflowFulfillStatus === 'process' && Number(detailData?.fulfillment_status) === 7"
                                class="text-amber-600 font-medium"
                            >进行中</span>
                            <span v-else-if="workflowFulfillStatus === 'process'" class="text-primary font-medium">等待发货/补充单号</span>
                            <span v-else-if="workflowFulfillStatus === 'wait'">待转入履约</span>
                            <span v-else-if="workflowFulfillStatus === 'success'" class="text-green-600">
                                {{ fulfillmentText(detailData?.fulfillment_status) }}
                            </span>
                            <span
                                v-else-if="workflowFulfillStatus === 'error'"
                                class="text-red-500 font-medium"
                            >
                                {{ fulfillmentText(detailData?.fulfillment_status) }}
                            </span>
                        </template>
                    </el-step>
                    <el-step title="订单完成" />
                </el-steps>
            </div>

            <!-- 顶部数据概览卡片 -->
            <div class="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-5 gap-4 mb-5">
                <el-card shadow="never" class="stat-card border border-gray-100 bg-gray-50/50">
                    <div class="flex items-center justify-between mb-1">
                        <div class="stat-title text-gray-500 text-xs">总金额</div>
                        <el-button
                            v-if="!readonly && canUpdateAmount(detailData)"
                            v-perms="['tcm.prescriptionOrder/updateAmount']"
                            type="primary"
                            size="small"
                            link
                            @click="emit('update-amount')"
                        >
                            修改
                        </el-button>
                    </div>
                    <div class="stat-value text-red-500 font-bold text-xl">¥{{ detailData.amount }}</div>
                </el-card>
                <el-card shadow="never" class="stat-card border border-gray-100 bg-gray-50/50">
                    <div class="stat-title text-gray-500 text-xs mb-1">已付总额</div>
                    <div class="stat-value text-green-600 font-bold text-xl">¥{{ detailData.linked_pay_paid_total || 0 }}</div>
                </el-card>
                <el-card shadow="never" class="stat-card border border-gray-100 bg-gray-50/50">
                    <div class="stat-title text-gray-500 text-xs mb-1">退款金额</div>
                    <div
                        class="stat-value font-bold text-xl"
                        :class="Number(detailData.refund_amount) > 0 ? 'text-rose-500' : 'text-gray-400'"
                    >
                        ¥{{ formatMoney(detailData.refund_amount || 0) }}
                    </div>
                </el-card>
                <el-card shadow="never" class="stat-card border border-gray-100 bg-gray-50/50">
                    <div class="stat-title text-gray-500 text-xs mb-1">需代收</div>
                    <div
                        class="stat-value font-bold text-xl"
                        :class="detailAgencyToCollect > 0 ? 'text-amber-600' : 'text-gray-500'"
                    >
                        ¥{{ formatMoney(detailAgencyToCollect) }}
                    </div>
                </el-card>
                <el-card shadow="never" class="stat-card border border-gray-100 bg-gray-50/50">
                    <div class="stat-title text-gray-500 text-xs mb-1">已付笔数</div>
                    <div class="stat-value text-primary font-bold text-xl">{{ detailLinkedPayOrders.length }} 笔</div>
                </el-card>
            </div>

            <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
                <!-- 左侧：处方单 -->
                <el-card shadow="never" class="po-panel po-panel-rx border-gray-100 h-full relative overflow-hidden">
                    <!-- 处方审核印章 -->
                    <div v-if="detailData.prescription_audit_status === 1" class="audit-stamp stamp-pass">
                        <div class="stamp-inner">审核通过</div>
                    </div>
                    <div v-if="detailData.prescription_audit_status === 2" class="audit-stamp stamp-reject">
                        <div class="stamp-inner">已驳回</div>
                    </div>
                    <template #header>
                        <div class="flex items-center justify-between">
                            <div class="flex items-center gap-3">
                                <span class="font-medium text-[15px]">处方详情</span>
                                <span v-if="detailData.doctor_name" class="text-xs text-gray-500">
                                    开方人：<span class="text-primary font-medium">{{ detailData.doctor_name }}</span>
                                </span>
                                <el-button
                                    v-if="
                                        !readonly &&
                                        detailData.prescription_id &&
                                        detailPrescription &&
                                        !String(detailData.prescription_detail_error || '').trim()
                                    "
                                    v-perms="['tcm.prescriptionOrder/patchPrescriptionPatient']"
                                    type="default"
                                    size="small"
                                    link
                                    @click="emit('patch-rx-patient')"
                                >
                                    改患者信息
                                </el-button>
                                <el-button
                                    v-if="!readonly && detailData.prescription_id && showPrescriptionAuditFilter"
                                    type="primary"
                                    size="small"
                                    link
                                    @click="emit('view-prescription')"
                                >
                                    详细
                                </el-button>
                                <el-button
                                    v-if="!readonly && detailData.id && showPrescriptionAuditFilter"
                                    type="warning"
                                    size="small"
                                    link
                                    :loading="gancaoPreviewLoading"
                                    :icon="Search"
                                    @click="emit('test-gancao-preview')"
                                >
                                    测试价格
                                </el-button>
                            </div>
                            <span class="text-xs text-gray-400">ID: {{ detailData.prescription_id || '—' }}</span>
                        </div>
                    </template>
                    <el-alert
                        v-if="!readonly && String(detailData.prescription_detail_error || '').trim()"
                        :title="detailData.prescription_detail_error"
                        type="warning"
                        :closable="false"
                        show-icon
                        class="mb-3"
                    />
                    <template v-else-if="detailPrescription">
                        <el-descriptions :column="2" border size="small" class="po-desc bg-white">
                            <el-descriptions-item label="处方编号" :span="2">{{ detailPrescription.sn || '—' }}</el-descriptions-item>
                            <el-descriptions-item label="患者">{{ detailPrescription.patient_name || '—' }}</el-descriptions-item>
                            <el-descriptions-item label="性别 / 年龄">
                                {{ detailPrescription.gender_desc || '—' }} · {{ detailPrescription.age ?? '—' }}岁
                            </el-descriptions-item>
                            <el-descriptions-item label="手机">
                                <span
                                    :class="
                                        detailRecipientRxPhoneMismatch ? 'rx-phone-mismatch text-red-600 font-bold' : ''
                                    "
                                >
                                    {{ detailPrescription.phone || '—' }}
                                </span>
                                <el-tag
                                    v-if="detailRecipientRxPhoneMismatch"
                                    type="danger"
                                    size="small"
                                    effect="dark"
                                    class="ml-2 align-middle"
                                >
                                    与订单手机不一致
                                </el-tag>
                            </el-descriptions-item>
                            <el-descriptions-item label="处方日期">{{ detailPrescription.prescription_date || '—' }}</el-descriptions-item>
                            <el-descriptions-item label="医师">{{ detailPrescription.doctor_name || '—' }}</el-descriptions-item>
                            <el-descriptions-item label="类型">{{ detailPrescription.prescription_type || '—' }}</el-descriptions-item>
                            <el-descriptions-item label="临床诊断" :span="2">
                                {{ detailPrescription.clinical_diagnosis || '—' }}
                            </el-descriptions-item>
                            <el-descriptions-item label="剂数 / 用法" :span="2" v-if="showPrescriptionAuditFilter">
                                {{ detailData.dose_count ?? detailPrescription.dose_count ?? '—' }} {{ detailData.dose_unit || '剂' }} ·
                                {{ detailPrescription.usage_instruction || detailPrescription.usage_method || '—' }}
                            </el-descriptions-item>
                            <el-descriptions-item label="处方金额">
                                <span class="text-red-500 font-medium">¥{{ detailPrescription.amount ?? '—' }}</span>
                            </el-descriptions-item>
                            <el-descriptions-item label="消费者审核">
                                <el-tag :type="consumerRxAuditTag(detailPrescription.audit_status)" size="small">
                                    {{ consumerRxAuditText(detailPrescription.audit_status) }}
                                </el-tag>
                            </el-descriptions-item>
                            <el-descriptions-item label="用量">
                                <div class="flex flex-col gap-1 text-sm leading-relaxed">
                                    <div>
                                        <span v-if="detailHasAuxHerbs" class="text-gray-500 mr-1">主方：</span>
                                        <template v-if="detailPrescription.dosage_amount">
                                            {{ detailPrescription.dosage_amount }}{{ detailPrescription.dosage_unit || 'g' }}
                                            <template v-if="detailPrescription.prescription_type === '浓缩水丸'">
                                                · {{ Number(detailPrescription.dosage_bag_count) > 0 ? Number(detailPrescription.dosage_bag_count) : 1 }}袋
                                            </template>
                                            <span v-if="detailPrescription.prescription_type === '饮片' && detailPrescription.need_decoction !== null" class="ml-2 text-gray-500">
                                                ({{ detailPrescription.need_decoction ? '代煎' : '不代煎' }})
                                            </span>
                                        </template>
                                        <template v-else>—</template>
                                    </div>
                                    <div v-if="detailHasAuxHerbs && detailAuxUsage">
                                        <span class="text-gray-500 mr-1">辅方：</span>
                                        <template v-if="detailAuxUsage.dosage_amount != null && detailAuxUsage.dosage_amount !== 0">
                                            {{ detailAuxUsage.dosage_amount }}{{ detailPrescription.dosage_unit || 'g' }}
                                            <template v-if="detailPrescription.prescription_type === '浓缩水丸'">
                                                · {{ Number(detailAuxUsage.dosage_bag_count) > 0 ? Number(detailAuxUsage.dosage_bag_count) : 1 }}袋
                                            </template>
                                            <span v-if="detailPrescription.prescription_type === '饮片'" class="ml-2 text-gray-500">
                                                ({{ detailAuxUsage.need_decoction ? '代煎' : '不代煎' }})
                                            </span>
                                        </template>
                                        <template v-else>—</template>
                                    </div>
                                </div>
                            </el-descriptions-item>
                            <el-descriptions-item>
                                <template #label>
                                    <div class="flex items-center gap-1">
                                        <span>服用方式</span>
                                        <el-button
                                            v-if="
                                                !readonly &&
                                                detailData.prescription_id &&
                                                detailPrescription &&
                                                !String(detailData.prescription_detail_error || '').trim()
                                            "
                                            v-perms="['tcm.prescriptionOrder/patchPrescriptionUsage']"
                                            type="primary"
                                            size="small"
                                            link
                                            @click="openPatchUsageDialog"
                                        >
                                            修改
                                        </el-button>
                                    </div>
                                </template>
                                <div class="flex flex-col gap-1.5 text-sm leading-relaxed">
                                    <template v-if="detailHasAuxHerbs">
                                        <div>
                                            <span class="text-gray-500 mr-1">主方：</span>
                                            每天
                                            {{ detailPrescription.times_per_day ? detailPrescription.times_per_day + ' 次' : '— 次' }}
                                            · 处方开立
                                            {{
                                                detailPrescription.usage_days != null && detailPrescription.usage_days !== ''
                                                    ? detailPrescription.usage_days + ' 天'
                                                    : '— 天'
                                            }}
                                        </div>
                                        <div v-if="detailAuxUsage">
                                            <span class="text-gray-500 mr-1">辅方：</span>
                                            每天
                                            {{ detailAuxUsage.times_per_day ? detailAuxUsage.times_per_day + ' 次' : '— 次' }}
                                            · 处方开立
                                            {{
                                                detailAuxUsage.usage_days != null && Number(detailAuxUsage.usage_days) > 0
                                                    ? detailAuxUsage.usage_days + ' 天'
                                                    : '— 天'
                                            }}
                                        </div>
                                    </template>
                                    <template v-else>
                                        <div>
                                            <span class="text-gray-500">每天次数：</span>
                                            {{ detailPrescription.times_per_day ? detailPrescription.times_per_day + ' 次' : '—' }}
                                        </div>
                                        <div>
                                            <span class="text-gray-500">处方开立：</span>
                                            {{
                                                detailPrescription.usage_days != null && detailPrescription.usage_days !== ''
                                                    ? detailPrescription.usage_days + ' 天'
                                                    : '—'
                                            }}
                                        </div>
                                    </template>
                                    <div>
                                        <span class="text-gray-500">订单设置：</span>
                                        {{
                                            detailData.medication_days != null &&
                                            String(detailData.medication_days).trim() !== ''
                                                ? detailData.medication_days + ' 天'
                                                : '—'
                                        }}
                                    </div>
                                </div>
                            </el-descriptions-item>
                            <el-descriptions-item v-if="detailDietaryText" label="忌口" :span="2">
                                {{ detailDietaryText }}
                            </el-descriptions-item>
                            <el-descriptions-item label="状态" :span="2">
                                <el-tag :type="Number(detailPrescription.void_status) === 1 ? 'danger' : 'success'" size="small">
                                    {{ Number(detailPrescription.void_status) === 1 ? '已作废' : '正常' }}
                                </el-tag>
                            </el-descriptions-item>
                        </el-descriptions>

                        <div v-if="!readonly && detailHerbsVisible" class="mt-4">
                            <div class="text-xs font-medium text-gray-500 mb-2 px-1">药材明细</div>
                            <el-table v-if="detailRxHerbs.length" :data="detailRxHerbs" size="small" border stripe max-height="260">
                                <el-table-column type="index" label="#" width="48" align="center" />
                                <el-table-column prop="name" label="药名" min-width="120" show-overflow-tooltip />
                                <el-table-column prop="dosage" label="用量(g)" width="96" align="right" />
                            </el-table>
                            <el-empty v-else description="无处方药材明细" :image-size="64" />
                        </div>
                    </template>
                    <el-empty v-else description="无处方数据" :image-size="72" />
                </el-card>

                <!-- 右侧：未关联 + 已关联支付单 -->
                <div class="flex flex-col gap-4 h-full">
                    <!-- 未关联的收款记录 -->
                    <el-card shadow="never" class="po-panel border-gray-100">
                        <template #header>
                            <div class="flex items-center justify-between">
                                <span class="font-medium text-[15px]">未关联的收款记录</span>
                                <span class="text-xs text-gray-400">本诊单下未被占用的支付单</span>
                            </div>
                        </template>
                        <el-table
                            v-if="detailUnlinkedPayOrders.length"
                            :data="detailUnlinkedPayOrders"
                            size="small"
                            border
                            stripe
                            class="po-pay-table"
                            max-height="280"
                        >
                            <el-table-column prop="id" label="ID" width="70" />
                            <el-table-column prop="order_no" label="单号" min-width="135" show-overflow-tooltip />
                            <el-table-column label="类型" width="90">
                                <template #default="{ row }">
                                    {{ row.order_type_desc || feeTypeText(row.order_type) }}
                                </template>
                            </el-table-column>
                            <el-table-column label="金额" width="86" align="right">
                                <template #default="{ row }">
                                    <span class="text-red-500">¥{{ row.amount }}</span>
                                </template>
                            </el-table-column>
                            <el-table-column label="状态" width="100" align="center">
                                <template #default="{ row }">
                                    <el-tag :type="payOrderStatusTag(row.status)" size="small">
                                        {{ row.status_desc || orderStatusText(row.status) }}
                                    </el-tag>
                                    <el-tag v-if="!readonly && row.is_exempt === 1" type="warning" size="small" class="ml-1">豁免</el-tag>
                                </template>
                            </el-table-column>
                            <el-table-column v-if="!readonly" label="方式" min-width="120" show-overflow-tooltip>
                                <template #default="{ row }">
                                    {{ formatPayOrderSource(row) }}
                                </template>
                            </el-table-column>
                            <el-table-column prop="creator_name" label="创建人" width="80" show-overflow-tooltip />
                            <el-table-column label="创建时间" min-width="136">
                                <template #default="{ row }">
                                    {{ formatOrderTime(row.create_time) }}
                                </template>
                            </el-table-column>
                        </el-table>
                        <el-empty v-else description="无未关联的收款单" :image-size="60" />
                    </el-card>

                    <!-- 已关联的收款记录 -->
                    <el-card shadow="never" class="po-panel po-panel-pay border-gray-100 relative overflow-hidden">
                        <!-- 支付单审核印章 -->
                        <div v-if="detailData.payment_slip_audit_status === 1" class="audit-stamp stamp-pass">
                            <div class="stamp-inner">审核通过</div>
                        </div>
                        <div v-if="detailData.payment_slip_audit_status === 2" class="audit-stamp stamp-reject">
                            <div class="stamp-inner">已驳回</div>
                        </div>
                        <template #header>
                            <div class="flex items-center justify-between">
                                <div class="flex items-center gap-3">
                                    <span class="font-medium text-[15px]">关联收款记录</span>
                                    <span v-if="detailData.creator_name" class="text-xs text-gray-500">
                                        创建人：<span class="text-primary font-medium">{{ detailData.creator_name }}</span>
                                    </span>
                                </div>
                            </div>
                        </template>
                        <el-table
                            v-if="detailLinkedPayOrders.length"
                            :data="detailLinkedPayOrders"
                            size="small"
                            border
                            stripe
                            class="po-pay-table"
                            max-height="280"
                        >
                            <el-table-column prop="id" label="ID" width="70" />
                            <el-table-column prop="order_no" label="单号" min-width="135" show-overflow-tooltip />
                            <el-table-column label="类型" width="90">
                                <template #default="{ row }">
                                    {{ row.order_type_desc || feeTypeText(row.order_type) }}
                                </template>
                            </el-table-column>
                            <el-table-column label="金额" width="86" align="right">
                                <template #default="{ row }">
                                    <span class="text-red-500">¥{{ row.amount }}</span>
                                </template>
                            </el-table-column>
                            <el-table-column label="状态" width="100" align="center">
                                <template #default="{ row }">
                                    <el-tag :type="payOrderStatusTag(row.status)" size="small">
                                        {{ row.status_desc || orderStatusText(row.status) }}
                                    </el-tag>
                                    <el-tag v-if="!readonly && row.is_exempt === 1" type="warning" size="small" class="ml-1">豁免</el-tag>
                                </template>
                            </el-table-column>
                            <el-table-column v-if="!readonly" label="方式" min-width="120" show-overflow-tooltip>
                                <template #default="{ row }">
                                    {{ formatPayOrderSource(row) }}
                                </template>
                            </el-table-column>
                            <el-table-column prop="creator_name" label="创建人" width="80" show-overflow-tooltip />
                            <el-table-column label="创建时间" min-width="136">
                                <template #default="{ row }">
                                    {{ formatOrderTime(row.create_time) }}
                                </template>
                            </el-table-column>
                        </el-table>
                        <el-empty v-else description="未关联收款单" :image-size="60" />
                    </el-card>
                </div>
            </div>

            <!-- 底部：履约与收货 -->
            <el-card shadow="never" class="po-panel po-panel-biz border-gray-100 mb-4">
                <template #header>
                    <span class="font-medium text-[15px]">履约与收货信息</span>
                </template>
                <el-descriptions :column="3" border size="small" class="po-desc">
                    <el-descriptions-item label="诊单ID" :span="3">
                        <span class="font-mono">{{ detailData.diagnosis_id }}</span>
                        <el-button
                            v-if="!readonly && Number(detailData.diagnosis_id) > 0"
                            type="primary"
                            link
                            size="small"
                            class="ml-2 align-baseline"
                            @click="emit('view-patient')"
                        >
                            查看患者信息
                        </el-button>
                    </el-descriptions-item>
                    <el-descriptions-item label="创建时间" :span="1">{{ formatTime(detailData.create_time) }}</el-descriptions-item>
                    <el-descriptions-item label="业务订单创建人" :span="2">
                        <div v-if="Number(detailData.creator_id) > 0 || detailData.creator_name" class="text-[13px] space-y-1">
                            <div>
                                <span class="font-medium text-gray-900">{{ detailData.creator_name || '—' }}</span>
                                <span v-if="!readonly && Number(detailData.creator_id) > 0" class="text-gray-500 ml-2 font-mono text-xs"
                                    >ID {{ detailData.creator_id }}</span
                                >
                            </div>
                            <div v-if="detailOrderCreatorMetaLine" class="text-gray-600 text-xs leading-relaxed">
                                {{ detailOrderCreatorMetaLine }}
                            </div>
                        </div>
                        <span v-else class="text-gray-400">—</span>
                    </el-descriptions-item>
                    <el-descriptions-item label="创建人所属部门" :span="3">
                        <div v-if="detailOrderCreatorDeptBreadcrumbs.length" class="space-y-1.5">
                            <div
                                v-for="(segments, idx) in detailOrderCreatorDeptBreadcrumbs"
                                :key="idx"
                                class="min-w-0"
                            >
                                <el-breadcrumb
                                    v-if="segments.length"
                                    class="po-diagnosis-creator-dept-breadcrumb text-[13px] leading-relaxed"
                                    separator="/"
                                >
                                    <el-breadcrumb-item v-for="(name, j) in segments" :key="j">
                                        <span class="text-gray-800 break-all">{{ name }}</span>
                                    </el-breadcrumb-item>
                                </el-breadcrumb>
                            </div>
                        </div>
                        <span v-else class="text-gray-400">—</span>
                    </el-descriptions-item>
                    <el-descriptions-item label="收货人">{{ detailData.recipient_name }}</el-descriptions-item>

                    <el-descriptions-item v-if="!readonly" label="挂号关联" :span="3">
                        <template v-if="detailLinkedAppointment">
                            <div class="flex flex-wrap items-center gap-x-4 gap-y-1 text-[13px]">
                                <span
                                    >流转编号（挂号） <span class="font-mono text-primary">#{{ detailLinkedAppointment.id }}</span></span
                                >
                                <span class="text-gray-500"
                                    >时间：{{ detailLinkedAppointment.appointment_date }}
                                    {{ detailLinkedAppointment.period }}
                                    {{ detailLinkedAppointment.appointment_time }}</span
                                >
                                <el-tag size="small" type="info">{{ detailLinkedAppointment.appointment_type_desc }}</el-tag>
                                <el-tag size="small">{{ detailLinkedAppointment.status_desc }}</el-tag>
                                <span v-if="detailLinkedAppointment.doctor_name"
                                    >接诊：{{ detailLinkedAppointment.doctor_name }}</span
                                >
                                <span v-if="detailLinkedAppointmentChannelText" class="text-gray-500"
                                    >渠道：{{ detailLinkedAppointmentChannelText }}</span
                                >
                                <el-tag v-if="detailLinkedAppointmentResolvedFromTag" size="small" effect="plain">{{
                                    detailLinkedAppointmentResolvedFromTag
                                }}</el-tag>
                            </div>
                            <p v-if="String(detailLinkedAppointment.remark || '').trim()" class="text-xs text-gray-500 mt-1">
                                备注：{{ detailLinkedAppointment.remark }}
                            </p>
                        </template>
                        <span v-else class="text-gray-400">暂无挂号预约记录（未绑定或诊单下无预约）</span>
                    </el-descriptions-item>

                    <el-descriptions-item label="收货手机">
                        <span
                            :class="
                                detailRecipientRxPhoneMismatch ? 'text-red-600 font-bold font-mono' : 'font-mono'
                            "
                        >
                            {{ detailData.recipient_phone || '—' }}
                        </span>
                        <el-tag
                            v-if="detailRecipientRxPhoneMismatch"
                            type="danger"
                            size="small"
                            effect="dark"
                            class="ml-2 align-middle"
                        >
                            与处方手机不一致
                        </el-tag>
                    </el-descriptions-item>
                    <el-descriptions-item label="收货地址" :span="2">{{ detailFullAddress }}</el-descriptions-item>

                    <el-descriptions-item label="复诊">{{ detailData.is_follow_up ? '是' : '否' }}</el-descriptions-item>
                    <el-descriptions-item label="用药疗程">{{ detailData.medication_days ? detailData.medication_days + ' 天' : '—' }}</el-descriptions-item>
                    <el-descriptions-item label="上次医护">{{ detailData.prev_staff || '—' }}</el-descriptions-item>

                    <el-descriptions-item label="服务渠道">{{ detailData.service_channel || '—' }}</el-descriptions-item>
                    <el-descriptions-item label="服务套餐">{{ detailServicePackageText }}</el-descriptions-item>
                    <el-descriptions-item label="费用类别">{{ feeTypeText(detailData.fee_type) }}</el-descriptions-item>

                    <el-descriptions-item v-if="showInternalCost" label="内部成本">
                        ¥{{ detailData.internal_cost }}
                    </el-descriptions-item>
                    <el-descriptions-item label="快递单号" :span="showInternalCost ? 1 : 2">{{ detailData.tracking_number || '—' }}</el-descriptions-item>
                    <el-descriptions-item label="快递公司">
                        {{ expressCompanyLabel(detailData.express_company) }}
                    </el-descriptions-item>

                    <el-descriptions-item v-perms="['tcm.prescriptionOrder/editRemarkExtra']" label="药房备注" :span="3">{{ detailData.remark_extra || '—' }}</el-descriptions-item>
                    <el-descriptions-item label="医助备注" :span="3">{{ detailData.remark_assistant || '—' }}</el-descriptions-item>
                    <el-descriptions-item label="处方审核意见" :span="3">
                        <span class="po-audit-remark">{{ detailData.prescription_audit_remark || '—' }}</span>
                    </el-descriptions-item>
                    <el-descriptions-item label="支付审核意见" :span="3">
                        <span class="po-audit-remark">{{ detailData.payment_slip_audit_remark || '—' }}</span>
                    </el-descriptions-item>
                </el-descriptions>
            </el-card>

            <!-- 物流轨迹 -->
            <el-card
                v-if="String(detailData.tracking_number || '').trim()"
                shadow="never"
                class="po-panel po-panel-logistics"
                :class="
                    !readonly && detailLogisticsUrgent.show
                        ? '!border-2 !border-red-500 shadow-md shadow-red-500/10'
                        : 'border-gray-100'
                "
            >
                <template #header>
                    <div class="flex items-center gap-2 flex-wrap">
                        <span class="font-medium text-[15px]">物流轨迹</span>
                        <span class="text-xs text-gray-400 font-mono">{{ detailData.tracking_number }}</span>
                        <el-tag
                            v-if="!readonly && detailLogisticsUrgent.show"
                            type="danger"
                            effect="dark"
                            size="small"
                        >
                            拒收/退回 · 待处理
                        </el-tag>
                    </div>
                </template>
                <p v-if="!readonly" class="po-logistics-tip text-gray-400 text-xs mb-3 font-normal">
                    优先读库，无记录时走快递100。顺丰会校验单号+电话（快递100要求完整手机号更易通过）；默认预填订单收货手机，若仍提示验证码错误请改成与顺丰面单一致的号码。
                </p>
                <div class="flex flex-wrap items-center gap-3 mb-4">
                    <el-input
                        v-model="logisticsTracePhoneTail"
                        clearable
                        maxlength="20"
                        placeholder="收件手机（建议11位，与面单一致）"
                        class="w-[180px]"
                        @keyup.enter="fetchLogisticsTrace"
                    />
                    <el-select v-model="detailLogisticsExpress" placeholder="承运商" style="width: 140px">
                        <el-option label="自动识别" value="auto" />
                        <el-option label="顺丰速运" value="sf" />
                        <el-option label="京东快递" value="jd" />
                        <el-option label="极兔速递" value="jt" />
                    </el-select>
                    <el-button
                        v-perms="['tcm.prescriptionOrder/logisticsTrace']"
                        type="primary"
                        plain
                        size="default"
                        :loading="logisticsTraceLoading"
                        @click="fetchLogisticsTrace"
                    >
                        <template #icon><el-icon><Refresh /></el-icon></template>
                        刷新轨迹
                    </el-button>
                    <el-button
                        v-if="!readonly"
                        v-perms="['tcm.prescriptionOrder/logisticsTrace']"
                        type="warning"
                        plain
                        size="default"
                        :loading="jdLogisticsUpdating"
                        @click="updateJdLogistics"
                    >
                        <template #icon><el-icon><Van /></el-icon></template>
                        京东接口更新
                    </el-button>
                    <div v-if="!readonly" class="ml-2 flex items-center gap-4 border-l pl-4 border-gray-200">
                        <el-link :href="detailOfficialUrls.sf" target="_blank" type="primary" :underline="false" class="text-[13px]">顺丰官网</el-link>
                        <el-link :href="detailOfficialUrls.jd" target="_blank" type="primary" :underline="false" class="text-[13px]">京东物流</el-link>
                        <el-link :href="detailOfficialUrls.jt" target="_blank" type="primary" :underline="false" class="text-[13px]">极兔</el-link>
                    </div>
                </div>

                <el-alert
                    v-if="!readonly && String(logisticsTracePayload?.hint || '').trim()"
                    :title="String(logisticsTracePayload?.hint || '')"
                    type="info"
                    :closable="false"
                    class="mb-4"
                    show-icon
                />

                <div v-if="logisticsTraceLoading && !logisticsTracePayload" class="py-6 text-center text-sm text-gray-500">
                    <el-icon class="is-loading mr-1"><Loading /></el-icon>正在加载物流轨迹...
                </div>

                <div v-else-if="logisticsTracePayload" class="logistics-content bg-gray-50/50 p-4 rounded-md">
                    <div v-if="logisticsTracePayload?.state_text" class="text-sm mb-4 font-medium flex items-center gap-2">
                        <span class="text-gray-800">状态：{{ logisticsTracePayload.state_text }}</span>
                        <el-tag v-if="logisticsTracePayload?.carrier_label" size="small" type="info">{{ logisticsTracePayload.carrier_label }}</el-tag>
                        <span v-if="!readonly && logisticsTracePayload?.source" class="text-xs text-gray-400 ml-1">
                            [{{ logisticsTracePayload.source === 'database' ? '数据库缓存' : 'API拉取' }}]
                        </span>
                        <span v-if="!readonly && logisticsTracePayload?.last_query_time" class="text-xs text-gray-400">
                            更新时间：{{ logisticsTracePayload.last_query_time }}
                        </span>
                    </div>
                    <el-timeline v-if="logisticsTraceList.length" class="mt-2 pl-2">
                        <el-timeline-item
                            v-for="(t, idx) in logisticsTraceList"
                            :key="idx"
                            :type="idx === 0 ? 'primary' : 'info'"
                            :hollow="idx !== 0"
                            :timestamp="t.time"
                            placement="top"
                        >
                            <span
                                :class="[
                                    idx === 0 ? 'text-gray-800 font-medium' : 'text-gray-500',
                                    !readonly && logisticsTraceLineUrgent(t.context)
                                        ? '!text-red-700 font-semibold bg-red-50 px-1.5 py-0.5 rounded'
                                        : ''
                                ]"
                            >{{ t.context }}</span>
                        </el-timeline-item>
                    </el-timeline>
                    <el-empty v-else description="暂无轨迹节点记录" :image-size="64" />
                </div>
            </el-card>

            <!-- 操作日志 -->
            <el-card
                v-perms="['tcm.prescriptionOrder/logs']"
                shadow="never"
                class="po-panel border-gray-100 mt-4"
            >
                <template #header>
                    <div class="flex items-center justify-between gap-2">
                        <span class="font-medium text-[15px]">操作日志</span>
                        <el-button
                            v-if="canAddPrescriptionOrderLog()"
                            type="primary"
                            link
                            size="small"
                            @click="openAddLogDialog"
                        >
                            新增日志
                        </el-button>
                    </div>
                </template>
                <el-timeline v-if="detailLogs.length" class="mt-2 pl-2">
                    <el-timeline-item
                        v-for="(log, idx) in detailLogs"
                        :key="log.id"
                        :type="idx === 0 ? 'primary' : 'info'"
                        :hollow="idx !== 0"
                        :timestamp="formatTime(log.create_time)"
                        placement="top"
                    >
                        <div class="flex items-center gap-2 mb-1">
                            <span class="font-medium text-[13px]">{{ log.admin_name }}</span>
                            <el-tag size="small" type="info">{{ logActionText(log.action) }}</el-tag>
                        </div>
                        <span :class="idx === 0 ? 'text-gray-800 font-medium' : 'text-gray-500'">{{ log.summary }}</span>
                    </el-timeline-item>
                </el-timeline>
                <el-empty v-else description="暂无操作日志" :image-size="64" />
            </el-card>

            <!-- 新增操作日志 -->
            <el-dialog
                v-model="addLogVisible"
                title="新增操作日志"
                width="520px"
                :close-on-click-modal="false"
                destroy-on-close
                append-to-body
                @closed="resetAddLogForm"
            >
                <el-form ref="addLogFormRef" :model="addLogForm" :rules="addLogRules" label-width="108px">
                    <el-form-item label="日志内容" prop="summary">
                        <el-input
                            v-model="addLogForm.summary"
                            type="textarea"
                            :rows="4"
                            maxlength="500"
                            show-word-limit
                            placeholder="记录本次操作说明、沟通结果等"
                        />
                    </el-form-item>
                    <el-form-item v-if="canSetRxAuditOnAddLog" label="处方审核">
                        <el-select v-model="addLogForm.prescription_audit_status" class="w-full" clearable placeholder="不修改">
                            <el-option label="待审核" :value="0" />
                            <el-option label="已通过" :value="1" />
                            <el-option label="已驳回" :value="2" />
                        </el-select>
                        <div v-if="detailData" class="text-xs text-gray-400 mt-1">
                            当前：{{ auditStatusText(detailData.prescription_audit_status) }}
                        </div>
                    </el-form-item>
                    <el-form-item
                        v-if="canSetRxAuditOnAddLog && addLogForm.prescription_audit_status !== '' && addLogForm.prescription_audit_status !== null && addLogForm.prescription_audit_status !== undefined"
                        label="处方审核意见"
                    >
                        <el-input
                            v-model="addLogForm.prescription_audit_remark"
                            type="textarea"
                            :rows="2"
                            maxlength="500"
                            show-word-limit
                            placeholder="选填"
                        />
                    </el-form-item>
                    <el-form-item v-if="canSetPayAuditOnAddLog" label="支付单审核">
                        <el-select v-model="addLogForm.payment_slip_audit_status" class="w-full" clearable placeholder="不修改">
                            <el-option label="待审核" :value="0" />
                            <el-option label="已通过" :value="1" />
                            <el-option label="已驳回" :value="2" />
                        </el-select>
                        <div v-if="detailData" class="text-xs text-gray-400 mt-1">
                            当前：{{ auditStatusText(detailData.payment_slip_audit_status) }}
                        </div>
                    </el-form-item>
                    <el-form-item
                        v-if="canSetPayAuditOnAddLog && addLogForm.payment_slip_audit_status !== '' && addLogForm.payment_slip_audit_status !== null && addLogForm.payment_slip_audit_status !== undefined"
                        label="支付审核意见"
                    >
                        <el-input
                            v-model="addLogForm.payment_slip_audit_remark"
                            type="textarea"
                            :rows="2"
                            maxlength="500"
                            show-word-limit
                            placeholder="选填"
                        />
                    </el-form-item>
                </el-form>
                <template #footer>
                    <el-button @click="addLogVisible = false">取消</el-button>
                    <el-button type="primary" :loading="addLogSaving" @click="submitAddLog">保存</el-button>
                </template>
            </el-dialog>

            <!-- 修改服用参数：主方 / 辅方 / 订单设置 -->
            <el-dialog
                v-model="patchUsageVisible"
                title="修改服用参数"
                width="480px"
                :close-on-click-modal="false"
                destroy-on-close
                @closed="resetPatchUsageForm"
            >
                <el-form
                    ref="patchUsageFormRef"
                    :model="patchUsageForm"
                    :rules="patchUsageRules"
                    label-width="108px"
                >
                    <div v-if="detailHasAuxHerbs" class="text-xs font-medium text-gray-500 mb-3">主方</div>
                    <el-form-item label="每天次数" prop="times_per_day">
                        <el-input-number
                            v-model="patchUsageForm.times_per_day"
                            :min="1"
                            :max="6"
                            :step="1"
                            controls-position="right"
                            class="w-full"
                        />
                    </el-form-item>
                    <el-form-item label="处方开立" prop="usage_days">
                        <div class="flex items-center gap-1 w-full">
                            <el-input-number
                                v-model="patchUsageForm.usage_days"
                                :min="1"
                                :max="999"
                                :step="1"
                                controls-position="right"
                                class="flex-1 min-w-0"
                            />
                            <span class="text-gray-500 shrink-0">天</span>
                        </div>
                    </el-form-item>
                    <template v-if="detailHasAuxHerbs">
                        <div class="text-xs font-medium text-gray-500 mb-3 mt-2 pt-2 border-t border-gray-100">辅方</div>
                        <el-form-item label="每天次数" prop="aux_times_per_day">
                            <el-input-number
                                v-model="patchUsageForm.aux_times_per_day"
                                :min="1"
                                :max="6"
                                :step="1"
                                controls-position="right"
                                class="w-full"
                            />
                        </el-form-item>
                        <el-form-item label="处方开立" prop="aux_usage_days">
                            <div class="flex items-center gap-1 w-full">
                                <el-input-number
                                    v-model="patchUsageForm.aux_usage_days"
                                    :min="1"
                                    :max="999"
                                    :step="1"
                                    controls-position="right"
                                    class="flex-1 min-w-0"
                                />
                                <span class="text-gray-500 shrink-0">天</span>
                            </div>
                        </el-form-item>
                    </template>
                    <div class="text-xs font-medium text-gray-500 mb-3 mt-2 pt-2 border-t border-gray-100">订单设置</div>
                    <el-form-item label="服用天数" prop="medication_days">
                        <div class="flex items-center gap-1 w-full">
                            <el-input-number
                                v-model="patchUsageForm.medication_days"
                                :min="1"
                                :max="999"
                                :step="1"
                                controls-position="right"
                                class="flex-1 min-w-0"
                            />
                            <span class="text-gray-500 shrink-0">天</span>
                        </div>
                    </el-form-item>
                </el-form>
                <template #footer>
                    <el-button @click="patchUsageVisible = false">取消</el-button>
                    <el-button type="primary" :loading="patchUsageSaving" @click="submitPatchUsage">保存</el-button>
                </template>
            </el-dialog>
        </div>
    </el-drawer>
</template>

<script lang="ts" setup name="PrescriptionOrderDetailDrawer">
import { computed, nextTick, onMounted, reactive, ref } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'
import { Refresh, Loading, Search, Van } from '@element-plus/icons-vue'
import {
    prescriptionOrderDetail,
    prescriptionOrderLogs,
    prescriptionOrderAddLog,
    prescriptionOrderLogisticsTrace,
    prescriptionOrderLogisticsJdUpdate,
    prescriptionOrderPaidPayOrders,
    prescriptionOrderPatchPrescriptionUsage
} from '@/api/tcm'
import { getDictData } from '@/api/app'
import feedback from '@/utils/feedback'
import useUserStore from '@/stores/modules/user'
import {
    TCM_ASSISTANT_ROLE_ID,
    PRESCRIPTION_AUDIT_ROLE_IDS,
    formatTime,
    formatMoney,
    formatOrderTime,
    feeTypeText,
    fulfillmentText,
    orderStatusText,
    payOrderStatusTag,
    consumerRxAuditText,
    consumerRxAuditTag,
    expressCompanyLabel,
    logActionText,
    auditStatusText,
    formatPayOrderSource,
    normalizeBizPhone,
    recipientVsPrescriptionPhoneMismatch,
    normalizeSlipHerbs,
    normalizeSlipAuxUsageForm,
    prescriptionHasAuxFormula,
    logisticsTraceLineUrgent,
    analyzeLogisticsPayloadUrgent,
    parseLogisticsTracePayload,
    canUpdateAmount,
    formatDietaryTaboo,
    type ServicePackageOption,
    normalizeServicePackageOptions,
    formatServicePackageLabels
} from './prescription-order-utils'

const props = withDefaults(
    defineProps<{
        /** 只读模式：隐藏修改金额、改患者信息、查看处方笺、测试价格、查看患者信息等操作入口 */
        readonly?: boolean
        /** 「测试价格」按钮 loading（由父页面甘草预览流程驱动） */
        gancaoPreviewLoading?: boolean
        /** 嵌套在其他抽屉内时需要 append-to-body */
        appendToBody?: boolean
    }>(),
    {
        readonly: false,
        gancaoPreviewLoading: false,
        appendToBody: false
    }
)

defineSlots<{
    /** 抽屉头部左侧扩展（完整版的发货类型切换等） */
    'header-extra'?: (props: { detail: any }) => any
    /** 抽屉头部右侧操作按钮（审核/发货/退款等） */
    'header-actions'?: (props: { detail: any }) => any
}>()

const emit = defineEmits<{
    (e: 'update-amount'): void
    (e: 'patch-rx-patient'): void
    (e: 'view-prescription'): void
    (e: 'test-gancao-preview'): void
    (e: 'view-patient'): void
    (e: 'detail-changed'): void
}>()

const userStore = useUserStore()

/**
 * 是否展示「处方审核」相关字段：纯医助（含角色 2 且不具备处方审核角色）不展示剂数/用法、处方笺等
 */
const showPrescriptionAuditFilter = computed(() => {
    const u = userStore.userInfo
    if (!u || Number(u.root) === 1) return true
    const ids = Array.isArray(u.role_ids) ? u.role_ids.map((n: unknown) => Number(n)) : []
    if (!ids.includes(TCM_ASSISTANT_ROLE_ID)) return true
    return ids.some((id) => PRESCRIPTION_AUDIT_ROLE_IDS.includes(id))
})

// ─── 详情数据 ───
const detailVisible = ref(false)
const detailLoading = ref(false)
const detailData = ref<Record<string, any> | null>(null)
const detailLogs = ref<any[]>([])
const detailUnlinkedPayOrders = ref<any[]>([])

const detailPrescription = computed(() => {
    const p = detailData.value?.prescription
    return p && typeof p === 'object' ? p : null
})

const detailDietaryText = computed(() => formatDietaryTaboo(detailPrescription.value?.dietary_taboo))

const detailLinkedPayOrders = computed(() => {
    const d = detailData.value
    if (!d) return []
    const arr = d.linked_pay_orders
    return Array.isArray(arr) ? arr : []
})

/** 需代收：优先用关联时记录的固定快照值；历史单（无快照）回退实时计算 总金额 − 关联已付总额 */
const detailAgencyToCollect = computed(() => {
    const d = detailData.value
    if (!d) return 0
    const snap = d.agency_collect_amount
    if (snap !== null && snap !== undefined && snap !== '') {
        return Number(snap) || 0
    }
    const total = Number(d.amount) || 0
    const paid = Number(d.linked_pay_paid_total) || 0
    return Math.round((total - paid) * 100) / 100
})

// --- 订单可视化审批履约流程逻辑 ---
const workflowActiveStep = computed(() => {
    if (!detailData.value) return 0
    const fs = Number(detailData.value.fulfillment_status)
    const rx = Number(detailData.value.prescription_audit_status)
    const pay = Number(detailData.value.payment_slip_audit_status)

    if (fs === 3 || [8, 9, 10, 11, 12].includes(fs)) return 5 // 订单完成 / 业务结案
    if (fs === 6) return 4 // 已签收（仍停留在"已发货/送达"环节）
    if (fs === 5) return 4 // 已发货
    if (fs === 7) return 4 // 进行中

    if (fs === 4) { // 已取消
        if (rx === 2) return 1
        if (pay === 2) return 2
        return 3
    }

    if (fs === 2) return 3 // 履约中

    // fs === 1 (待双审通过)
    if (rx === 0 || rx === 2) return 1
    if (pay === 0 || pay === 2) return 2
    return 3
})

const workflowRxStatus = computed(() => {
    const rx = Number(detailData.value?.prescription_audit_status)
    if (rx === 1) return 'success'
    if (rx === 2) return 'error'
    if (workflowActiveStep.value === 1) return 'process'
    return 'wait'
})

const workflowPayStatus = computed(() => {
    const pay = Number(detailData.value?.payment_slip_audit_status)
    if (pay === 1) return 'success'
    if (pay === 2) return 'error'
    if (workflowActiveStep.value === 2) return 'process'
    return 'wait'
})

const workflowFulfillStatus = computed(() => {
    const fs = Number(detailData.value?.fulfillment_status)
    if (fs === 3 || fs === 5 || fs === 6 || fs === 8 || fs === 11 || fs === 12) return 'success'
    if (fs === 4 || fs === 9 || fs === 10) return 'error'
    if (fs === 7) return 'process'
    if (workflowActiveStep.value === 3) return 'process'
    return 'wait'
})
// --- end 可视化流程逻辑 ---

/** 详情抽屉：业务收货手机 vs 处方登记手机 */
const detailRecipientRxPhoneMismatch = computed(() => {
    const rx = detailPrescription.value?.phone
    const biz = detailData.value?.recipient_phone
    return recipientVsPrescriptionPhoneMismatch(biz, rx)
})

const detailPrescriptionPhoneDisplay = computed(() => {
    const s = normalizeBizPhone(detailPrescription.value?.phone)
    return s || '—'
})

const detailOrderPhoneDisplay = computed(() => {
    const s = normalizeBizPhone(detailData.value?.recipient_phone)
    return s || '—'
})

/** 详情：业务订单创建人部门面包屑（后端 order_creator_dept_path / diagnosis_creator_dept_path） */
const detailOrderCreatorDeptBreadcrumbs = computed(() => {
    const raw = String(
        (detailData.value as Record<string, unknown> | null)?.order_creator_dept_path ??
            (detailData.value as Record<string, unknown> | null)?.diagnosis_creator_dept_path ??
            ''
    ).trim()
    if (!raw) {
        return [] as string[][]
    }
    return raw
        .split('；')
        .map((s) => s.trim())
        .filter(Boolean)
        .map((p) => {
            if (p.includes(' / ')) {
                return p
                    .split(' / ')
                    .map((x) => x.trim())
                    .filter(Boolean)
            }
            return p
                .split('/')
                .map((x) => x.trim())
                .filter(Boolean)
        })
        .filter((segs) => segs.length > 0)
})

const detailOrderCreatorMetaLine = computed(() => {
    const d = detailData.value as Record<string, unknown> | null
    if (!d) return ''
    const account = String(d.creator_account ?? '').trim()
    const mobile = String(d.creator_mobile ?? '').trim()
    const parts: string[] = []
    if (account) parts.push(`登录账号：${account}`)
    if (mobile) parts.push(`手机：${mobile}`)
    return parts.join(' · ')
})

const detailLinkedAppointment = computed(() => {
    const a = detailData.value?.linked_appointment
    return a && typeof a === 'object' ? a : null
})

const detailLinkedAppointmentResolvedFromTag = computed(() => {
    const from = String(detailLinkedAppointment.value?.resolved_from || '')
    if (from === 'prescription') return '处方绑定挂号'
    if (from === 'diagnosis') return '诊单关联挂号'
    return ''
})

/** 渠道展示：后端 linked_appointment.channel_source_desc（字典名），缺省回退原值 */
const detailLinkedAppointmentChannelText = computed(() => {
    const a = detailLinkedAppointment.value
    if (!a) return ''
    const desc = String(a.channel_source_desc ?? '').trim()
    if (desc) return desc
    return String(a.channel_source ?? '').trim()
})

const detailRxHerbs = computed(() => normalizeSlipHerbs(detailPrescription.value?.herbs))

const detailHasAuxHerbs = computed(() => prescriptionHasAuxFormula(detailPrescription.value as any))

/** 详情：辅方用法（aux_usage JSON 经规范化后的对象，与处方类型一致） */
const detailAuxUsage = computed(() => {
    const rx = detailPrescription.value as any
    if (!rx || !prescriptionHasAuxFormula(rx)) return null
    const raw = rx.aux_usage
    if (raw == null || raw === '' || (Array.isArray(raw) && raw.length === 0)) return null
    return normalizeSlipAuxUsageForm(raw, rx.prescription_type || '浓缩水丸')
})

/** false=无权限；true/缺省兼容旧接口（旧版未下发该字段时仍展示药材） */
const detailHerbsVisible = computed(() => detailData.value?.prescription_detail_herbs_visible !== false)

/** 内部成本（财务字段）：仅完整版展示 */
const showInternalCost = computed(
    () => !props.readonly && detailData.value?.internal_cost != null && detailData.value?.internal_cost !== ''
)

// 完整收货地址（省市区 + 详细地址）
const detailFullAddress = computed(() => {
    const d = detailData.value
    if (!d) return '—'

    const parts = []
    if (d.shipping_province) parts.push(d.shipping_province)
    if (d.shipping_city) parts.push(d.shipping_city)
    if (d.shipping_district) parts.push(d.shipping_district)
    if (d.shipping_address) parts.push(d.shipping_address)

    return parts.length > 0 ? parts.join(' ') : '—'
})

// ─── 服务套餐字典 ───
const servicePackageOptions = ref<ServicePackageOption[]>([])

async function loadServicePackageOptions() {
    if (servicePackageOptions.value.length > 0) return
    try {
        const data: any = await getDictData({ type: 'server_order' })
        const opts = normalizeServicePackageOptions(data?.server_order)
        if (opts.length > 0) {
            servicePackageOptions.value = opts
        }
    } catch {
        /* 请求被同参数请求取消或失败时保留现值，open() 时会重试 */
    }
}

const detailServicePackageText = computed(() =>
    formatServicePackageLabels(detailData.value?.service_package, servicePackageOptions.value)
)

onMounted(() => {
    loadServicePackageOptions()
})

// ─── 操作日志 ───
function canViewPrescriptionOrderLogs() {
    const p = userStore.perms || []
    return p.includes('*') || p.includes('tcm.prescriptionOrder/logs')
}

async function fetchLogs(id: number) {
    if (!canViewPrescriptionOrderLogs()) {
        detailLogs.value = []
        return
    }
    try {
        const res: any = await prescriptionOrderLogs({ id })
        detailLogs.value = res?.data ?? res ?? []
    } catch {
        detailLogs.value = []
    }
}

function hasPerm(perm: string) {
    const p = userStore.perms || []
    return p.includes('*') || p.includes(perm)
}

function canAddPrescriptionOrderLog() {
    return hasPerm('tcm.prescriptionOrder/addLog')
}

/** 与后端 canAuditPrescriptionOrder 同档：超管或 prescription_audit_roles */
const canSetRxAuditOnAddLog = computed(() => {
    const u = userStore.userInfo
    if (!u || Number(u.root) === 1) return true
    const ids = Array.isArray(u.role_ids) ? u.role_ids.map((n: unknown) => Number(n)) : []
    return ids.some((id) => PRESCRIPTION_AUDIT_ROLE_IDS.includes(id))
})

/** 与后端 canAuditPaymentSlipOrder 同档：超管或 prescription_order_payment_audit_roles 默认 0,3 */
const canSetPayAuditOnAddLog = computed(() => {
    const u = userStore.userInfo
    if (!u || Number(u.root) === 1) return true
    const ids = Array.isArray(u.role_ids) ? u.role_ids.map((n: unknown) => Number(n)) : []
    return ids.some((id) => [0, 3].includes(id))
})

const addLogVisible = ref(false)
const addLogSaving = ref(false)
const addLogFormRef = ref<FormInstance>()
const addLogForm = reactive({
    summary: '',
    prescription_audit_status: '' as number | '',
    payment_slip_audit_status: '' as number | '',
    prescription_audit_remark: '',
    payment_slip_audit_remark: ''
})
const addLogRules: FormRules = {
    summary: [{ required: true, message: '请填写日志内容', trigger: 'blur' }]
}

const patchUsageVisible = ref(false)
const patchUsageSaving = ref(false)
const patchUsageFormRef = ref<FormInstance>()
const patchUsageForm = reactive({
    times_per_day: 3 as number | undefined,
    usage_days: 7 as number | undefined,
    aux_times_per_day: 3 as number | undefined,
    aux_usage_days: 7 as number | undefined,
    medication_days: undefined as number | undefined
})
const patchUsageRules = computed<FormRules>(() => {
    const rules: FormRules = {
        times_per_day: [{ required: true, message: '请填写主方每天次数', trigger: 'change' }],
        usage_days: [{ required: true, message: '请填写主方开立天数', trigger: 'change' }],
        medication_days: [{ required: true, message: '请填写订单服用天数', trigger: 'change' }]
    }
    if (detailHasAuxHerbs.value) {
        rules.aux_times_per_day = [{ required: true, message: '请填写辅方每天次数', trigger: 'change' }]
        rules.aux_usage_days = [{ required: true, message: '请填写辅方开立天数', trigger: 'change' }]
    }
    return rules
})

function openPatchUsageDialog() {
    const rx = detailPrescription.value
    const ord = detailData.value
    if (!rx || !ord?.id || !ord.prescription_id) {
        feedback.msgWarning('无处方数据')
        return
    }
    const aux = detailAuxUsage.value
    patchUsageForm.times_per_day =
        Number(rx.times_per_day) > 0 ? Number(rx.times_per_day) : 3
    patchUsageForm.usage_days =
        Number(rx.usage_days) > 0 ? Number(rx.usage_days) : 7
    patchUsageForm.aux_times_per_day =
        aux && Number(aux.times_per_day) > 0 ? Number(aux.times_per_day) : 3
    patchUsageForm.aux_usage_days =
        aux && Number(aux.usage_days) > 0 ? Number(aux.usage_days) : 7
    const md = Number(ord.medication_days)
    patchUsageForm.medication_days = md > 0 ? md : Number(rx.usage_days) > 0 ? Number(rx.usage_days) : 7
    patchUsageVisible.value = true
    nextTick(() => patchUsageFormRef.value?.clearValidate())
}

function resetPatchUsageForm() {
    patchUsageForm.times_per_day = 3
    patchUsageForm.usage_days = 7
    patchUsageForm.aux_times_per_day = 3
    patchUsageForm.aux_usage_days = 7
    patchUsageForm.medication_days = undefined
}

async function submitPatchUsage() {
    const form = patchUsageFormRef.value
    if (!form) return
    try {
        await form.validate()
    } catch {
        return
    }
    const ordId = detailData.value?.id
    if (!ordId) return
    patchUsageSaving.value = true
    try {
        const payload: {
            id: number
            times_per_day: number
            usage_days: number
            medication_days: number
            aux_times_per_day?: number
            aux_usage_days?: number
        } = {
            id: ordId,
            times_per_day: Number(patchUsageForm.times_per_day),
            usage_days: Number(patchUsageForm.usage_days),
            medication_days: Number(patchUsageForm.medication_days)
        }
        if (detailHasAuxHerbs.value) {
            payload.aux_times_per_day = Number(patchUsageForm.aux_times_per_day)
            payload.aux_usage_days = Number(patchUsageForm.aux_usage_days)
        }
        await prescriptionOrderPatchPrescriptionUsage(payload)
        feedback.msgSuccess('保存成功')
        patchUsageVisible.value = false
        await refresh()
        emit('detail-changed')
    } catch {
        /* 拦截器已提示 */
    } finally {
        patchUsageSaving.value = false
    }
}

function resetAddLogForm() {
    addLogForm.summary = ''
    addLogForm.prescription_audit_status = ''
    addLogForm.payment_slip_audit_status = ''
    addLogForm.prescription_audit_remark = ''
    addLogForm.payment_slip_audit_remark = ''
    addLogFormRef.value?.clearValidate()
}

function openAddLogDialog() {
    if (!detailData.value?.id) return
    resetAddLogForm()
    const d = detailData.value
    addLogForm.prescription_audit_remark = String(d.prescription_audit_remark || '')
    addLogForm.payment_slip_audit_remark = String(d.payment_slip_audit_remark || '')
    addLogVisible.value = true
}

async function submitAddLog() {
    if (!addLogFormRef.value || !detailData.value?.id) return
    await addLogFormRef.value.validate()
    addLogSaving.value = true
    try {
        const payload: Record<string, unknown> = {
            id: detailData.value.id,
            summary: addLogForm.summary.trim()
        }
        if (
            canSetRxAuditOnAddLog.value &&
            addLogForm.prescription_audit_status !== '' &&
            addLogForm.prescription_audit_status !== null &&
            addLogForm.prescription_audit_status !== undefined
        ) {
            payload.prescription_audit_status = addLogForm.prescription_audit_status
            payload.prescription_audit_remark = addLogForm.prescription_audit_remark
        }
        if (
            canSetPayAuditOnAddLog.value &&
            addLogForm.payment_slip_audit_status !== '' &&
            addLogForm.payment_slip_audit_status !== null &&
            addLogForm.payment_slip_audit_status !== undefined
        ) {
            payload.payment_slip_audit_status = addLogForm.payment_slip_audit_status
            payload.payment_slip_audit_remark = addLogForm.payment_slip_audit_remark
        }
        await prescriptionOrderAddLog(payload as any)
        feedback.msgSuccess('日志已添加')
        addLogVisible.value = false
        await refresh()
        emit('detail-changed')
    } catch {
        /* 拦截器已提示 */
    } finally {
        addLogSaving.value = false
    }
}

// ─── 未关联支付单 ───
async function loadDetailUnlinkedPayOrders(diagnosisId: number, prescriptionOrderId: number, linkedIds: number[]) {
    if (!diagnosisId) {
        detailUnlinkedPayOrders.value = []
        return
    }
    try {
        const res: any = await prescriptionOrderPaidPayOrders({
            diagnosis_id: diagnosisId,
            prescription_order_id: prescriptionOrderId
        })
        const lists = res?.lists ?? res?.data?.lists ?? []
        // 列表已由服务端限制；此处再过滤已关联项
        const filtered = Array.isArray(lists)
            ? lists.filter((item: any) => !linkedIds.includes(item.id))
            : []
        detailUnlinkedPayOrders.value = filtered
    } catch {
        detailUnlinkedPayOrders.value = []
    }
}

// ─── 物流轨迹 ───
const detailLogisticsExpress = ref<string>('auto')
const logisticsTraceLoading = ref(false)
const jdLogisticsUpdating = ref(false)
const logisticsTracePayload = ref<Record<string, any> | null>(null)
/** 顺丰/快递100：与运单一致的收件手机后四位（可覆盖订单收货手机） */
const logisticsTracePhoneTail = ref('')
/** 物流轨迹请求序号：同手机多运单或快速切换订单时，丢弃过期的异步响应 */
let logisticsTraceRequestSeq = 0

type LogisticsTraceRequestContext = {
    requestSeq: number
    orderId: number
    trackingNumber: string
}

function bumpLogisticsTraceRequestToken() {
    logisticsTraceRequestSeq += 1
    logisticsTracePayload.value = null
}

function isCurrentLogisticsTraceContext(ctx: LogisticsTraceRequestContext): boolean {
    if (ctx.requestSeq !== logisticsTraceRequestSeq) return false
    if (Number(detailData.value?.id) !== ctx.orderId) return false
    return String(detailData.value?.tracking_number || '').trim() === ctx.trackingNumber
}

const detailOfficialUrls = computed(() => {
    const n = String(detailData.value?.tracking_number || '').trim()
    if (!n) {
        return { sf: 'javascript:void(0)', jd: 'javascript:void(0)', jt: 'javascript:void(0)' }
    }
    const enc = encodeURIComponent(n)
    return {
        sf: `https://www.sf-express.com/cn/sc/dynamic_function/waybill/#search/bill-number/${enc}`,
        jd: `https://www.jdl.com/#/trackQuery?waybillCode=${enc}`,
        jt: `https://www.jtexpress.com.cn/index/query/gzquery.html?bills=${enc}`
    }
})

const logisticsTraceList = computed(() => {
    const p = logisticsTracePayload.value
    if (!p || !Array.isArray(p.traces)) return []
    return p.traces as Array<{ time: string; context: string }>
})

/** 详情抽屉：轨迹/状态中是否出现拒收等字样，用于顶部与物流卡片强提示 */
const detailLogisticsUrgent = computed(() => analyzeLogisticsPayloadUrgent(logisticsTracePayload.value))

async function fetchLogisticsTrace() {
    const orderId = Number(detailData.value?.id)
    const trackingNumber = String(detailData.value?.tracking_number || '').trim()
    if (!orderId || !trackingNumber) return

    const requestSeq = ++logisticsTraceRequestSeq
    const ctx: LogisticsTraceRequestContext = { requestSeq, orderId, trackingNumber }

    logisticsTraceLoading.value = true
    try {
        const digits = String(logisticsTracePhoneTail.value || '').replace(/\D/g, '')
        const params: { id: number; express_company?: string; phone_tail?: string } = {
            id: orderId,
            express_company: detailLogisticsExpress.value
        }
        if (digits.length >= 4) {
            params.phone_tail = digits
        }
        const res: any = await prescriptionOrderLogisticsTrace(params)
        if (!isCurrentLogisticsTraceContext(ctx)) return
        logisticsTracePayload.value = parseLogisticsTracePayload(res, trackingNumber, orderId)
    } catch {
        if (!isCurrentLogisticsTraceContext(ctx)) return
        logisticsTracePayload.value = null
    } finally {
        if (isCurrentLogisticsTraceContext(ctx)) {
            logisticsTraceLoading.value = false
        }
    }
}

// 直接请求京东官方物流接口，刷新并落库轨迹后重新读取展示
async function updateJdLogistics() {
    const orderId = Number(detailData.value?.id)
    const trackingNumber = String(detailData.value?.tracking_number || '').trim()
    if (!orderId || !trackingNumber) {
        feedback.msgWarning('当前订单未填写快递单号')
        return
    }
    jdLogisticsUpdating.value = true
    try {
        const res: any = await prescriptionOrderLogisticsJdUpdate({ id: orderId })
        feedback.msgSuccess(res?.message || '京东物流轨迹已更新')
        await fetchLogisticsTrace()
    } catch (e: any) {
        feedback.msgError(e?.message || '京东物流更新失败')
    } finally {
        jdLogisticsUpdating.value = false
    }
}

// ─── 打开 / 刷新 ───
async function open(id: number) {
    // 页面级同参数字典请求会取消抽屉挂载时的那次（axios 去重取消），打开时兜底重试
    void loadServicePackageOptions()
    // 显式彻底清空缓存，防止前一次弹窗的数据残留
    detailData.value = null
    detailUnlinkedPayOrders.value = []
    bumpLogisticsTraceRequestToken()
    detailLogisticsExpress.value = 'auto'
    logisticsTracePhoneTail.value = ''
    detailLogs.value = []

    detailVisible.value = true
    detailLoading.value = true
    try {
        const res: any = await prescriptionOrderDetail({ id })
        const d = res?.data ?? res ?? null
        detailData.value = d
        if (d) {
            detailLogisticsExpress.value = String(d.express_company || 'auto') || 'auto'
            const dig = String(d.recipient_phone || '').replace(/\D/g, '')
            logisticsTracePhoneTail.value = dig.length >= 4 ? dig : ''
            if (String(d.tracking_number || '').trim()) {
                fetchLogisticsTrace()
            }
            fetchLogs(id)

            // 加载未关联的支付单
            const diagId = d.diagnosis_id
            const linkedIds = d.pay_order_ids || []
            if (diagId) {
                void loadDetailUnlinkedPayOrders(diagId, id, linkedIds)
            }
        }
    } catch (e: any) {
        feedback.msgError(e?.message || '加载失败')
        detailVisible.value = false
    } finally {
        detailLoading.value = false
    }
}

/** 静默刷新当前详情（含日志/未关联支付单；快递单号变化时重拉轨迹），供父页面操作成功后调用 */
async function refresh() {
    const id = Number(detailData.value?.id)
    if (!id) return
    try {
        const res: any = await prescriptionOrderDetail({ id })
        const d = res?.data ?? res ?? null
        if (!d) return
        const prevTracking = String(detailData.value?.tracking_number || '').trim()
        detailData.value = d
        const nextTracking = String(d.tracking_number || '').trim()
        if (nextTracking && nextTracking !== prevTracking) {
            bumpLogisticsTraceRequestToken()
            detailLogisticsExpress.value = String(d.express_company || 'auto') || 'auto'
            void fetchLogisticsTrace()
        }
        void fetchLogs(id)
        const diagId = d.diagnosis_id
        if (diagId) {
            void loadDetailUnlinkedPayOrders(diagId, id, d.pay_order_ids || [])
        }
    } catch {
        /* 静默失败，避免打断当前抽屉 */
    }
}

/** 抽屉开着且正展示指定订单时刷新（父页面列表操作后的常用模式） */
async function refreshIfCurrent(id: number | string | undefined) {
    const n = Number(id)
    if (!detailVisible.value || !(n > 0) || Number(detailData.value?.id) !== n) return
    await refresh()
}

function close() {
    detailVisible.value = false
}

defineExpose({
    open,
    refresh,
    refreshIfCurrent,
    close,
    /** 当前详情数据（父页面操作弹窗/槽内按钮可读取，亦可原地修补字段） */
    detail: detailData,
    visible: detailVisible
})
</script>

<style scoped lang="scss">
.po-detail-drawer :deep(.el-drawer__header) {
    margin-bottom: 0;
    padding: 16px 24px;
    border-bottom: 1px solid var(--el-border-color-lighter);
}

.stat-card {
    border-radius: 8px;
}

.stat-title {
    font-weight: 500;
}

.po-panel {
    border-radius: 8px;
    transition: all 0.3s;
}

.po-panel :deep(.el-card__header) {
    padding: 14px 16px;
    background-color: var(--el-bg-color-page);
    border-bottom: 1px solid var(--el-border-color-lighter);
}

.po-panel :deep(.el-card__body) {
    padding: 16px;
}

.po-desc :deep(.el-descriptions__label) {
    width: 120px;
    color: var(--el-text-color-regular);
}

.po-audit-remark {
    color: var(--el-color-danger);
    font-weight: 600;
    white-space: pre-wrap;
    word-break: break-word;
}

/* 动态审核印章 */
.audit-stamp {
    position: absolute;
    top: 18px;
    right: -14px;
    width: 72px;
    height: 72px;
    border: 3px solid currentColor;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    transform: rotate(20deg);
    opacity: 0.8;
    pointer-events: none;
    z-index: 10;
    user-select: none;
    font-weight: 700;
    font-size: 13px;
    letter-spacing: 1px;
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.5);
}
.audit-stamp::after {
    content: '';
    position: absolute;
    top: 4px;
    left: 4px;
    right: 4px;
    bottom: 4px;
    border: 1px double currentColor;
    border-radius: 50%;
    opacity: 0.6;
}
.audit-stamp .stamp-inner {
    text-align: center;
    line-height: 1.1;
}
.stamp-pass {
    color: var(--el-color-success);
}
.stamp-reject {
    color: var(--el-color-danger);
}

.po-diagnosis-creator-dept-breadcrumb {
    :deep(.el-breadcrumb__item) {
        display: inline-flex;
        float: none;
    }
    :deep(.el-breadcrumb__separator) {
        margin: 0 2px 0 4px;
    }
}
</style>
