<!-- 处方管理 -->
<template>
    <div class="prescription-list">
        <el-card class="filter-toolbar" shadow="never" :body-style="{ padding: '10px 14px' }">
            <div class="pl-toolbar">
                <div class="pl-toolbar__line">
                    <span class="pl-toolbar__k" title="按处方创建时间">创建时间</span>
                    <el-radio-group
                        v-model="dateQuickTab"
                        size="small"
                        class="pl-toolbar__rg"
                        @change="onDateQuickTabChange"
                    >
                        <el-radio-button label="all">全部</el-radio-button>
                        <el-radio-button label="today">今日</el-radio-button>
                        <el-radio-button label="yesterday">昨日</el-radio-button>
                        <el-radio-button label="before_yesterday">前天</el-radio-button>
                    </el-radio-group>
                    <DaterangePicker
                        class="pl-toolbar__range"
                        v-model:startTime="formData.start_time"
                        v-model:endTime="formData.end_time"
                    />
                    <span class="pl-toolbar__sep" aria-hidden="true" />
                    <span
                        class="pl-toolbar__k"
                        title="「未通过」含待审核与已驳回"
                    >审核</span>
                    <el-radio-group
                        v-model="formData.audit_filter"
                        size="small"
                        class="pl-toolbar__rg pl-toolbar__rg--audit"
                        @change="onAuditFilterChange"
                    >
                        <el-radio-button label="pending" class="pl-audit-pending-btn">待审核</el-radio-button>
                        <el-radio-button label="all">全部</el-radio-button>
                        <el-radio-button label="passed">已通过</el-radio-button>
                        <el-radio-button label="not_passed">未通过</el-radio-button>
                        <el-radio-button label="rejected">驳回</el-radio-button>
                    </el-radio-group>
                    <span class="pl-toolbar__sep" aria-hidden="true" />
                    <span class="pl-toolbar__k" title="与列表「来源」列一致：系统代开 / 手工">来源</span>
                    <el-radio-group
                        v-model="formData.source_filter"
                        size="small"
                        class="pl-toolbar__rg pl-toolbar__rg--source"
                        @change="onSourceFilterChange"
                    >
                        <el-radio-button label="all">全部</el-radio-button>
                        <el-radio-button label="manual">手工</el-radio-button>
                        <el-radio-button label="system">系统代开</el-radio-button>
                    </el-radio-group>
                </div>
                <div class="pl-toolbar__line pl-toolbar__line--second">
                    <el-form :model="formData" inline class="pl-toolbar__form">
                        <el-form-item label="处方编号" class="!mb-0">
                            <el-input
                                v-model="formData.sn"
                                placeholder="编号"
                                clearable
                                class="pl-toolbar__input"
                                @keyup.enter="resetPage"
                            />
                        </el-form-item>
                        <el-form-item label="患者" class="!mb-0">
                            <el-input
                                v-model="formData.patient_name"
                                placeholder="姓名"
                                clearable
                                class="pl-toolbar__input"
                                @keyup.enter="resetPage"
                            />
                        </el-form-item>
                        <el-form-item label="医师" class="!mb-0">
                            <el-select
                                v-model="formData.creator_ids"
                                multiple
                                collapse-tags
                                collapse-tags-tooltip
                                filterable
                                clearable
                                placeholder="全部医师"
                                class="pl-toolbar__select pl-toolbar__select--doctors"
                            >
                                <el-option
                                    v-for="d in doctorOptions"
                                    :key="d.id"
                                    :label="d.name"
                                    :value="Number(d.id)"
                                />
                            </el-select>
                        </el-form-item>
                    </el-form>
                    <div class="pl-toolbar__actions">
                        <el-button type="primary" @click="resetPage">查询</el-button>
                        <el-button @click="resetParams">重置</el-button>
                    </div>
                </div>
            </div>
        </el-card>

        <el-card v-loading="pager.loading" class="mt-3 table-card" shadow="never">
            <div class="pl-table-head">
                <span class="pl-table-head__title">处方列表</span>
                <div class="flex items-center gap-2">
                    <el-button
                        v-perms="['tcm.prescriptionOrder/lists']"
                        @click="goBusinessOrderList"
                    >
                        业务订单
                    </el-button>
                    <el-button type="primary" @click="handleAdd" v-perms="['cf.prescription/add']">
                        <template #icon>
                            <icon name="el-icon-Plus" />
                        </template>
                        新增处方
                    </el-button>
                </div>
            </div>

            <div class="mt-3">
                <el-table :data="pager.lists" size="default" stripe>
                    <el-table-column label="处方编号" min-width="160">
                        <template #default="{ row }">
                            <span class="font-medium">{{ row.sn || '—' }}</span>
                            <div class="text-xs text-gray-400 mt-0.5">ID: {{ row.id }}</div>
                            <div
                                v-for="(warn, idx) in listRxOrderWarnings(row)"
                                :key="`rx-order-warn-${row.id}-${idx}`"
                                class="text-xs text-red-600 mt-0.5 leading-snug"
                            >
                                {{ warn }}
                            </div>
                        </template>
                    </el-table-column>
                    <el-table-column label="处方类型" min-width="100">
                        <template #default="{ row }">
                            <el-tag type="info" size="small">{{ row.prescription_type || '—' }}</el-tag>
                        </template>
                    </el-table-column>
                    <el-table-column label="来源" min-width="92" align="center">
                        <template #default="{ row }">
                            <el-tag
                                v-if="Number(row.is_system_auto) === 1"
                                type="warning"
                                size="small"
                                effect="plain"
                            >
                                系统代开
                            </el-tag>
                            <span v-else class="text-gray-400 text-sm">手工</span>
                        </template>
                    </el-table-column>
                    <el-table-column label="患者信息" min-width="110">
                        <template #default="{ row }">
                            <div class="font-medium">{{ row.patient_name || '—' }}</div>
                            <div class="text-xs text-gray-500 mt-0.5">
                                {{ row.gender === 1 ? '男' : (row.gender === 0 ? '女' : '未知') }} · {{ row.age ? row.age + '岁' : '—' }}
                            </div>
                        </template>
                    </el-table-column>
              
                  
                
                    <el-table-column label="审核状态" min-width="200">
                        <template #default="{ row }">
                            <div class="flex flex-col gap-1">
                                <div class="flex flex-wrap items-center gap-1">
                                    <el-tag :type="listAuditStatusTagType(row)">
                                        {{ listAuditStatusLabel(row) }}
                                    </el-tag>
                                    <span
                                        v-if="Number(row.business_prescription_audit_rejected) === 1"
                                        class="text-xs text-gray-500"
                                    >
                                        （业务订单审核）
                                    </span>
                                </div>
                                <template v-if="listRejectReasonLines(row).length">
                                    <div
                                        v-for="(line, idx) in listRejectReasonLines(row)"
                                        :key="idx"
                                        class="text-xs text-red-600 leading-snug line-clamp-3"
                                        :title="line"
                                    >
                                        {{ line }}
                                    </div>
                                </template>
                            </div>
                        </template>
                    </el-table-column>
                    <el-table-column label="作废" min-width="80" align="center">
                        <template #default="{ row }">
                            <el-tag v-if="row.void_status === 1" type="danger" size="small">作废</el-tag>
                            <span v-else class="text-gray-400">—</span>
                        </template>
                    </el-table-column>
                    <el-table-column label="医师信息" min-width="120">
                        <template #default="{ row }">
                            <div class="font-medium">{{ row.doctor_name || '—' }}</div>
                            <div class="text-xs text-gray-500 mt-0.5">{{ row.prescription_date || '—' }}</div>
                        </template>
                    </el-table-column>
                    <el-table-column label="医助" min-width="90">
                        <template #default="{ row }">
                            <div class="text-sm">{{ row.assistant_name || '—' }}</div>
                        </template>
                    </el-table-column>
                    <el-table-column label="创建时间" min-width="160">
                        <template #default="{ row }">
                            {{ formatListCreateTime(row.create_time) }}
                        </template>
                    </el-table-column>
                    <el-table-column label="操作" width="300" fixed="right">
                        <template #default="{ row }">
                            <el-button type="primary" link @click="handleView(row)"  v-perms="['cf.prescription/read']">
                                查看
                            </el-button>
                            <el-button
                                v-if="Number(row.void_status) !== 1"
                                type="primary"
                                link
                                v-perms="['tcm.prescription/patchPatient']"
                                @click="openPatchPatientDialog(row)"
                            >
                                改姓名手机
                            </el-button>
                            <el-button
                                v-if="!Number(row.has_prescription_order) && Number(row.void_status) !== 1"
                                type="success"
                                link
                                v-perms="['tcm.prescriptionOrder/create']"
                                @click="openCreateOrderFromPrescription(row)"
                            >
                                创建订单
                            </el-button>
                            <el-button
                                v-if="!isApprovedActivePrescription(row)"
                                type="primary"
                                link
                                @click="handleEdit(row)"
                                v-perms="['cf.prescription/edit']"
                            >
                                编辑
                            </el-button>
                            <el-button
                                v-if="row.audit_status === 0 && row.void_status !== 1"
                                type="warning"
                                link
                                v-perms="['cf.prescription/audit']"
                                @click="openAuditDialog(row)"
                            >
                                审核
                            </el-button>
                            <el-button
                                v-if="!isApprovedActivePrescription(row)"
                                type="danger"
                                link
                                @click="handleDelete(row.id)"
                                v-perms="['cf.prescription/del']"
                            >
                                删除
                            </el-button>
                        </template>
                    </el-table-column>
                </el-table>
            </div>
            
            <div class="flex mt-2 justify-end">
                <pagination v-model="pager" @change="getLists" />
            </div>
        </el-card>
        
        <!-- 新增/编辑/查看抽屉 -->
        <el-drawer
            v-model="showEdit"
            :title="editMode === 'add' ? '新增处方' : editMode === 'edit' ? '编辑处方' : '查看处方'"
            :size="editMode === 'view' ? '920px' : '860px'"
            class="cf-prescription-drawer"
            :close-on-click-modal="false"
            destroy-on-close
            @closed="onEditDialogClosed"
        >
            <!-- 查看：A4 处方笺（药房联样式） -->
            <div v-if="editMode === 'view'" v-loading="viewDetailLoading" class="rx-wrap">
                <!-- 顶部工具栏（不打印 / 不下载） -->
                <div class="rx-toolbar">
                    <el-tag
                        v-if="slipView && Number(slipView.is_system_auto) === 1"
                        type="warning"
                        size="small"
                        effect="plain"
                    >系统代开</el-tag>
                    <el-tag v-if="slipView && Number(slipView.void_status) === 1" type="danger" size="small">已作废</el-tag>
                    <el-tag
                        v-else-if="slipView && Number(slipView.business_prescription_audit_rejected) === 1"
                        type="danger"
                        size="small"
                    >业务订单已驳回</el-tag>
                    <el-tag
                        v-else-if="slipView && Number(slipView.audit_status) === 1"
                        type="success"
                        size="small"
                    >已通过</el-tag>
                    <el-tag
                        v-else-if="slipView && Number(slipView.audit_status) === 0"
                        type="warning"
                        size="small"
                    >待审核</el-tag>
                    <el-tag v-else-if="slipView" type="danger" size="small">已驳回</el-tag>
                    <div class="flex-1" />
                    <el-button :icon="Printer" size="small" @click="handlePrintSlip">打印</el-button>
                    <el-button
                        type="primary"
                        :icon="Download"
                        size="small"
                        :loading="downloadingSlip"
                        @click="handleDownloadSlip"
                    >
                        下载 PDF (A4)
                    </el-button>
                </div>

                <!-- 状态提示（不进入打印区） -->
                <div v-if="slipView && Number(slipView.void_status) === 1" class="rx-status rx-status-danger">
                    作废人：{{ slipView.void_by_name || '—' }}，作废时间：{{ formatVoidTime(slipView.void_time) }}
                </div>
                <div
                    v-else-if="slipView && Number(slipView.business_prescription_audit_rejected) === 1"
                    class="rx-status rx-status-danger"
                >
                    <div class="font-medium">审核状态：已驳回（业务订单·处方审核）</div>
                    <div v-if="slipView.business_prescription_audit_remark" class="mt-1">
                        驳回意见：{{ slipView.business_prescription_audit_remark }}
                    </div>
                </div>
                <div
                    v-else-if="slipView && Number(slipView.audit_status) === 2"
                    class="rx-status rx-status-danger"
                >
                    <div class="font-medium">消费者处方审核：已驳回</div>
                    <div v-if="slipView.audit_remark" class="mt-1">驳回意见：{{ slipView.audit_remark }}</div>
                </div>

                <!-- A4 处方纸 -->
                <div v-if="slipView" ref="rxPaperRef" class="rx-paper">
                    <!-- 顶部告知栏 -->
                    <div class="rx-notice">
                        <span class="rx-notice-text">
                            服药前请核对姓名、电话、医生等信息以及服法、医嘱等要点
                        </span>
                        <span class="rx-notice-meta">
                            <span>日期：{{ rxDateText }}</span>
                            <span>编号：{{ rxSerialText }}</span>
                        </span>
                    </div>

                    <!-- 患者信息表 -->
                    <div class="rx-info">
                        <div class="rx-info-row">
                            <div class="rx-info-cell">
                                <span class="rx-key">姓名</span>
                                <span class="rx-val">{{ slipView.patient_name || '—' }}</span>
                            </div>
                            <div class="rx-info-cell">
                                <span class="rx-key">性别</span>
                                <span class="rx-val">{{ slipGenderLabel(slipView.gender) }}</span>
                            </div>
                            <div class="rx-info-cell">
                                <span class="rx-key">年龄</span>
                                <span class="rx-val">{{ slipAgeText(slipView.age) }}</span>
                            </div>
                            <div class="rx-info-cell">
                                <span class="rx-key">电话</span>
                                <span class="rx-val">{{ slipView.phone || '—' }}</span>
                            </div>
                        </div>
                        <div class="rx-info-row rx-info-row-full">
                            <div class="rx-info-cell">
                                <span class="rx-key">收件信息</span>
                                <span class="rx-val">{{ rxRecipientText }}</span>
                            </div>
                        </div>
                        <div class="rx-info-row rx-info-row-full">
                            <div class="rx-info-cell">
                                <span class="rx-key">临床诊断</span>
                                <span class="rx-val">{{ slipView.clinical_diagnosis || '—' }}</span>
                            </div>
                        </div>
                    </div>

                    <!-- Rp 区域（带水印） -->
                    <div class="rx-rp">
                        <div class="rx-watermark">药房联</div>
                        <div class="rx-rp-head">
                            <div class="rx-rp-label">Rp.</div>
                            <div class="rx-rp-cols-head">
                                <div class="rx-rp-col-head">
                                    <span>用药 (单剂)</span>
                                    <span>总量</span>
                                </div>
                                <div class="rx-rp-col-head">
                                    <span>用药 (单剂)</span>
                                    <span>总量</span>
                                </div>
                            </div>
                        </div>

                        <div class="rx-herbs">
                            <template v-if="slipMainHerbs.length">
                                <div class="rx-herb-section-label">主方</div>
                                <div
                                    v-for="(h, i) in slipMainHerbs"
                                    :key="'main-' + i"
                                    class="rx-herb-cell"
                                >
                                    <span class="rx-herb-name">{{ h.name }} ({{ h.dosage }}克)</span>
                                    <span class="rx-herb-total">{{ rxHerbTotal(h.dosage) }}克</span>
                                </div>
                            </template>
                            <template v-if="slipAuxHerbs.length">
                                <div class="rx-herb-section-label rx-herb-section-label--aux">辅方</div>
                                <div
                                    v-for="(h, i) in slipAuxHerbs"
                                    :key="'aux-' + i"
                                    class="rx-herb-cell"
                                >
                                    <span class="rx-herb-name">{{ h.name }} ({{ h.dosage }}克)</span>
                                    <span class="rx-herb-total">{{ rxHerbTotal(h.dosage) }}克</span>
                                </div>
                            </template>
                        </div>
                    </div>

                    <!-- 服法 / 医嘱 / 备注 / 药房备注 / 出丸 -->
                    <div class="rx-text">
                        <p>主方服法：{{ rxUsageText }}</p>
                        <p v-if="rxAuxUsageText">辅方服法：{{ rxAuxUsageText }}</p>
                        <p v-if="rxAdviceText">医嘱：{{ rxAdviceText }}</p>
                        <p v-if="rxRemarkText">备注：{{ rxRemarkText }}</p>
                        <p v-if="rxPharmacyRemarkText" class="rx-text-warn">
                            药房备注：{{ rxPharmacyRemarkText }}
                        </p>
                        <p v-if="rxOutPelletText" class="rx-text-warn">
                            出丸：{{ rxOutPelletText }}
                        </p>
                    </div>

                    <!-- 底部表：医师/审方/配药/复核/发药 + 类型/剂数/单剂量 -->
                    <div class="rx-bottom">
                        <div class="rx-bot-row rx-bot-row-1">
                            <div class="rx-bot-cell rx-bot-stack rx-bot-doctor">
                                <div class="rx-bot-label">医师</div>
                                <div class="rx-bot-doctor-body">
                                    <img
                                        v-if="slipView.doctor_signature"
                                        :src="slipView.doctor_signature"
                                        alt="医师签名"
                                        class="rx-bot-sign-img"
                                    />
                                    <div class="rx-bot-doctor-name">{{ slipView.doctor_name || '—' }}</div>
                                </div>
                            </div>
                          <div class="rx-bot-cell rx-bot-meta">
                                <span class="rx-bot-meta-key">类型:</span>
                                <span class="rx-bot-meta-val">{{ rxTypeText }}</span>
                            </div>
                            <div class="rx-bot-cell rx-bot-meta">
                                <span class="rx-bot-meta-key">天数:</span>
                                <span class="rx-bot-meta-val">{{ slipView.dose_count || '—' }}剂</span>
                            </div>
                            <div class="rx-bot-cell rx-bot-meta">
                                <span class="rx-bot-meta-key">单剂量:</span>
                                <span class="rx-bot-meta-val">{{ rxPerDoseAmount }}克</span>
                            </div>
                        </div>
                        
                    </div>
                </div>

                <!-- 审核痕迹（不进入打印区） -->
                <div
                    v-if="slipView && (slipView.audit_by_name || slipView.audit_remark)"
                    class="rx-audit"
                >
                    <div v-if="slipView.audit_by_name">
                        审核人：{{ slipView.audit_by_name }}
                        <span v-if="slipView.audit_time" class="ml-2 text-gray-400">
                            {{ formatAuditTime(slipView.audit_time) }}
                        </span>
                    </div>
                    <div v-if="slipView.audit_remark" class="mt-1">审核意见：{{ slipView.audit_remark }}</div>
                </div>
            </div>

            <el-form
                v-else
                ref="formRef"
                :model="editForm"
                :rules="rules"
                label-width="120px"
            >
                <el-alert
                    v-if="editMode === 'edit' && Number(editForm.is_system_auto) === 1"
                    type="warning"
                    :closable="false"
                    show-icon
                    class="mb-4"
                    title="本处方为系统自动生成（如挂号完成），默认无药材配方，请补充药材与诊断等信息后再保存。"
                />
                <el-alert
                    v-if="editMode === 'edit'"
                    type="info"
                    :closable="false"
                    show-icon
                    class="mb-4"
                    title="保存修改后，该处方将重新进入「待审核」，需审核人员再次通过后方可生效。"
                />
                <el-alert
                    v-if="editMode === 'edit' && Number(editForm.audit_status) === 2"
                    type="error"
                    :closable="false"
                    show-icon
                    class="mb-4"
                >
                    <template #title>当前消费者处方为「已驳回」</template>
                    <div class="text-sm mt-1">
                        保存修改后将清除驳回并变为「待审核」。{{
                            editForm.audit_remark ? `上次意见：${editForm.audit_remark}` : ''
                        }}
                    </div>
                </el-alert>
                <el-alert
                    v-if="
                        editMode === 'edit' &&
                        Number(editForm.business_prescription_audit_rejected) === 1 &&
                        Number(editForm.audit_status) === 1
                    "
                    type="warning"
                    :closable="false"
                    show-icon
                    class="mb-4"
                >
                    <template #title>业务订单侧「处方审核」已驳回</template>
                    <div class="text-sm mt-1">
                        消费者处方仍为「已通过」；您修改并保存后，将重置关联业务订单的处方/支付单审核为「待审」，请在「处方业务订单」中继续处理。
                    </div>
                    <div
                        v-if="String(editForm.business_prescription_audit_remark || '').trim()"
                        class="text-sm mt-2 text-gray-800 font-medium"
                    >
                        驳回意见：{{ editForm.business_prescription_audit_remark }}
                    </div>
                </el-alert>
                <el-alert
                    v-if="editMode === 'edit' && editReviveHint"
                    type="warning"
                    :closable="false"
                    show-icon
                    class="mb-4"
                    :title="editReviveHint"
                />
                <div
                    v-if="Number(editForm.diagnosis_id) > 0"
                    class="mb-3 flex flex-wrap items-center gap-2 pl-[120px]"
                >
                    <el-button type="primary" size="small" @click="openDiagnosisPatientDetail">
                        查看患者诊单详情
                    </el-button>
                    <span class="text-xs text-gray-400">关联诊单 #{{ editForm.diagnosis_id }}</span>
                </div>
                <el-row :gutter="20">
                    <el-col :span="12">
                        <el-form-item label="患者姓名" prop="patient_name">
                            <el-input
                                v-model="editForm.patient_name"
                                placeholder="请输入患者姓名"
                                :disabled="editMode === 'edit'"
                            />
                        </el-form-item>
                    </el-col>
                    <el-col :span="12">
                        <el-form-item label="门诊号" prop="visit_no">
                            <el-input
                                v-model="editForm.visit_no"
                                placeholder="自动生成或手动输入"
                                :disabled="editMode === 'edit'"
                            />
                        </el-form-item>
                    </el-col>
                </el-row>
                
                <el-row :gutter="20">
                    <el-col :span="8">
                        <el-form-item label="性别" prop="gender">
                            <el-radio-group v-model="editForm.gender">
                                <el-radio :label="1">男</el-radio>
                                <el-radio :label="0">女</el-radio>
                            </el-radio-group>
                        </el-form-item>
                    </el-col>
                    <el-col :span="8">
                        <el-form-item label="年龄" prop="age">
                            <el-input-number
                                v-model="editForm.age"
                                :min="0"
                                :max="150"
                                placeholder="请输入年龄"
                                class="w-full"
                            />
                        </el-form-item>
                    </el-col>
                    <el-col :span="8">
                        <el-form-item label="处方日期" prop="prescription_date">
                            <el-date-picker
                                v-model="editForm.prescription_date"
                                type="date"
                                placeholder="选择日期"
                                format="YYYY-MM-DD"
                                value-format="YYYY-MM-DD"
                                class="w-full"
                            />
                        </el-form-item>
                    </el-col>
                </el-row>
                
                <el-row :gutter="20">
                    <el-col :span="12">
                        <el-form-item label="面象" prop="tongue">
                            <el-input v-model="editForm.tongue" placeholder="请输入面象" />
                        </el-form-item>
                    </el-col>
                    <el-col :span="12">
                        <el-form-item label="舌象" prop="tongue_image">
                            <el-input v-model="editForm.tongue_image" placeholder="请输入舌象" />
                        </el-form-item>
                    </el-col>
                </el-row>
                
                <el-row :gutter="20">
                    <el-col :span="12">
                        <el-form-item label="脉象" prop="pulse">
                            <el-input v-model="editForm.pulse" placeholder="请输入脉象" />
                        </el-form-item>
                    </el-col>
                    <el-col :span="12">
                        <el-form-item label="脉象详情" prop="pulse_condition">
                            <el-input v-model="editForm.pulse_condition" placeholder="请输入脉象详情" />
                        </el-form-item>
                    </el-col>
                </el-row>
                
                <el-form-item label="临床诊断" prop="clinical_diagnosis">
                    <el-input
                        v-model="editForm.clinical_diagnosis"
                        type="textarea"
                        :rows="3"
                        placeholder="请输入临床诊断"
                        maxlength="500"
                        show-word-limit
                    />
                </el-form-item>
                
                <el-form-item label="药材配方" prop="herbs" required>
                    <div class="w-full">
                        <div class="flex flex-wrap items-center gap-2">
                            <el-button
                                type="success"
                                size="small"
                                v-perms="['cf.prescription/add', 'cf.prescription/edit', 'tcm.prescriptionLibrary/lists']"
                                @click="openLibraryDialog"
                            >
                                从处方库导入
                            </el-button>
                            <el-button type="warning" size="small" plain :icon="EditPen" @click="openPasteRecipeDialog">
                                导入药方
                            </el-button>
                            <span class="text-xs text-gray-500">
                                粘贴文本解析药名与剂量；须与药品库名称完全一致才录入（导入至主方）
                            </span>
                        </div>

                        <div class="herb-formula-block mt-3">
                            <div class="herb-formula-block__head">
                                <el-tag type="primary" size="small">主方</el-tag>
                                <el-button type="primary" size="small" @click="addHerb('主方')">添加主方药材</el-button>
                            </div>
                            <el-table :data="mainHerbRows" class="mt-2" border empty-text="暂无主方药材">
                                <el-table-column label="序号" type="index" width="60" />
                                <el-table-column label="药材名称" min-width="220">
                                    <template #default="{ row }">
                                        <MedicineNameSelect v-model="editForm.herbs[row.index].name" class="w-full" />
                                    </template>
                                </el-table-column>
                                <el-table-column label="剂量(克)" min-width="120">
                                    <template #default="{ row }">
                                        <el-input-number
                                            v-model="editForm.herbs[row.index].dosage"
                                            :min="0"
                                            :precision="1"
                                            :step="0.5"
                                            placeholder="剂量"
                                            class="w-full"
                                        />
                                    </template>
                                </el-table-column>
                                <el-table-column label="操作" width="80">
                                    <template #default="{ row }">
                                        <el-button type="danger" link @click="removeHerb(row.index)">删除</el-button>
                                    </template>
                                </el-table-column>
                            </el-table>
                        </div>

                        <div class="herb-formula-block mt-4">
                            <div class="herb-formula-block__head">
                                <el-tag type="warning" size="small">辅方</el-tag>
                                <el-button type="primary" size="small" plain @click="addHerb('辅方')">
                                    添加辅方药材
                                </el-button>
                            </div>
                            <el-table :data="auxHerbRows" class="mt-2" border empty-text="暂无辅方药材">
                                <el-table-column label="序号" type="index" width="60" />
                                <el-table-column label="药材名称" min-width="220">
                                    <template #default="{ row }">
                                        <MedicineNameSelect v-model="editForm.herbs[row.index].name" class="w-full" />
                                    </template>
                                </el-table-column>
                                <el-table-column label="剂量(克)" min-width="120">
                                    <template #default="{ row }">
                                        <el-input-number
                                            v-model="editForm.herbs[row.index].dosage"
                                            :min="0"
                                            :precision="1"
                                            :step="0.5"
                                            placeholder="剂量"
                                            class="w-full"
                                        />
                                    </template>
                                </el-table-column>
                                <el-table-column label="操作" width="80">
                                    <template #default="{ row }">
                                        <el-button type="danger" link @click="removeHerb(row.index)">删除</el-button>
                                    </template>
                                </el-table-column>
                            </el-table>
                        </div>
                        <el-alert
                            v-if="editMode === 'edit'"
                            type="warning"
                            :closable="false"
                            show-icon
                            class="mt-3"
                            v-loading="rxLinkedOrderHint.loading"
                        >
                            <template #title>业务订单要求（请与本处方保持一致）</template>
                            <div class="text-sm mt-1 leading-relaxed">
                                <template
                                    v-if="
                                        rxLinkedOrderHint.orderNo ||
                                        rxLinkedOrderHint.medicationDays != null ||
                                        rxLinkedOrderHint.remarkAssistant
                                    "
                                >
                                    <p v-if="rxLinkedOrderHint.orderNo" class="mb-1.5">
                                        最近关联订单（按创建倒序）：
                                        <span class="font-mono text-primary">{{ rxLinkedOrderHint.orderNo }}</span>
                                    </p>
                                    <p class="mb-1.5">
                                        <span class="font-semibold">服用天数（订单）</span>：
                                        {{
                                            rxLinkedOrderHint.medicationDays != null
                                                ? `${rxLinkedOrderHint.medicationDays} 天`
                                                : '— 订单未填写'
                                        }}
                                    </p>
                                    <p>
                                        <span class="font-semibold">医助备注（订单）</span>：
                                        <span class="whitespace-pre-wrap">{{
                                            rxLinkedOrderHint.remarkAssistant || '— 无'
                                        }}</span>
                                    </p>
                                </template>
                                <p v-else-if="!rxLinkedOrderHint.loading" class="text-gray-600">
                                    当前处方暂无关联业务订单，或您无订单列表权限；若有订单，将在此处显示订单内
                                    <span class="font-semibold">服用天数</span>与
                                    <span class="font-semibold">医助备注</span>。
                                </p>
                            </div>
                        </el-alert>
                    </div>
                </el-form-item>
                
                <el-row :gutter="20">
                    <el-col :span="8">
                        <el-form-item label="剂数" prop="dose_count">
                            <el-input-number
                                v-model="editForm.dose_count"
                                :min="1"
                                placeholder="剂数"
                                class="w-full"
                            />
                        </el-form-item>
                    </el-col>
                    <el-col :span="8">
                        <el-form-item label="剂量单位" prop="dose_unit">
                            <el-select v-model="editForm.dose_unit" placeholder="请选择" class="w-full">
                                <el-option label="剂" value="剂" />
                                <el-option label="丸" value="丸" />
                                <el-option label="袋" value="袋" />
                                <el-option label="盒" value="盒" />
                                <el-option label="瓶" value="瓶" />
                                <el-option label="膏" value="膏" />
                                <el-option label="贴" value="贴" />
                            </el-select>
                        </el-form-item>
                    </el-col>
                      <el-col :span="8">
                     <el-form-item label="处方类型" prop="prescription_type">
                    <el-select v-model="editForm.prescription_type" placeholder="请选择处方类型" class="w-full">
                        <el-option label="浓缩水丸" value="浓缩水丸" />
                        <el-option label="饮片" value="饮片" />
                        <el-option label="颗粒" value="颗粒" />
                        <el-option label="丸剂" value="丸剂" />
                        <el-option label="散剂" value="散剂" />
                        <el-option label="膏方" value="膏方" />
                        <el-option label="汤剂" value="汤剂" />
                    </el-select>
                </el-form-item>  </el-col>
                </el-row>

                <div class="usage-formula-title usage-formula-title--main">主方用法</div>
                <el-row :gutter="20">
                    <el-col :span="8">
                        <el-form-item label="用量" prop="dosage_amount">
                            <!-- 浓缩水丸：1-10g 下拉选择 -->
                            <el-select
                                v-if="editForm.prescription_type === '浓缩水丸'"
                                v-model="editForm.dosage_amount"
                                placeholder="请选择用量"
                                class="w-full"
                            >
                                <el-option :label="1 + 'g'" :value="1" />
                                <el-option :label="2 + 'g'" :value="2" />
                                <el-option :label="3 + 'g'" :value="3" />
                                <el-option :label="4 + 'g'" :value="4" />
                                <el-option :label="5 + 'g'" :value="5" />
                                <el-option :label="6 + 'g'" :value="6" />
                                <el-option :label="7 + 'g'" :value="7" />
                                <el-option :label="8 + 'g'" :value="8" />
                                <el-option :label="9 + 'g'" :value="9" />
                                <el-option :label="10 + 'g'" :value="10" />
                            </el-select>
                            <!-- 饮片：50-250ml 下拉选择，步进50 -->
                            <el-select
                                v-else-if="editForm.prescription_type === '饮片'"
                                v-model="editForm.dosage_amount"
                                placeholder="请选择用量"
                                class="w-full"
                            >
                               <el-option label="50ml" :value="50" />
                                    <el-option label="100ml" :value="100" />
                                    <el-option label="120ml" :value="120" />
                                    <el-option label="150ml" :value="150" />
                                    <el-option label="180ml" :value="180" />
                                    <el-option label="200ml" :value="200" />
                                    <el-option label="250ml" :value="250" />
                            </el-select>
                            <!-- 其他类型：自由输入 -->
                            <el-input-number
                                v-else
                                v-model="editForm.dosage_amount"
                                :min="0"
                                :precision="2"
                                class="w-full"
                            />
                        </el-form-item>
                    </el-col>
                    <el-col v-if="editForm.prescription_type === '浓缩水丸'" :span="8">
                        <el-form-item label=" " prop="dosage_bag_count" label-width="12px">
                            <el-select v-model="editForm.dosage_bag_count" placeholder="请选择袋数" class="w-[120px]">
                                <el-option label="1袋" :value="1" />
                                <el-option label="2袋" :value="2" />
                                <el-option label="3袋" :value="3" />
                                <el-option label="4袋" :value="4" />
                                <el-option label="5袋" :value="5" />
                            </el-select>
                        </el-form-item>
                    </el-col>
                    
                    <!-- 饮片代煎选项 -->
                    <el-col v-if="editForm.prescription_type === '饮片'" :span="8">
                        <el-form-item label="是否代煎" prop="need_decoction">
                            <el-radio-group v-model="editForm.need_decoction">
                                <el-radio :label="true">代煎</el-radio>
                                <el-radio :label="false">不代煎</el-radio>
                            </el-radio-group>
                        </el-form-item>
                    </el-col>
                    
                    <!-- 饮片每贴出包数 -->
                    <el-col v-if="editForm.prescription_type === '饮片'" :span="8">
                        <el-form-item label="每贴出包数" prop="bags_per_dose">
                            <el-select v-model="editForm.bags_per_dose" placeholder="请选择" class="w-full">
                                <el-option label="1包" :value="1" />
                                <el-option label="2包" :value="2" />
                                <el-option label="3包" :value="3" />
                                <el-option label="4包" :value="4" />
                                <el-option label="5包" :value="5" />
                                <el-option label="6包" :value="6" />
                                <el-option label="7包" :value="7" />
                                <el-option label="8包" :value="8" />
                                <el-option label="9包" :value="9" />
                            </el-select>
                        </el-form-item>
                    </el-col>
                    
                     <el-col :span="8">
                            <el-form-item label="每天几次" prop="times_per_day">
                                <el-input-number v-model="editForm.times_per_day" :min="1" :max="6" class="!w-full" placeholder="每天服用次数" />
                            </el-form-item>
                        </el-col>
                    <el-col :span="8">
                        <el-form-item label="服用天数" prop="usage_days">
                            <el-input-number
                                v-model="editForm.usage_days"
                                :min="1"
                                :max="365"
                                placeholder="服用天数"
                                class="w-full"
                            />
                        </el-form-item>
                    </el-col>
                </el-row>

                <template v-if="auxHerbRows.length > 0">
                    <div class="usage-formula-title usage-formula-title--aux">辅方用法</div>
                    <el-row :gutter="20">
                    <el-col :span="8">
                        <el-form-item label="用量">
                            <el-select
                                v-if="editForm.prescription_type === '浓缩水丸'"
                                v-model="editForm.aux_usage.dosage_amount"
                                placeholder="请选择用量"
                                class="w-full"
                            >
                                <el-option v-for="n in 10" :key="n" :label="n + 'g'" :value="n" />
                            </el-select>
                            <el-select
                                v-else-if="editForm.prescription_type === '饮片'"
                                v-model="editForm.aux_usage.dosage_amount"
                                placeholder="请选择用量"
                                class="w-full"
                            >
                                <el-option label="50ml" :value="50" />
                                <el-option label="100ml" :value="100" />
                                <el-option label="120ml" :value="120" />
                                <el-option label="150ml" :value="150" />
                                <el-option label="180ml" :value="180" />
                                <el-option label="200ml" :value="200" />
                                <el-option label="250ml" :value="250" />
                            </el-select>
                            <el-input-number
                                v-else
                                v-model="editForm.aux_usage.dosage_amount"
                                :min="0"
                                :precision="2"
                                class="w-full"
                            />
                        </el-form-item>
                    </el-col>
                    <el-col v-if="editForm.prescription_type === '浓缩水丸'" :span="8">
                        <el-form-item label=" " label-width="12px">
                            <el-select
                                v-model="editForm.aux_usage.dosage_bag_count"
                                placeholder="请选择袋数"
                                class="w-[120px]"
                            >
                                <el-option label="1袋" :value="1" />
                                <el-option label="2袋" :value="2" />
                                <el-option label="3袋" :value="3" />
                                <el-option label="4袋" :value="4" />
                                <el-option label="5袋" :value="5" />
                            </el-select>
                        </el-form-item>
                    </el-col>
                    <el-col v-if="editForm.prescription_type === '饮片'" :span="8">
                        <el-form-item label="是否代煎">
                            <el-radio-group v-model="editForm.aux_usage.need_decoction">
                                <el-radio :label="true">代煎</el-radio>
                                <el-radio :label="false">不代煎</el-radio>
                            </el-radio-group>
                        </el-form-item>
                    </el-col>
                    <el-col v-if="editForm.prescription_type === '饮片'" :span="8">
                        <el-form-item label="每贴出包数">
                            <el-select v-model="editForm.aux_usage.bags_per_dose" placeholder="请选择" class="w-full">
                                <el-option v-for="n in 9" :key="n" :label="n + '包'" :value="n" />
                            </el-select>
                        </el-form-item>
                    </el-col>
                    <el-col :span="8">
                        <el-form-item label="每天几次">
                            <el-input-number
                                v-model="editForm.aux_usage.times_per_day"
                                :min="1"
                                :max="6"
                                class="!w-full"
                                placeholder="每天服用次数"
                            />
                        </el-form-item>
                    </el-col>
                    <el-col :span="8">
                        <el-form-item label="服用天数">
                            <el-input-number
                                v-model="editForm.aux_usage.usage_days"
                                :min="1"
                                :max="365"
                                placeholder="服用天数"
                                class="w-full"
                            />
                        </el-form-item>
                    </el-col>
                    </el-row>
                </template>
                
                <el-form-item label="用法" prop="usage_instruction">
                    <el-input
                        v-model="editForm.usage_instruction"
                        placeholder="例如：水煎服，一日二次"
                        maxlength="200"
                        show-word-limit
                    />
                </el-form-item>
                
                <el-row :gutter="20">
                    <el-col :span="12">
                        <el-form-item label="服用时间" prop="usage_time">
                            <el-select v-model="editForm.usage_time" placeholder="请选择服用时间" class="w-full">
                                <el-option label="饭前" value="饭前" />
                                <el-option label="饭后" value="饭后" />
                                <el-option label="饭中" value="饭中" />
                                <el-option label="空腹" value="空腹" />
                                <el-option label="睡前" value="睡前" />
                                <el-option label="晨起" value="晨起" />
                                <el-option label="随时" value="随时" />
                            </el-select>
                        </el-form-item>
                    </el-col>
                    <el-col :span="12">
                        <el-form-item label="服用方式" prop="usage_way">
                            <el-select v-model="editForm.usage_way" placeholder="请选择服用方式" class="w-full">
                                <el-option label="温水送服" value="温水送服" />
                                <el-option label="开水冲服" value="开水冲服" />
                                <el-option label="黄酒送服" value="黄酒送服" />
                                <el-option label="淡盐水送服" value="淡盐水送服" />
                                <el-option label="米汤送服" value="米汤送服" />
                                <el-option label="嚼服" value="嚼服" />
                                <el-option label="含化" value="含化" />
                            </el-select>
                        </el-form-item>
                    </el-col>
                </el-row>
                
                <el-form-item label="忌口" prop="dietary_taboo">
                    <el-select 
                        v-model="editForm.dietary_taboo" 
                        multiple 
                        placeholder="请选择忌口内容（可多选）" 
                        class="w-full"
                    >
                        <el-option label="辛辣食物" value="辛辣食物" />
                        <el-option label="生冷食物" value="生冷食物" />
                        <el-option label="油腻食物" value="油腻食物" />
                        <el-option label="海鲜" value="海鲜" />
                        <el-option label="牛羊肉" value="牛羊肉" />
                        <el-option label="鸡蛋" value="鸡蛋" />
                        <el-option label="豆制品" value="豆制品" />
                        <el-option label="酒类" value="酒类" />
                        <el-option label="浓茶" value="浓茶" />
                        <el-option label="咖啡" value="咖啡" />
                        <el-option label="烟草" value="烟草" />
                        <el-option label="萝卜" value="萝卜" />
                    </el-select>
                </el-form-item>
                
                <el-form-item label="其他说明" prop="usage_notes">
                    <el-input
                        v-model="editForm.usage_notes"
                        type="textarea"
                        :rows="2"
                        placeholder="其他服用注意事项"
                        maxlength="200"
                        show-word-limit
                    />
                </el-form-item>
                
                <el-form-item label="医师姓名" prop="doctor_name">
                    <el-input v-model="editForm.doctor_name" placeholder="请输入医师姓名" />
                </el-form-item>

                <el-form-item label="医师签名" prop="doctor_signature" required>
                    <div class="signature-pad-wrap">
                        <canvas
                            ref="signatureCanvasRef"
                            class="signature-canvas"
                            @pointerdown.prevent="onSignaturePointerDown"
                            @pointermove.prevent="onSignaturePointerMove"
                            @pointerup.prevent="onSignaturePointerUp"
                            @pointercancel.prevent="onSignaturePointerUp"
                        />
                        <div class="signature-actions">
                            <el-button size="small" @click="clearSignature">清空签名</el-button>
                        </div>
                    </div>
                    <div class="text-xs text-amber-600 mt-1">* 必填，请在框内手写医师签名</div>
                </el-form-item>

            </el-form>

            <template #footer>
                <template v-if="editMode === 'view'">
                    <el-button @click="showEdit = false">关闭</el-button>
                </template>
                <template v-else>
                    <el-button @click="showEdit = false">取消</el-button>
                    <el-button type="primary" @click="handleSubmit" :loading="submitLoading">
                        确定
                    </el-button>
                </template>
            </template>
        </el-drawer>

        <!-- 修正处方笺姓名 / 手机号（zyt_tcm_prescription，写入订单日志） -->
        <el-dialog
            v-model="patchPatientVisible"
            title="修正姓名、性别与手机号"
            width="440px"
            :close-on-click-modal="false"
            destroy-on-close
            @closed="resetPatchPatientForm"
        >
            <el-form
                ref="patchPatientFormRef"
                :model="patchPatientForm"
                :rules="patchPatientRules"
                label-width="88px"
            >
                <el-form-item label="处方编号">
                    <span class="text-gray-700">#{{ patchPatientForm.id || '—' }}</span>
                </el-form-item>
                <el-form-item label="患者姓名" prop="patient_name">
                    <el-input v-model="patchPatientForm.patient_name" maxlength="50" show-word-limit placeholder="处方笺展示姓名" />
                </el-form-item>
                <el-form-item label="性别" prop="gender">
                    <el-radio-group v-model="patchPatientForm.gender">
                        <el-radio :label="1">男</el-radio>
                        <el-radio :label="0">女</el-radio>
                    </el-radio-group>
                </el-form-item>
                <el-form-item label="手机号" prop="phone">
                    <el-input v-model="patchPatientForm.phone" maxlength="20" placeholder="处方笺展示手机号" />
                </el-form-item>
            </el-form>
            <p class="text-xs text-gray-500 -mt-2 mb-2">
                仅更新处方表 patient_name、gender、phone，不改变审核状态；记录写入业务订单操作日志（有关联订单时可在此订单日志中查看）。
            </p>
            <template #footer>
                <el-button @click="patchPatientVisible = false">取消</el-button>
                <el-button type="primary" :loading="patchPatientSubmitLoading" @click="submitPatchPatient">
                    保存
                </el-button>
            </template>
        </el-dialog>

        <!-- 从消费者处方创建业务订单（zyt_tcm_prescription_order，与支付单 zyt_order 分离） -->
        <el-dialog
            v-model="createOrderVisible"
            title="创建业务订单"
            width="940px"
            top="4vh"
            :close-on-click-modal="false"
            @closed="resetCreateOrderForm"
            class="create-order-dialog"
        >
            <div class="create-order-dialog__inner">
                <!-- 关联处方：卡片式信息区，层次更清晰 -->
                <div v-if="createOrderPrescription" class="create-order-rx-card">
                    <div class="create-order-rx-card__head">
                        <span class="create-order-rx-card__badge">关联处方</span>
                        <div class="create-order-rx-card__meta">
                            <span class="create-order-rx-card__id">#{{ createOrderPrescription.id }}</span>
                            <span v-if="createOrderPrescription.sn" class="create-order-rx-card__sn">{{ createOrderPrescription.sn }}</span>
                            <span class="create-order-rx-card__patient">{{ createOrderPrescription.patient_name || '—' }}</span>
                        </div>
                    </div>
                    <!-- <el-tooltip :content="createOrderHerbSummary" placement="bottom" :show-after="300">
                        <div class="create-order-rx-card__herbs">{{ createOrderHerbSummary }}</div>
                    </el-tooltip> -->
                </div>

                <el-steps
                    :active="createOrderStep"
                    finish-status="success"
                    align-center
                    class="create-order-steps"
                >
                    <el-step title="患者与收货" description="诊单与物流地址" />
                    <el-step title="服务与支付单" description="套餐与关联收款" />
                    <el-step title="金额与确认" description="费用与备注" />
                </el-steps>

                <p class="create-order-step-lead">{{ createOrderStepLead }}</p>

                <el-form
                    ref="createOrderFormRef"
                    :model="createOrderForm"
                    :rules="createOrderRules"
                    label-width="108px"
                    class="create-order-form"
                >
                <div v-show="createOrderStep === 0" class="create-order-step-panel">
                        <el-row :gutter="20">
                            <el-col :span="24">
                                <el-form-item label="诊单患者" prop="patient_id">
                                    <el-select
                                        v-model="createOrderForm.patient_id"
                                        class="w-full"
                                        placeholder="搜索姓名/手机/身份证"
                                        filterable
                                        remote
                                        :remote-method="searchPatientsForOrder"
                                        :loading="createOrderPatientLoading"
                                        @change="onCreateOrderPatientChange"
                                    >
                                        <el-option
                                            v-for="item in createOrderPatientList"
                                            :key="item.id"
                                            :label="`${item.patient_name} (${item.phone || '无手机'})`"
                                            :value="item.id"
                                        />
                                    </el-select>
                                </el-form-item>
                            </el-col>
                            <el-col :span="12">
                                <el-form-item label="收货人" prop="recipient_name">
                                    <el-input v-model="createOrderForm.recipient_name" placeholder="姓名" maxlength="50" />
                                </el-form-item>
                            </el-col>
                            <el-col :span="12">
                                <el-form-item label="收货手机" prop="recipient_phone">
                                    <el-input v-model="createOrderForm.recipient_phone" placeholder="物流联系" maxlength="20" />
                                </el-form-item>
                            </el-col>
                            <el-col :span="24">
                                <el-form-item label="省市区" prop="region">
                                    <el-cascader
                                        v-model="createOrderForm.region"
                                        :options="regionOptions"
                                        :props="{ value: 'name', label: 'name', children: 'children', emitPath: true, checkStrictly: false }"
                                        placeholder="省 / 市 / 区"
                                        clearable
                                        filterable
                                        class="w-full"
                                        @change="handleRegionChange"
                                    />
                                </el-form-item>
                            </el-col>
                            <el-col :span="24">
                                <el-form-item label="详细地址" prop="shipping_address">
                                    <el-input
                                        v-model="createOrderForm.shipping_address"
                                        type="textarea"
                                        :rows="3"
                                        placeholder="街道、小区、门牌号等详细地址"
                                        maxlength="200"
                                        show-word-limit
                                    />
                                </el-form-item>
                            </el-col>
                        </el-row>
                </div>

                <div v-show="createOrderStep === 1" class="create-order-step-panel">
                        <el-row :gutter="20">
                            <el-col :xs="24" :sm="8">
                                <el-form-item label="复诊">
                                    <el-switch v-model="createOrderForm.is_follow_up" :active-value="1" :inactive-value="0" />
                                </el-form-item>
                            </el-col>
                            <el-col :xs="24" :sm="8">
                                <el-form-item label="服用天数" class="create-order-form-item--inline-num">
                                    <div class="flex items-center gap-1 w-full">
                                        <el-input-number
                                            v-model="createOrderForm.medication_days"
                                            :min="1"
                                            :max="999"
                                            :step="1"
                                            controls-position="right"
                                            class="flex-1 min-w-0"
                                        />
                                        <span class="create-order-unit-suffix">天</span>
                                    </div>
                                </el-form-item>
                            </el-col>
                            <el-col :xs="24" :sm="8">
                                <el-form-item label="上次医生">
                                    <el-input v-model="createOrderForm.prev_staff" placeholder="可选" maxlength="100" />
                                </el-form-item>
                            </el-col>
                            <el-col :span="12">
                                <el-form-item label="服务渠道">
                                    <el-input v-model="createOrderForm.service_channel" placeholder="可选" maxlength="100" />
                                </el-form-item>
                            </el-col>
                            <el-col :span="12">
                                <el-form-item label="服务套餐">
                                    <el-select
                                        v-model="createOrderForm.service_package"
                                        multiple
                                        collapse-tags
                                        collapse-tags-tooltip
                                        placeholder="请选择服务套餐"
                                        clearable
                                        class="w-full"
                                    >
                                        <el-option
                                            v-for="item in servicePackageOptions"
                                            :key="item.value"
                                            :label="item.name"
                                            :value="item.value"
                                        />
                                    </el-select>
                                </el-form-item>
                            </el-col>
                            <el-col :span="24">
                                <el-form-item label="关联支付单" prop="pay_order_ids">
                                    <el-select
                                        v-model="createOrderForm.pay_order_ids"
                                        class="w-full"
                                        multiple
                                        collapse-tags
                                        collapse-tags-tooltip
                                        :placeholder="
                                            createOrderDepositMin > 0
                                                ? '请至少选择一笔本诊单支付单（已开启门槛）'
                                                : '多选本诊单支付单（可选）'
                                        "
                                        :loading="createOrderPaidOrdersLoading"
                                    >
                                        <el-option
                                            v-for="o in createOrderPaidOrders"
                                            :key="o.id"
                                            :label="`${o.order_no} · ¥${o.amount} · ${formatPoCategory(o.order_type)}`"
                                            :value="o.id"
                                            class="!h-auto py-1.5"
                                        >
                                            <div class="flex flex-col gap-0.5" style="line-height: normal;">
                                                <div class="flex items-center justify-between">
                                                    <span class="font-medium text-[13px] text-gray-800">{{ o.order_no }}</span>
                                                    <span class="text-orange-500 font-medium ml-4">¥{{ o.amount }}</span>
                                                </div>
                                                <div class="flex items-center justify-between text-xs text-gray-400 mt-1">
                                                    <span class="truncate pr-2">{{ formatPoCategory(o.order_type) }}<template v-if="o.remark"> · {{ o.remark }}</template></span>
                                                    <span class="shrink-0">{{ String(o.create_time || '').substring(0, 16) }}</span>
                                                </div>
                                            </div>
                                        </el-option>
                                    </el-select>
                                    <div class="create-order-pay-hint text-gray-500">
                                        <template v-if="createOrderDepositMin > 0">
                                            <span class="text-amber-600 font-medium">当前已开启关联支付门槛（¥{{ formatPoDepositMoney(createOrderDepositMin) }}），须至少选择一笔支付单。</span>
                                            <span class="mx-1"> </span>
                                        </template>
                                        主管/本诊单医助可见全部支付单；否则仅本人收款单。已被占用的支付单不列出。
                                        <el-tooltip
                                            content="主管或本诊单医助可见该诊单全部支付单（待支付/已支付），否则仅本人创建的收款单。已被其他有效业务订单占用的支付单不会出现在此列表。"
                                            placement="top"
                                        >
                                            <span class="text-primary cursor-help ml-0.5">详情</span>
                                        </el-tooltip>
                                    </div>
                                </el-form-item>
                            </el-col>
                        </el-row>
                </div>

                <div v-show="createOrderStep === 2" class="create-order-step-panel">
                        <!-- 横向概览，一屏内更省高度 -->
                        <div
                            class="create-order-deposit-bar"
                            :class="createOrderLinkedPaidTotal >= createOrderDepositMin ? 'is-ok' : 'is-warn'"
                        >
                            <div class="create-order-deposit-bar__cell">
                                <span class="create-order-deposit-bar__label">定金门槛</span>
                                <strong>¥{{ formatPoDepositMoney(createOrderDepositMin) }}</strong>
                                <span class="create-order-deposit-bar__sub">{{ createOrderDepositMin > 0 ? '须 ≥ 此值' : '未设置' }}</span>
                            </div>
                            <div class="create-order-deposit-bar__sep" />
                            <div class="create-order-deposit-bar__cell">
                                <span class="create-order-deposit-bar__label">已选收款</span>
                                <strong>¥{{ formatPoDepositMoney(createOrderLinkedPaidTotal) }}</strong>
                                <span class="create-order-deposit-bar__sub">
                                    {{ createOrderLinkedPaidTotal >= createOrderDepositMin ? '已达标' : '未达标' }}
                                </span>
                            </div>
                        </div>

                        <el-row :gutter="20" class="create-order-step-panel__row-after-bar">
                            <el-col :span="12">
                                <el-form-item label="费用类别" prop="fee_type">
                                    <el-select v-model="createOrderForm.fee_type" placeholder="请选择" class="w-full">
                                        <el-option label="挂号费" :value="1" />
                                        <el-option label="问诊费" :value="2" />
                                        <el-option label="药品费用" :value="3" />
                                        <el-option label="首付费用" :value="4" />
                                        <el-option label="尾款费用" :value="5" />
                                        <el-option label="其他费用" :value="6" />
                                        <el-option label="全部费用" :value="7" />
                                        <el-option label="驼奶费用" :value="8" />
                                    </el-select>
                                </el-form-item>
                            </el-col>
                            <el-col :span="12">
                                <el-form-item label="总金额" prop="amount">
                                    <el-input-number
                                        v-model="createOrderForm.amount"
                                        :min="createOrderAmountInputMin"
                                        :step="0.01"
                                        :precision="2"
                                        class="w-full"
                                        controls-position="right"
                                        placeholder="元"
                                    />
                                </el-form-item>
                            </el-col>
                            <el-col v-perms="['finance.account_log/lists']" :span="12">
                                <el-form-item label="内部成本">
                                    <el-input-number
                                        v-model="createOrderForm.internal_cost"
                                        :min="0"
                                        :step="0.01"
                                        :precision="2"
                                        class="w-full"
                                        controls-position="right"
                                        placeholder="财务可见"
                                    />
                                </el-form-item>
                            </el-col>
                            <el-col :span="24">
                                <el-form-item v-perms="['tcm.prescriptionOrder/editRemarkExtra']" label="药房备注">
                                    <el-input
                                        v-model="createOrderForm.remark_extra"
                                        type="textarea"
                                        :rows="3"
                                        placeholder="选填，对内说明"
                                        maxlength="200"
                                        show-word-limit
                                    />
                                </el-form-item>
                                <el-form-item label="医助备注">
                                    <el-input
                                        v-model="createOrderForm.remark_assistant"
                                        type="textarea"
                                        :rows="3"
                                        placeholder="选填，医助对内说明"
                                        maxlength="500"
                                        show-word-limit
                                    />
                                </el-form-item>
                            </el-col>
                        </el-row>
                </div>
            </el-form>
            </div>

            <template #footer>
                <div class="create-order-footer">
                    <div class="create-order-footer__hint">
                        <span class="create-order-footer__step">第 {{ createOrderStep + 1 }} / 3 步</span>
                        <span v-if="createOrderStep === 2 && createOrderDepositMin > 0" class="create-order-footer__warn">
                            订单金额与关联支付单合计须 ≥ ¥{{ formatPoDepositMoney(createOrderDepositMin) }}
                        </span>
                    </div>
                    <div class="create-order-footer__actions">
                        <el-button size="large" @click="createOrderVisible = false">取消</el-button>
                        <el-button v-if="createOrderStep > 0" size="large" @click="goCreateOrderPrevStep">上一步</el-button>
                        <el-button
                            v-if="createOrderStep < 2"
                            type="primary"
                            size="large"
                            @click="goCreateOrderNextStep"
                        >
                            下一步
                        </el-button>
                        <el-button
                            v-if="createOrderStep === 2"
                            type="primary"
                            size="large"
                            :loading="createOrderSubmitLoading"
                            @click="submitCreateOrderFromPrescription"
                        >
                            创建业务订单
                        </el-button>
                    </div>
                </div>
            </template>
        </el-dialog>

        <!-- 从处方库导入：当前开方医师的全部模板 + 所有人可见的公共模板 -->
        <el-dialog
            v-model="showLibraryDialog"
            title="从处方库导入"
            width="800px"
            :close-on-click-modal="false"
        >
            <div class="mb-4 flex gap-3">
                <el-input
                    v-model="librarySearchName"
                    class="flex-1"
                    placeholder="请输入处方名称搜索"
                    clearable
                    @keyup.enter="searchLibrary"
                    @clear="searchLibrary"
                >
                    <template #append>
                        <el-button :icon="Search" @click="searchLibrary" />
                    </template>
                </el-input>
                <el-select
                    v-model="librarySearchFormulaType"
                    placeholder="处方类型"
                    clearable
                    class="w-[140px]"
                    @change="searchLibrary"
                >
                    <el-option label="全部" value="" />
                    <el-option label="主方" value="主方" />
                    <el-option label="辅方" value="辅方" />
                </el-select>
            </div>
            <div class="mb-3 flex flex-wrap items-center gap-x-4 gap-y-2">
                <span class="text-sm text-gray-600 shrink-0">导入方式</span>
                <el-radio-group v-model="libraryImportMode">
                    <el-radio label="replace">覆盖现有药材</el-radio>
                    <el-radio label="append">追加到末尾</el-radio>
                </el-radio-group>
            </div>

            <el-table
                v-loading="libraryLoading"
                :data="libraryList"
                height="400"
                style="cursor: pointer"
                @row-click="handleSelectLibraryRow"
            >
                <el-table-column label="处方名称" prop="prescription_name" min-width="150" show-overflow-tooltip />
                <el-table-column label="处方类型" width="90">
                    <template #default="{ row }">
                        <el-tag :type="row.formula_type === '辅方' ? 'warning' : 'primary'" size="small">
                            {{ row.formula_type || '主方' }}
                        </el-tag>
                    </template>
                </el-table-column>
                <el-table-column label="药材数量" width="100">
                    <template #default="{ row }">
                        {{ row.herbs?.length || 0 }}味
                    </template>
                </el-table-column>
                <el-table-column label="药材明细" min-width="300" show-overflow-tooltip>
                    <template #default="{ row }">
                        <span v-if="row.herbs && row.herbs.length > 0">
                            {{ row.herbs.map((h: any) => `${h.name} ${h.dosage}g`).join('、') }}
                        </span>
                        <span v-else class="text-gray-400">暂无药材</span>
                    </template>
                </el-table-column>
                <el-table-column label="是否公开" width="110">
                    <template #default="{ row }">
                        <el-tag :type="row.is_public ? 'success' : 'info'" size="small">
                            {{ row.is_public ? '所有人可见' : '仅自己可见' }}
                        </el-tag>
                    </template>
                </el-table-column>
                <el-table-column label="创建人" prop="creator_name" width="100" />
                <el-table-column label="操作" width="100" fixed="right">
                    <template #default="{ row }">
                        <el-button type="primary" link @click.stop="handleImportLibrary(row)">导入</el-button>
                    </template>
                </el-table-column>
            </el-table>

            <div class="flex justify-end mt-4">
                <el-pagination
                    v-model:current-page="libraryPage"
                    v-model:page-size="libraryPageSize"
                    :total="libraryTotal"
                    :page-sizes="[10, 15, 20, 50]"
                    layout="total, sizes, prev, pager, next"
                    @current-change="loadLibraryList"
                    @size-change="loadLibraryList"
                />
            </div>
        </el-dialog>

        <!-- 粘贴药方文本导入（与诊间 tcm-prescription 逻辑一致：药品库完全同名才录入） -->
        <el-dialog
            v-model="showPasteRecipeDialog"
            title="导入药方（识别药材）"
            width="560px"
            :close-on-click-modal="false"
            destroy-on-close
            @closed="pasteRecipeText = ''"
        >
            <p class="text-gray-500 text-sm mb-2 leading-relaxed">
                粘贴整张药方文本，系统按「药名 + 剂量」解析；药名须与药品库中名称完全一致才会录入，否则跳过。支持顿号/逗号/换行分隔；单行可用空格分味（如「黄芪15g
                白术10g」）；「黄芪、党参各10克」等同剂量写法亦可识别。
            </p>
            <el-input
                v-model="pasteRecipeText"
                type="textarea"
                :rows="10"
                placeholder="示例：&#10;黄芪15 党参12 茯苓10&#10;柴胡10g、黄芩10、半夏12克&#10;黄芪、白术、茯苓各15克"
            />
            <div class="mt-3 flex flex-wrap items-center gap-x-4 gap-y-2">
                <span class="text-sm text-gray-600 shrink-0">导入方式</span>
                <el-radio-group v-model="pasteRecipeImportMode">
                    <el-radio label="replace">覆盖现有药材</el-radio>
                    <el-radio label="append">追加到末尾</el-radio>
                </el-radio-group>
            </div>
            <template #footer>
                <el-button @click="showPasteRecipeDialog = false">取消</el-button>
                <el-button type="primary" :loading="pasteRecipeImportLoading" @click="handlePasteRecipeImport">
                    识别并导入
                </el-button>
            </template>
        </el-dialog>

        <el-dialog v-model="auditDialogVisible" title="处方审核" width="480px" destroy-on-close @closed="auditRemark = ''">
            <p class="text-sm text-gray-600 mb-3">
                通过：处方保持有效。驳回：将同时作废此处方（与诊间「驳回/作废处方」一致）。
            </p>
            <el-form label-width="80px">
                <el-form-item label="审核意见">
                    <el-input
                        v-model="auditRemark"
                        type="textarea"
                        :rows="3"
                        maxlength="500"
                        show-word-limit
                        placeholder="通过可简要说明；驳回必填"
                    />
                </el-form-item>
            </el-form>
            <template #footer>
                <el-button @click="auditDialogVisible = false">取消</el-button>
                <el-button type="primary" :loading="auditLoading" @click="submitAudit('approve')">审核通过</el-button>
                <el-button type="danger" :loading="auditLoading" @click="submitAudit('reject')">驳回处方</el-button>
            </template>
        </el-dialog>

        <!-- 与 tcm/diagnosis/edit 同一套诊单界面（只读 + 全部分页签） -->
        <TcmDiagnosisEditView ref="diagnosisViewRef" />
    </div>
</template>

<script lang="ts" setup name="prescriptionList">
import {
    prescriptionLists,
    prescriptionAdd,
    prescriptionEdit,
    prescriptionPatchPatient,
    prescriptionDelete,
    prescriptionAudit,
    prescriptionDetail,
    prescriptionOrderCreate,
    prescriptionOrderPaidPayOrders,
    prescriptionOrderLists,
    getDoctors,
    prescriptionLibraryLists
} from '@/api/tcm'
import { medicineLists } from '@/api/medicine'
import { getDictData } from '@/api/app'
import { roleAll } from '@/api/perms/role'
import { usePaging } from '@/hooks/usePaging'
import useUserStore from '@/stores/modules/user'
import feedback from '@/utils/feedback'
import type { FormInstance, FormRules } from 'element-plus'
import DaterangePicker from '@/components/daterange-picker/index.vue'
import MedicineNameSelect from '@/components/medicine-name-select/index.vue'
import { Search, Download, Printer, EditPen } from '@element-plus/icons-vue'
import { computed, onMounted, reactive, ref, watch, nextTick, defineAsyncComponent } from 'vue'
import { useRouter } from 'vue-router'
import html2canvas from 'html2canvas'
import jsPDF from 'jspdf'

const TcmDiagnosisEditView = defineAsyncComponent(() => import('@/views/tcm/diagnosis/edit.vue'))

type FormulaType = '主方' | '辅方'
type HerbRow = { name: string; dosage: number; formula_type: FormulaType }

type AuxUsageForm = {
    dosage_amount?: number
    dosage_bag_count: number
    need_decoction: boolean
    bags_per_dose: number
    times_per_day: number
    usage_days: number
}

function defaultAuxUsage(prescriptionType = '浓缩水丸'): AuxUsageForm {
    if (prescriptionType === '饮片') {
        return {
            dosage_amount: 50,
            dosage_bag_count: 1,
            need_decoction: false,
            bags_per_dose: 1,
            times_per_day: 3,
            usage_days: 7
        }
    }
    if (prescriptionType === '浓缩水丸') {
        return {
            dosage_amount: 5,
            dosage_bag_count: 1,
            need_decoction: false,
            bags_per_dose: 1,
            times_per_day: 3,
            usage_days: 7
        }
    }
    return {
        dosage_amount: 1,
        dosage_bag_count: 1,
        need_decoction: false,
        bags_per_dose: 1,
        times_per_day: 3,
        usage_days: 7
    }
}

function normalizeAuxUsageForm(raw: unknown, prescriptionType: string): AuxUsageForm {
    const base = defaultAuxUsage(prescriptionType)
    if (!raw || typeof raw !== 'object') return { ...base }
    const o = raw as Record<string, unknown>
    return {
        dosage_amount:
            o.dosage_amount !== null && o.dosage_amount !== undefined && o.dosage_amount !== ''
                ? Number(o.dosage_amount)
                : base.dosage_amount,
        dosage_bag_count: o.dosage_bag_count != null ? Number(o.dosage_bag_count) || 1 : base.dosage_bag_count,
        need_decoction: o.need_decoction === 1 || o.need_decoction === true,
        bags_per_dose: o.bags_per_dose != null ? Number(o.bags_per_dose) || 1 : base.bags_per_dose,
        times_per_day: o.times_per_day != null ? Number(o.times_per_day) || 3 : base.times_per_day,
        usage_days: o.usage_days != null ? Number(o.usage_days) || 7 : base.usage_days
    }
}

function buildUsageSegmentText(
    usage: {
        prescription_type?: string
        dosage_amount?: number | null
        dosage_unit?: string
        dosage_bag_count?: number
        times_per_day?: number
        usage_way?: string
        usage_time?: string
    },
    fallbackWay?: string,
    fallbackTime?: string
): string {
    const pt = usage.prescription_type || '浓缩水丸'
    const times = Number(usage.times_per_day) > 0 ? Number(usage.times_per_day) : 3
    const amount = usage.dosage_amount != null ? Number(usage.dosage_amount) : 10
    const unit = usage.dosage_unit || (pt === '饮片' ? 'ml' : 'g')
    const usageWay = usage.usage_way || fallbackWay || '温水送服'
    const usageTime = usage.usage_time || fallbackTime || ''
    const seg: string[] = []
    seg.push(`每天${times}次`)
    if (pt === '浓缩水丸') {
        const bags = Number(usage.dosage_bag_count) > 0 ? Number(usage.dosage_bag_count) : 1
        seg.push(`一次${bags}袋`)
        seg.push(`每袋${amount}${unit}`)
    } else {
        seg.push(`一次${amount}${unit}`)
    }
    seg.push(usageWay)
    if (usageTime) seg.push(usageTime)
    return seg.join(', ')
}

function normalizeFormulaType(v: unknown): FormulaType {
    return v === '辅方' ? '辅方' : '主方'
}

function normalizeHerbRow(raw: any): HerbRow {
    return {
        name: String(raw?.name ?? '').trim(),
        dosage: Number(raw?.dosage) || 0,
        formula_type: normalizeFormulaType(raw?.formula_type)
    }
}

function normalizeSlipHerbs(raw: unknown): HerbRow[] {
    if (!raw) return []
    if (Array.isArray(raw)) {
        return raw.map((x: any) => normalizeHerbRow(x))
    }
    return []
}

/** 与 server/config/project.php prescription_audit_roles 保持一致 */
const PRESCRIPTION_AUDIT_ROLE_IDS = [0, 3]

/** 处方笺抬头/页脚（与诊间打印一致） */
const SLIP_HOSPITAL_NAME = '成都双流甄养堂互联网医院'
const SLIP_COMPANY_LINE = '成都双流甄养堂互联网医院有限公司 联系方式：4001667339'
const SLIP_ADDRESS_LINE = '地址：四川省成都市双流区黄甲街道黄龙大道二段280号'

const userStore = useUserStore()
const router = useRouter()

function goBusinessOrderList() {
    const hit = router.getRoutes().find((r) => r.meta?.perms === 'tcm.prescriptionOrder/lists')
    if (hit?.path) {
        router.push(hit.path)
    } else {
        feedback.msgWarning('未配置「处方业务订单」菜单，请在权限管理中执行菜单 SQL 或手动添加路由')
    }
}

// 表单数据（与列表接口查询参数一致）
const formData = reactive({
    /** 处方编号（后台 sn，模糊匹配） */
    sn: '',
    patient_name: '',
    /** 处方创建人（医师账号 ID），多选 */
    creator_ids: [] as number[],
    /** all | passed | not_passed | pending | rejected（all 表示不限，接口传参会转为空） */
    audit_filter: 'all' as string,
    /** all | manual | system — 与 is_system_auto：手工(0) / 系统代开(1) */
    source_filter: 'all' as string,
    start_time: '',
    end_time: ''
})

const doctorOptions = ref<Array<{ id: number; name: string; account?: string }>>([])

/** 创建时间快捷：all | today | yesterday | before_yesterday | custom | '' */
const dateQuickTab = ref<string>('all')

const showEdit = ref(false)
const editMode = ref<'add' | 'edit' | 'view'>('add')
const submitLoading = ref(false)
const formRef = ref<FormInstance>()
const signatureCanvasRef = ref<HTMLCanvasElement>()
/** 当前一笔的 pointerId（配合 setPointerCapture，移出画布仍跟手） */
const signatureActivePointerId = ref<number | null>(null)
/** 签名板 CSS 像素尺寸（内部分辨率按 DPR 放大，触摸更跟手） */
const SIGNATURE_CSS_W = 560
const SIGNATURE_CSS_H = 168
/** 查看模式：处方笺数据源（先列表行，再详情覆盖） */
const slipView = ref<Record<string, any> | null>(null)
const viewDetailLoading = ref(false)

const roleOptions = ref<Array<{ id: number; name: string }>>([])

const auditDialogVisible = ref(false)
const auditTargetId = ref(0)
const auditRemark = ref('')
const auditLoading = ref(false)

/** 修正处方笺显示用姓名 / 手机号 */
const patchPatientVisible = ref(false)
const patchPatientSubmitLoading = ref(false)
const patchPatientFormRef = ref<FormInstance>()
const patchPatientForm = reactive({
    id: 0,
    patient_name: '',
    gender: 1 as 0 | 1,
    phone: ''
})
const patchPatientRules: FormRules = {
    patient_name: [{ required: true, message: '请输入患者姓名', trigger: 'blur' }],
    gender: [{ required: true, message: '请选择性别', trigger: 'change' }],
    phone: [{ required: true, message: '请输入手机号', trigger: 'blur' }]
}

function openPatchPatientDialog(row: Record<string, unknown>) {
    patchPatientForm.id = Number(row.id) || 0
    patchPatientForm.patient_name = String(row.patient_name ?? '').trim()
    const g = Number(row.gender)
    patchPatientForm.gender = g === 0 || g === 1 ? (g as 0 | 1) : 1
    patchPatientForm.phone = String(row.phone ?? '').trim()
    patchPatientVisible.value = true
}

function resetPatchPatientForm() {
    patchPatientForm.id = 0
    patchPatientForm.patient_name = ''
    patchPatientForm.gender = 1
    patchPatientForm.phone = ''
    patchPatientFormRef.value?.clearValidate()
}

async function submitPatchPatient() {
    const form = patchPatientFormRef.value
    if (!form) return
    try {
        await form.validate()
    } catch {
        return
    }
    patchPatientSubmitLoading.value = true
    try {
        await prescriptionPatchPatient({
            id: patchPatientForm.id,
            patient_name: patchPatientForm.patient_name.trim(),
            phone: patchPatientForm.phone.trim(),
            gender: patchPatientForm.gender
        })
        feedback.msgSuccess('已保存')
        patchPatientVisible.value = false
        getLists()
    } catch (e: unknown) {
        const msg = e && typeof e === 'object' && 'msg' in e ? String((e as { msg?: string }).msg) : ''
        feedback.msgError(msg || '保存失败')
    } finally {
        patchPatientSubmitLoading.value = false
    }
}

/** 从消费者处方创建订单 */
const createOrderVisible = ref(false)
/** 创建订单分步向导：0 患者与收货 / 1 服务与支付单 / 2 金额与确认 */
const createOrderStep = ref(0)

const createOrderStepLead = computed(() => {
    const texts = [
        '请核对诊单患者并填写完整收货信息，便于发货与物流联系。',
        '按需填写服务相关信息，并选择本诊单下需要关联的支付单。',
        '确认费用类别与订单金额；提交前请对照定金门槛是否已满足。'
    ]
    return texts[createOrderStep.value] ?? ''
})

/** 第 1 步：患者与收货（分步校验） */
const CREATE_ORDER_STEP0_FIELDS = ['patient_id', 'recipient_name', 'recipient_phone', 'region', 'shipping_address'] as const

const createOrderPrescription = ref<any>(null)
const createOrderFormRef = ref<FormInstance>()
const createOrderSubmitLoading = ref(false)
const createOrderPatientLoading = ref(false)
const createOrderPatientList = ref<any[]>([])
const createOrderPaidOrders = ref<Array<{ id: number; order_no?: string; amount?: number | string; order_type?: number | string; remark?: string; create_time?: string }>>([])
const createOrderPaidOrdersLoading = ref(false)
const createOrderDepositMin = ref(0)

function formatPoDepositMoney(v: unknown) {
    const n = Number(v)
    if (Number.isNaN(n)) return '—'
    return n.toFixed(2)
}

function formatPoCategory(t: unknown) {
    const m: Record<number, string> = {
        1: '挂号费',
        2: '问诊费',
        3: '药品费用',
        4: '首付',
        5: '尾款',
        6: '其他'
    }
    return m[Number(t)] || '未知'
}

const createOrderForm = reactive({
    patient_id: '' as number | string,
    recipient_name: '',
    recipient_phone: '',
    region: [] as string[],
    shipping_address: '',
    is_follow_up: 0,
    medication_days: undefined as number | undefined,
    prev_staff: '',
    service_channel: '',
    service_package: [] as string[],
    express_company: 'auto',
    tracking_number: '',
    fee_type: 3,
    amount: 0,
    internal_cost: undefined as number | undefined,
    remark_extra: '',
    remark_assistant: '',
    pay_order_ids: [] as number[]
})

// 省市区数据（简化版，实际项目中应该从 API 获取或使用完整的省市区数据）
const regionOptions = ref([])

/** 服务套餐（字典 server_order，与业务订单编辑一致） */
const servicePackageOptions = ref<Array<{ name: string; value: string }>>([])

// 转换省市区数据格式
const transformRegionData = (data: any[]) => {
    return data.map((province: any) => ({
        name: province.province,
        code: province.code,
        children: province.citys?.map((city: any) => ({
            name: city.city,
            code: city.code,
            children: city.areas?.map((area: any) => ({
                name: area.area,
                code: area.code
            })) || []
        })) || []
    }))
}

// 加载省市区数据
const loadRegionData = async () => {
    try {
        console.log('开始加载省市区数据...')
        // 开发环境使用代理，生产环境使用环境变量中的基础URL
        const apiUrl = import.meta.env.DEV 
            ? '/api-proxy/area/ChinaCitys.json'
            : `https://cos.zhenyangtang.com.cn/area/ChinaCitys.json`
        
        const response = await fetch(apiUrl)
        console.log('响应状态:', response.status)
        
        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`)
        }
        
        const data = await response.json()
        console.log('加载的数据条数:', data?.length)
        
        // 转换数据格式
        regionOptions.value = transformRegionData(data)
        console.log('regionOptions 已设置，条数:', regionOptions.value.length)
    } catch (error) {
        console.error('加载省市区数据失败:', error)
        // 如果加载失败，使用基本的省市数据作为后备
        regionOptions.value = [
            {
                name: '四川省',
                children: [
                    {
                        name: '成都市',
                        children: [
                            { name: '锦江区' },
                            { name: '青羊区' },
                            { name: '金牛区' },
                            { name: '武侯区' },
                            { name: '成华区' },
                            { name: '龙泉驿区' },
                            { name: '青白江区' },
                            { name: '新都区' },
                            { name: '温江区' },
                            { name: '双流区' }
                        ]
                    },
                    {
                        name: '绵阳市',
                        children: [
                            { name: '涪城区' },
                            { name: '游仙区' },
                            { name: '安州区' }
                        ]
                    }
                ]
            },
            {
                name: '北京市',
                children: [
                    {
                        name: '北京市',
                        children: [
                            { name: '东城区' },
                            { name: '西城区' },
                            { name: '朝阳区' },
                            { name: '丰台区' },
                            { name: '海淀区' }
                        ]
                    }
                ]
            },
            {
                name: '上海市',
                children: [
                    {
                        name: '上海市',
                        children: [
                            { name: '黄浦区' },
                            { name: '徐汇区' },
                            { name: '长宁区' },
                            { name: '静安区' },
                            { name: '普陀区' }
                        ]
                    }
                ]
            },
            {
                name: '广东省',
                children: [
                    {
                        name: '广州市',
                        children: [
                            { name: '荔湾区' },
                            { name: '越秀区' },
                            { name: '海珠区' },
                            { name: '天河区' },
                            { name: '白云区' }
                        ]
                    },
                    {
                        name: '深圳市',
                        children: [
                            { name: '罗湖区' },
                            { name: '福田区' },
                            { name: '南山区' },
                            { name: '宝安区' }
                        ]
                    }
                ]
            }
        ]
        console.log('使用后备数据，条数:', regionOptions.value.length)
    }
}

const loadServicePackageOptions = async () => {
    try {
        const data = await getDictData({ type: 'server_order' })
        servicePackageOptions.value = (data?.server_order || []).filter((item: { status?: number }) => item.status !== 0)
    } catch {
        servicePackageOptions.value = []
    }
}

// 处理省市区选择变化
const handleRegionChange = (value: string[]) => {
    console.log('选择的省市区：', value)
    // value is an array like ['四川省', '成都市', '锦江区']
    // We'll extract these in the submit function
}

const createOrderLinkedPaidTotal = computed(() => {
    const ids = new Set(createOrderForm.pay_order_ids.map((x) => Number(x)))
    let s = 0
    for (const o of createOrderPaidOrders.value) {
        if (ids.has(Number(o.id))) {
            s += Number(o.amount) || 0
        }
    }
    return Math.round(s * 100) / 100
})

const createOrderAmountInputMin = computed(() => {
    const m = createOrderDepositMin.value
    if (m > 0) {
        return Math.round(m * 100) / 100
    }
    return 0
})

const createOrderRules = computed<FormRules>(() => {
    const rules: FormRules = {
        patient_id: [{ required: true, message: '请选择诊单患者', trigger: 'change' }],
        recipient_name: [{ required: true, message: '请输入收货人', trigger: 'blur' }],
        recipient_phone: [{ required: true, message: '请输入收货手机', trigger: 'blur' }],
        region: [{ required: true, message: '请选择省/市/区', trigger: 'change', type: 'array' }],
        shipping_address: [{ required: true, message: '请输入收货地址', trigger: 'blur' }],
        fee_type: [{ required: true, message: '请选择费用类别', trigger: 'change' }],
        amount: [
            { required: true, message: '请输入订单金额', trigger: 'blur' },
            {
                validator: (_rule, v, cb) => {
                    const min = createOrderDepositMin.value
                    const num = Number(v)
                    if (min > 0 && (!Number.isFinite(num) || num < min)) {
                        cb(new Error(`订单金额须大于等于定金门槛 ¥${formatPoDepositMoney(min)}`))
                        return
                    }
                    cb()
                },
                trigger: 'blur'
            }
        ]
    }
    // 与 .env PRESCRIPTION_ORDER_LINK_PAY_MIN_AMOUNT 一致（接口 deposit_min_amount）
    // 勿在 el-form-item 上设 required，否则会多出一条默认英文「pay_order_ids is required」
    if (createOrderDepositMin.value > 0) {
        const depMsg = `已开启关联支付门槛（¥${formatPoDepositMoney(createOrderDepositMin.value)}），请至少选择一笔支付单`
        rules.pay_order_ids = [
            {
                type: 'array',
                required: true,
                min: 1,
                message: depMsg,
                trigger: 'change'
            }
        ]
    }
    return rules
})

const createOrderHerbSummary = computed(() => {
    const row = createOrderPrescription.value
    const herbs = normalizeSlipHerbs(row?.herbs)
    if (!herbs.length) return '暂无药材明细'
    const main = herbs.filter((h) => normalizeFormulaType(h.formula_type) === '主方')
    const aux = herbs.filter((h) => normalizeFormulaType(h.formula_type) === '辅方')
    const fmt = (list: HerbRow[]) => list.map((h) => `${h.name} ${h.dosage}g`).join('、')
    const parts: string[] = []
    if (main.length) parts.push(`主方：${fmt(main)}`)
    if (aux.length) parts.push(`辅方：${fmt(aux)}`)
    const s = parts.join('；')
    return s.length > 120 ? `${s.slice(0, 120)}…` : s
})

function resetCreateOrderForm() {
    createOrderStep.value = 0
    createOrderForm.patient_id = ''
    createOrderForm.recipient_name = ''
    createOrderForm.recipient_phone = ''
    createOrderForm.shipping_address = ''
    createOrderForm.is_follow_up = 0
    createOrderForm.medication_days = undefined
    createOrderForm.prev_staff = ''
    createOrderForm.service_channel = ''
    createOrderForm.service_package = []
    createOrderForm.express_company = 'auto'
    createOrderForm.tracking_number = ''
    createOrderForm.fee_type = 3
    createOrderForm.amount = 0
    createOrderForm.internal_cost = undefined
    createOrderForm.remark_extra = ''
    createOrderForm.remark_assistant = ''
    createOrderForm.pay_order_ids = []
    createOrderPatientList.value = []
    createOrderPaidOrders.value = []
    createOrderDepositMin.value = 0
    createOrderPrescription.value = null
    createOrderFormRef.value?.clearValidate()
}

/** 仅按定金门槛抬升「总金额」，不跟已选支付单合计联动（由用户自填） */
function syncCreateOrderAmountFromRules() {
    const min = createOrderDepositMin.value
    if (min <= 0) return
    const need = Math.round(min * 100) / 100
    if (Number(createOrderForm.amount) < need) {
        createOrderForm.amount = need
    }
}

async function loadCreateOrderPaidOrders() {
    const did = Number(createOrderForm.patient_id)
    if (!did) {
        createOrderPaidOrders.value = []
        createOrderDepositMin.value = 0
        return
    }
    try {
        createOrderPaidOrdersLoading.value = true
        const res: any = await prescriptionOrderPaidPayOrders({
            diagnosis_id: did
        })
        const lists = res?.lists ?? res?.data?.lists ?? []
        createOrderPaidOrders.value = Array.isArray(lists) ? lists : []
        const dep = Number(res?.deposit_min_amount ?? res?.data?.deposit_min_amount) || 0
        createOrderDepositMin.value = dep
        syncCreateOrderAmountFromRules()
    } catch {
        createOrderPaidOrders.value = []
        createOrderDepositMin.value = 0
    } finally {
        createOrderPaidOrdersLoading.value = false
    }
}

watch(
    () => createOrderForm.patient_id,
    () => {
        createOrderForm.pay_order_ids = []
        void loadCreateOrderPaidOrders()
    }
)

async function openCreateOrderFromPrescription(row: any) {
    if (Number(row?.void_status) === 1) {
        feedback.msgWarning('已作废处方不可创建业务订单')
        return
    }
    resetCreateOrderForm()
    createOrderPrescription.value = row
    const did = Number(row.diagnosis_id) || 0
    if (did > 0) {
        createOrderForm.patient_id = did
        createOrderForm.recipient_name = row.patient_name || ''
        createOrderForm.recipient_phone = String(row.phone || '').trim()
        createOrderPatientList.value = [
            {
                id: did,
                patient_name: row.patient_name || '',
                phone: String(row.phone || '').trim()
            }
        ]
    }
    const ud = Number(row.usage_days)
    if (ud > 0) {
        createOrderForm.medication_days = ud
    }
    createOrderVisible.value = true
    void loadCreateOrderPaidOrders()
    const rxId = row.id
    if (rxId && !createOrderForm.recipient_phone) {
        try {
            const d = (await prescriptionDetail({ id: rxId })) as Record<string, unknown> | null
            const phone = d && typeof d.phone === 'string' ? d.phone.trim() : ''
            if (phone && createOrderPrescription.value?.id === rxId) {
                createOrderForm.recipient_phone = phone
                const first = createOrderPatientList.value[0]
                if (first && Number(first.id) === did) {
                    first.phone = phone
                }
            }
        } catch {
            /* 列表无电话时尽力补全，失败忽略 */
        }
    }
}

async function searchPatientsForOrder(query: string) {
    if (!query) {
        createOrderPatientList.value = []
        return
    }
    try {
        createOrderPatientLoading.value = true
        const res: any = await searchPatientsAPI({
            keyword: query,
            page_no: 1,
            page_size: 10
        })
        createOrderPatientList.value = res?.lists || []
    } catch {
        createOrderPatientList.value = []
    } finally {
        createOrderPatientLoading.value = false
    }
}

function onCreateOrderPatientChange(id: number | string) {
    const p = createOrderPatientList.value.find((x) => Number(x.id) === Number(id))
    if (p) {
        createOrderForm.recipient_name = p.patient_name || ''
        createOrderForm.recipient_phone = p.phone || ''
    }
}

function goCreateOrderPrevStep() {
    if (createOrderStep.value > 0) {
        createOrderStep.value -= 1
    }
}

async function goCreateOrderNextStep() {
    const form = createOrderFormRef.value
    if (!form) return
    try {
        if (createOrderStep.value === 0) {
            await form.validateField([...CREATE_ORDER_STEP0_FIELDS])
        } else if (createOrderStep.value === 1 && createOrderDepositMin.value > 0) {
            await form.validateField(['pay_order_ids'])
        }
        if (createOrderStep.value < 2) {
            createOrderStep.value += 1
        }
    } catch {
        /* 校验未通过，留在当前步 */
    }
}

async function submitCreateOrderFromPrescription() {
    if (!createOrderFormRef.value || !createOrderPrescription.value) return
    if (createOrderStep.value !== 2) return
    try {
        await createOrderFormRef.value.validate()
        createOrderSubmitLoading.value = true
        const diagnosisId = Number(createOrderForm.patient_id)
        const payload: Record<string, unknown> = {
            prescription_id: createOrderPrescription.value.id,
            diagnosis_id: diagnosisId,
            recipient_name: createOrderForm.recipient_name,
            recipient_phone: createOrderForm.recipient_phone,
            shipping_address: createOrderForm.shipping_address,
            is_follow_up: createOrderForm.is_follow_up,
            prev_staff: createOrderForm.prev_staff || '',
            service_channel: createOrderForm.service_channel || '',
            service_package:
                Array.isArray(createOrderForm.service_package) && createOrderForm.service_package.length > 0
                    ? createOrderForm.service_package.join(',')
                    : '',
            express_company: createOrderForm.express_company || 'auto',
            tracking_number: createOrderForm.tracking_number || '',
            fee_type: createOrderForm.fee_type,
            amount: createOrderForm.amount,
            remark_extra: createOrderForm.remark_extra || '',
            remark_assistant: createOrderForm.remark_assistant || ''
        }
        
        // 添加省市区字段
        if (createOrderForm.region && createOrderForm.region.length >= 3) {
            payload.shipping_province = createOrderForm.region[0]
            payload.shipping_city = createOrderForm.region[1]
            payload.shipping_district = createOrderForm.region[2]
        }
        
        if (createOrderForm.medication_days != null && createOrderForm.medication_days > 0) {
            payload.medication_days = createOrderForm.medication_days
        }
        if (createOrderForm.internal_cost != null && createOrderForm.internal_cost > 0) {
            payload.internal_cost = createOrderForm.internal_cost
        }
        if (createOrderForm.pay_order_ids.length) {
            payload.pay_order_ids = [...createOrderForm.pay_order_ids]
        }
        const res: any = await prescriptionOrderCreate(payload)
        const row = res?.data ?? res
        const orderNo = row?.order_no
        feedback.msgSuccess(orderNo ? `业务订单已创建，单号：${orderNo}` : '业务订单已创建')
        createOrderVisible.value = false
        getLists()
    } catch (e) {
        console.error(e)
    } finally {
        createOrderSubmitLoading.value = false
    }
}

/** 正在编辑的这条是否原为已作废 / 已驳回（用于提示） */
const editingWasVoid = ref(false)
const editingWasRejected = ref(false)

const editReviveHint = computed(() => {
    const v = editingWasVoid.value
    const r = editingWasRejected.value
    if (!v && !r) return ''
    if (v && r) return '当前处方已作废且已驳回。保存后将取消作废、清除驳回，并重新进入待审核。'
    if (v) return '当前为已作废处方。保存后将取消作废，并重新进入待审核。'
    return '当前为已驳回处方。保存后将清除驳回，并重新进入待审核。'
})

const slipHerbsList = computed(() => {
    const h = slipView.value?.herbs
    return Array.isArray(h) ? (h as HerbRow[]) : []
})

const slipMainHerbs = computed(() =>
    slipHerbsList.value.filter((h) => normalizeFormulaType(h.formula_type) === '主方')
)
const slipAuxHerbs = computed(() =>
    slipHerbsList.value.filter((h) => normalizeFormulaType(h.formula_type) === '辅方')
)

const mainHerbRows = computed(() =>
    editForm.herbs
        .map((herb, index) => ({ herb, index }))
        .filter(({ herb }) => normalizeFormulaType(herb.formula_type) === '主方')
)
const auxHerbRows = computed(() =>
    editForm.herbs
        .map((herb, index) => ({ herb, index }))
        .filter(({ herb }) => normalizeFormulaType(herb.formula_type) === '辅方')
)

const slipDietaryText = computed(() => {
    const d = slipView.value?.dietary_taboo
    if (Array.isArray(d)) return d.filter(Boolean).join('、')
    if (typeof d === 'string' && d.trim()) return d.trim()
    return ''
})

/* ============================================================
 * A4 处方笺（药房联）相关计算
 * ============================================================ */
const rxPaperRef = ref<HTMLElement | null>(null)
const downloadingSlip = ref(false)

const padN = (n: number) => String(n).padStart(2, '0')

const rxDateText = computed(() => {
    const v = slipView.value
    if (!v) return '—'
    const ts = (v as any).create_time ?? (v as any).update_time ?? null
    if (ts) {
        const t = String(ts).length === 10 ? Number(ts) * 1000 : Number(ts)
        const d = new Date(t)
        if (!isNaN(d.getTime())) {
            return `${d.getFullYear()}-${padN(d.getMonth() + 1)}-${padN(d.getDate())} ${padN(d.getHours())}:${padN(d.getMinutes())}`
        }
    }
    return v.prescription_date || '—'
})

const rxSerialText = computed(() => {
    const v = slipView.value as any
    if (!v) return '—'
    return (
        v.order_no ||
        v.serial_no ||
        v.serial_number ||
        v.no ||
        v.prescription_no ||
        v.visit_no ||
        (v.id ? `G${v.id}` : '—')
    )
})

const rxRecipientText = computed(() => {
    const v = slipView.value as any
    if (!v) return '—'
    if (v.recipient_text) return v.recipient_text
    const parts: string[] = []
    if (v.recipient_name || v.patient_name) parts.push(v.recipient_name || v.patient_name)
    if (v.recipient_phone || v.phone) parts.push(v.recipient_phone || v.phone)
    let region = v.region
    if (Array.isArray(region)) region = region.filter(Boolean).join('')
    if (region) parts.push(String(region))
    if (v.shipping_address) parts.push(String(v.shipping_address))
    else if (v.address) parts.push(String(v.address))
    return parts.length ? parts.join('，') : '—'
})

const rxDoseCount = computed(() => {
    const n = Number(slipView.value?.dose_count)
    return Number.isFinite(n) && n > 0 ? n : 1
})

const rxPerDoseAmount = computed(() => {
    const list = slipHerbsList.value
    const sum = list.reduce((acc: number, h: any) => acc + (Number(h?.dosage) || 0), 0)
    return formatNum(sum)
})

const rxHerbTotal = (dosage: number | string) => {
    const d = Number(dosage) || 0
    return formatNum(d * rxDoseCount.value)
}

const rxTypeText = computed(() => {
    const v = slipView.value as any
    if (!v) return '—'
    const t = v.prescription_type || '浓缩水丸'
    return /丸|散|膏|片/.test(t) ? `浓缩丸-${t}` : t
})

const rxUsageText = computed(() => {
    const v = slipView.value as any
    if (!v) return '—'
    if (v.usage_text) return v.usage_text
    return buildUsageSegmentText(v)
})

const rxAuxUsageText = computed(() => {
    const v = slipView.value as any
    if (!v || !slipAuxHerbs.value.length) return ''
    const aux = normalizeAuxUsageForm(v.aux_usage, v.prescription_type || '浓缩水丸')
    return buildUsageSegmentText(
        {
            prescription_type: v.prescription_type,
            dosage_amount: aux.dosage_amount,
            dosage_unit: v.dosage_unit,
            dosage_bag_count: aux.dosage_bag_count,
            times_per_day: aux.times_per_day,
            usage_way: v.usage_way,
            usage_time: v.usage_time
        },
        v.usage_way,
        v.usage_time
    )
})

const rxAdviceText = computed(() => {
    const v = slipView.value as any
    if (!v) return ''
    /** 出丸克数已经在底部以红色独立行展示，这里不重复 */
    return v.medical_advice || ''
})

const rxRemarkText = computed(() => {
    const v = slipView.value as any
    if (!v) return ''
    const parts: string[] = []
    parts.push(`共${slipHerbsList.value.length}味药`)
    if (v.usage_notes) parts.push(String(v.usage_notes))
    if (v.remark) parts.push(String(v.remark))
    return parts.join(' ')
})

const rxPharmacyRemarkText = computed(() => {
    const v = slipView.value as any
    if (!v) return ''
    return v.pharmacy_remark || v.pharmacy_note || ''
})

const rxOutPelletText = computed(() => {
    const v = slipView.value as any
    if (!v) return ''
    const out = computeOutPellet(v)
    return out ? `${out}克` : ''
})

function computeOutPellet(v: any): string {
    if (!v) return ''
    if ((v.prescription_type || '浓缩水丸') === '浓缩水丸') {
        const days = Number(v.medication_days ?? v.usage_days ?? v.dose_count)
        const times = Number(v.times_per_day)
        const doseG = Number(v.dosage_amount)
        const bags = Number(v.dosage_bag_count) > 0 ? Number(v.dosage_bag_count) : 1
        if (
            Number.isFinite(days) &&
            Number.isFinite(times) &&
            Number.isFinite(doseG) &&
            days > 0 &&
            times > 0 &&
            doseG > 0
        ) {
            return formatNum(days * times * doseG * bags)
        }
    }
    const explicit = v.out_pellet || v.total_weight
    if (explicit && Number(explicit) > 0) return formatNum(Number(explicit))
    const list = slipHerbsList.value
    if (!list.length) return ''
    const perDose = list.reduce((acc: number, h: any) => acc + (Number(h?.dosage) || 0), 0)
    return formatNum(perDose * rxDoseCount.value)
}

function formatNum(n: number): string {
    if (!isFinite(n)) return '0'
    return Number.isInteger(n) ? String(n) : n.toFixed(2).replace(/\.?0+$/, '')
}

const rxFee = computed(() => {
    const v = slipView.value as any
    const medicine = pickFee(v, ['medicine_fee', 'medicine_amount', 'drug_fee', 'pay_amount']) || 0
    const consult = pickFee(v, ['consult_fee', 'consultation_fee']) || 0
    const making = pickFee(v, ['making_fee', 'process_fee', 'manufacturing_fee']) || 0
    const shipping = pickFee(v, ['shipping_fee', 'freight_fee', 'delivery_fee']) || 0
    const discount = pickFee(v, ['discount_amount', 'discount_fee', 'discount']) || 0
    /** 业务订单合计金额（来自后端 detail 注入的 order_amount） */
    const orderAmount = pickFee(v, ['order_amount']) || 0
    let total = pickFee(v, ['total_amount', 'grand_total', 'amount_total']) || 0
    if (!total) total = orderAmount
    if (!total) total = Math.max(0, medicine + consult + making + shipping - discount)
    return {
        medicine: formatYuan(medicine),
        consult: formatYuan(consult),
        making: formatYuan(making),
        shipping: formatYuan(shipping),
        discount: formatYuan(discount),
        total: formatYuan(total)
    }
})

function pickFee(v: any, keys: string[]): number {
    if (!v) return 0
    for (const k of keys) {
        const val = v[k]
        if (val == null || val === '') continue
        const n = Number(val)
        if (!isNaN(n)) return n
    }
    return 0
}

function formatYuan(n: number): string {
    if (!isFinite(n)) return '0'
    return n.toFixed(2).replace(/\.?0+$/, '') || '0'
}

/* === 打印 === */
function handlePrintSlip() {
    if (!slipView.value) return
    nextTick(() => {
        try {
            window.print()
        } catch (e) {
            console.error(e)
        }
    })
}

/* === 下载 PDF（A4） === */
async function handleDownloadSlip() {
    const node = rxPaperRef.value
    if (!node) {
        feedback.msgWarning('处方笺尚未渲染完成')
        return
    }
    downloadingSlip.value = true
    try {
        await nextTick()
        /** 等一帧让浏览器完成最后的布局/字体回流 */
        await new Promise((r) => requestAnimationFrame(() => r(null)))
        await new Promise((r) => setTimeout(r, 250))

        /** 走 html2canvas 默认（DOM 克隆 + stylesheet 复制）模式：
         *  - 它会把页面 <style>/<link> 表全部复制到 iframe 渲染上下文，
         *    Vue scoped 样式与 Tailwind 工具类都能生效；
         *  - 不要开 foreignObjectRendering：它不携带外部样式表，会导致空白。
         */
        const canvas = await html2canvas(node, {
            scale: 2,
            backgroundColor: '#ffffff',
            useCORS: true,
            allowTaint: false,
            logging: false,
            /** 锁定渲染尺寸 = 元素自身尺寸，按 A4 真实宽度排版 */
            windowWidth: node.scrollWidth,
            windowHeight: node.scrollHeight,
            width: node.scrollWidth,
            height: node.scrollHeight
        })
        const imgData = canvas.toDataURL('image/jpeg', 0.95)
        const pdf = new jsPDF({ unit: 'mm', format: 'a4', orientation: 'portrait' })
        const pageW = 210
        const pageH = 297
        const imgW = pageW
        const imgH = (canvas.height * imgW) / canvas.width

        if (imgH <= pageH) {
            pdf.addImage(imgData, 'JPEG', 0, 0, imgW, imgH)
        } else {
            let leftHeight = imgH
            let position = 0
            while (leftHeight > 0) {
                pdf.addImage(imgData, 'JPEG', 0, position, imgW, imgH)
                leftHeight -= pageH
                position -= pageH
                if (leftHeight > 0) pdf.addPage()
            }
        }
        const name = (slipView.value as any)?.patient_name || '处方'
        const id = (slipView.value as any)?.id || ''
        const date = (slipView.value as any)?.prescription_date || ''
        pdf.save(`处方-${name}${date ? '-' + date : ''}${id ? '-' + id : ''}.pdf`)
    } catch (e: any) {
        console.error('下载处方 PDF 失败:', e)
        feedback.msgError(e?.message || '下载失败，请重试')
    } finally {
        downloadingSlip.value = false
    }
}

// 编辑表单
const editForm = reactive({
    id: 0,
    prescription_type: '浓缩水丸',
    dosage_amount: 1 as number | undefined,
    dosage_unit: 'g',
    dosage_bag_count: 1,
    need_decoction: false,
    bags_per_dose: 1,
    patient_name: '',
    gender: 1,
    age: 0,
    visit_no: '',
    prescription_date: '',
    tongue: '',
    tongue_image: '',
    pulse: '',
    pulse_condition: '',
    clinical_diagnosis: '',
    herbs: [] as HerbRow[],
    dose_count: 7,
    dose_unit: '剂',
    usage_days: 7,
    usage_instruction: '',
    usage_time: '饭后',
    usage_way: '温水送服',
    dietary_taboo: [] as string[],
    usage_notes: '',
    doctor_name: '',
    /** 医师电子签名 PNG data URL（与诊间处方一致） */
    doctor_signature: '',
    is_shared: 0,
    visible_role_ids: [] as number[],
    audit_status: 1,
    audit_time: null as number | null,
    audit_by_name: '',
    audit_remark: '',
    diagnosis_id: 0,
    /** 开方医师 admin id（处方库导入按此医生筛选） */
    creator_id: 0,
    /** 1=系统自动生成（如挂号完成） */
    is_system_auto: 0,
    /** 列表带入：业务订单「处方审核」驳回（消费者处方本身可能仍为已通过） */
    business_prescription_audit_rejected: 0,
    business_prescription_audit_remark: '',
    times_per_day: 2,
    aux_usage: defaultAuxUsage('浓缩水丸')
})

/** 编辑页：关联业务订单上的服用天数、医助备注（与处方提示一致） */
const rxLinkedOrderHint = reactive({
    loading: false,
    orderNo: '',
    medicationDays: null as number | null,
    remarkAssistant: ''
})

function clearRxLinkedOrderHint() {
    rxLinkedOrderHint.loading = false
    rxLinkedOrderHint.orderNo = ''
    rxLinkedOrderHint.medicationDays = null
    rxLinkedOrderHint.remarkAssistant = ''
}

async function loadRxLinkedOrderHintForEdit(prescriptionId: number) {
    rxLinkedOrderHint.orderNo = ''
    rxLinkedOrderHint.medicationDays = null
    rxLinkedOrderHint.remarkAssistant = ''
    if (!prescriptionId) {
        rxLinkedOrderHint.loading = false
        return
    }
    rxLinkedOrderHint.loading = true
    try {
        const data: any = await prescriptionOrderLists({
            page_no: 1,
            page_size: 5,
            prescription_id: prescriptionId
        })
        const lists = data?.lists
        const row = Array.isArray(lists) && lists.length ? lists[0] : null
        if (row) {
            rxLinkedOrderHint.orderNo = String(row.order_no || '').trim()
            const md = row.medication_days
            const mdn = md !== null && md !== undefined && String(md).trim() !== '' ? Number(md) : NaN
            rxLinkedOrderHint.medicationDays = Number.isFinite(mdn) && mdn > 0 ? mdn : null
            rxLinkedOrderHint.remarkAssistant = String(row.remark_assistant || '').trim()
        }
    } catch {
        /* 无列表权限或网络错误：保持空 */
    } finally {
        rxLinkedOrderHint.loading = false
    }
}

const diagnosisViewRef = ref<{
    openViewOnly: (id: number) => Promise<void>
} | null>(null)

function openDiagnosisPatientDetail() {
    const id = Number(editForm.diagnosis_id)
    if (!id) {
        feedback.msgWarning('本处方未关联诊单，无法查看诊单患者信息')
        return
    }
    void diagnosisViewRef.value?.openViewOnly(id)
}

// 标志：是否正在加载数据（防止watch函数覆盖已加载的值）
const isLoadingData = ref(false)

// 监听处方类型变化，自动调整用量单位和默认值
watch(() => editForm.prescription_type, (newType) => {
    // 如果正在加载数据，不要自动重置值
    if (isLoadingData.value) {
        return
    }
    
    if (newType === '浓缩水丸') {
        editForm.dosage_unit = 'g'
        editForm.dosage_amount = 1
        editForm.dosage_bag_count = 1
        editForm.need_decoction = false
        editForm.bags_per_dose = 1
    } else if (newType === '饮片') {
        editForm.dosage_unit = 'ml'
        editForm.dosage_amount = 50
        editForm.dosage_bag_count = 1
        editForm.bags_per_dose = 1
        // need_decoction 保持用户选择
    } else {
        editForm.dosage_unit = 'g'
        editForm.dosage_amount = undefined
        editForm.dosage_bag_count = 1
        editForm.need_decoction = false
        editForm.bags_per_dose = 1
    }
    Object.assign(editForm.aux_usage, defaultAuxUsage(newType))
})

// 表单验证规则
const rules: FormRules = {
    patient_name: [
        { required: true, message: '请输入患者姓名', trigger: 'blur' }
    ],
    gender: [
        { required: true, message: '请选择性别', trigger: 'change' }
    ],
    prescription_date: [
        { required: true, message: '请选择处方日期', trigger: 'change' }
    ],
    clinical_diagnosis: [
        { required: true, message: '请输入临床诊断', trigger: 'blur' }
    ],
    dose_count: [
        { required: true, message: '请输入剂数', trigger: 'blur' }
    ],
    doctor_name: [
        { required: true, message: '请输入医师姓名', trigger: 'blur' }
    ],
    doctor_signature: [
        {
            required: true,
            validator: (_rule, v, cb) => {
                if (!v || !String(v).trim()) {
                    cb(new Error('请使用电子签名板手写医师签名'))
                } else {
                    cb()
                }
            },
            trigger: 'change'
        }
    ]
}

async function fetchPrescriptionLists(params: Record<string, unknown>) {
    const { audit_filter, source_filter, creator_ids, ...rest } = params
    const payload: Record<string, unknown> = {
        ...rest,
        audit_filter: audit_filter === 'all' || audit_filter === '' ? '' : audit_filter,
        source_filter:
            source_filter === 'all' || source_filter === '' || source_filter === undefined ? '' : source_filter
    }
    if (Array.isArray(creator_ids) && creator_ids.length > 0) {
        payload.creator_ids = creator_ids
    }
    return prescriptionLists(payload)
}

const { pager, getLists, resetPage } = usePaging({
    fetchFun: fetchPrescriptionLists,
    params: formData
})

function pad2(n: number) {
    return String(n).padStart(2, '0')
}

/** 本地日历日的 00:00:00 ~ 23:59:59 字符串（与 daterange-picker 一致） */
function dayRangeStrings(d: Date) {
    const y = d.getFullYear()
    const m = pad2(d.getMonth() + 1)
    const day = pad2(d.getDate())
    const base = `${y}-${m}-${day}`
    return { start: `${base} 00:00:00`, end: `${base} 23:59:59` }
}

function onDateQuickTabChange(val: string | number | boolean | undefined) {
    const tab = String(val ?? 'all')
    if (tab === 'all') {
        formData.start_time = ''
        formData.end_time = ''
    } else {
        const now = new Date()
        const t = new Date(now.getFullYear(), now.getMonth(), now.getDate())
        if (tab === 'yesterday') {
            t.setDate(t.getDate() - 1)
        } else if (tab === 'before_yesterday') {
            t.setDate(t.getDate() - 2)
        }
        const { start, end } = dayRangeStrings(t)
        formData.start_time = start
        formData.end_time = end
    }
    resetPage()
}

function onAuditFilterChange() {
    resetPage()
}

function onSourceFilterChange() {
    resetPage()
}

let syncingDateTab = false
watch(
    () => [formData.start_time, formData.end_time],
    () => {
        if (syncingDateTab) return
        const s = formData.start_time
        const e = formData.end_time
        if (!s && !e) {
            dateQuickTab.value = 'all'
            return
        }
        if (!s || !e) {
            dateQuickTab.value = ''
            return
        }
        const now = new Date()
        const matchOffset = (offset: number) => {
            const d = new Date(now.getFullYear(), now.getMonth(), now.getDate() - offset)
            const { start, end } = dayRangeStrings(d)
            return s === start && e === end
        }
        if (matchOffset(0)) dateQuickTab.value = 'today'
        else if (matchOffset(1)) dateQuickTab.value = 'yesterday'
        else if (matchOffset(2)) dateQuickTab.value = 'before_yesterday'
        else dateQuickTab.value = ''
    }
)

function formatListCreateTime(v: unknown) {
    if (v === null || v === undefined || v === '') return '—'
    if (typeof v === 'number' && v >= 1e9 && v < 1e11) {
        return formatAuditTime(v)
    }
    const s = String(v).trim()
    if (/^\d{10}$/.test(s)) {
        return formatAuditTime(parseInt(s, 10))
    }
    return s
}

function resetParams() {
    syncingDateTab = true
    dateQuickTab.value = 'all'
    formData.sn = ''
    formData.patient_name = ''
    formData.creator_ids = []
    formData.audit_filter = 'all'
    formData.source_filter = 'all'
    formData.start_time = ''
    formData.end_time = ''
    syncingDateTab = false
    resetPage()
}

function userCanAudit() {
    const u = userStore.userInfo
    if (!u) return false
    if (Number(u.root) === 1) return true
    const raw = u.role_ids ?? u.role_id
    const ids = Array.isArray(raw) ? raw.map((n: unknown) => Number(n)) : []
    return PRESCRIPTION_AUDIT_ROLE_IDS.some((rid) => ids.includes(rid))
}

function auditStatusLabel(v: number | undefined) {
    if (v === 0) return '待审核'
    if (v === 2) return '已驳回'
    return '已通过'
}

function auditStatusTagType(v: number | undefined) {
    if (v === 0) return 'warning'
    if (v === 2) return 'danger'
    return 'success'
}

/** 业务订单处方审核驳回时，列表「审核状态」主标签显示为已驳回 */
function listAuditStatusLabel(row: { audit_status?: number; business_prescription_audit_rejected?: number }) {
    if (Number(row.business_prescription_audit_rejected) === 1) return '已驳回'
    return auditStatusLabel(row.audit_status)
}

function listAuditStatusTagType(row: { audit_status?: number; business_prescription_audit_rejected?: number }) {
    if (Number(row.business_prescription_audit_rejected) === 1) return 'danger'
    return auditStatusTagType(row.audit_status)
}

function listRejectReasonLines(row: {
    audit_status?: number
    audit_remark?: string
    business_prescription_audit_rejected?: number
    business_prescription_audit_remark?: string
}): string[] {
    const out: string[] = []
    if (Number(row.business_prescription_audit_rejected) === 1) {
        const t = String(row.business_prescription_audit_remark || '').trim()
        out.push(t ? `业务订单审核驳回意见：${t}` : '业务订单审核驳回意见：—')
    }
    if (Number(row.audit_status) === 2) {
        const t = String(row.audit_remark || '').trim()
        out.push(t ? `消费者处方审核驳回意见：${t}` : '消费者处方审核驳回意见：—')
    }
    return out
}

/** 已通过审核且未作废：仅可查看，不可编辑/删除（与预约列表「查看」一致） */
function isApprovedActivePrescription(row: { audit_status?: number; void_status?: number }) {
    return Number(row.audit_status) === 1 && Number(row.void_status) !== 1
}

function formatAuditTime(ts: number | null | undefined) {
    if (!ts) return ''
    const d = new Date(ts * 1000)
    return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')} ${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`
}

function formatVoidTime(ts: number | null | undefined) {
    if (!ts) return '—'
    return formatAuditTime(ts)
}

function slipGenderLabel(g: unknown) {
    if (g === 1 || g === '1') return '男'
    if (g === 0 || g === '0') return '女'
    return '—'
}

function slipAgeText(age: unknown) {
    if (age === null || age === undefined || age === '') return '—'
    return `${age}岁`
}

function herbValidationLabel(globalIndex: number): string {
    const herb = editForm.herbs[globalIndex]
    if (!herb) return `第${globalIndex + 1}味`
    const ft = normalizeFormulaType(herb.formula_type)
    let n = 0
    for (let i = 0; i <= globalIndex; i++) {
        if (normalizeFormulaType(editForm.herbs[i]?.formula_type) === ft) n++
    }
    return `${ft}第${n}味`
}

function listRxOrderWarnings(row: any): string[] {
    if (Number(row?.has_prescription_order) !== 1) return []
    const herbs = normalizeSlipHerbs(row?.herbs)
    const herbNames = herbs
        .map((h) => String(h?.name || '').trim())
        .filter(Boolean)
    const warns: string[] = []

    if (!herbNames.length) {
        warns.push('请开方，当前处方药材为空白')
        return warns
    }

    const seen = new Set<string>()
    const dup = new Set<string>()
    for (const n of herbNames) {
        const k = n.replace(/\s+/g, '').toLowerCase()
        if (!k) continue
        if (seen.has(k)) dup.add(n)
        else seen.add(k)
    }
    if (dup.size > 0) {
        warns.push(`已有关联业务订单，当前处方存在重复药材：${Array.from(dup).join('、')}`)
    }
    return warns
}

function rowToSlipView(row: any) {
    return {
        ...row,
        herbs: normalizeSlipHerbs(row?.herbs)
    }
}

function onEditDialogClosed() {
    slipView.value = null
    signatureActivePointerId.value = null
}

/**
 * 签名坐标：与 initSignatureCanvas 里 ctx.scale(dpr) 后的「逻辑像素」一致（0…SIGNATURE_CSS_W/H），
 * 不能用 canvas.width/rect.width（会把 dpr 乘两次，笔画和鼠标严重错位）。
 */
function getSignatureLocalPoint(e: PointerEvent) {
    const canvas = signatureCanvasRef.value
    if (!canvas) return { x: 0, y: 0 }
    const rect = canvas.getBoundingClientRect()
    if (rect.width <= 0 || rect.height <= 0) return { x: 0, y: 0 }
    const x = ((e.clientX - rect.left) / rect.width) * SIGNATURE_CSS_W
    const y = ((e.clientY - rect.top) / rect.height) * SIGNATURE_CSS_H
    return {
        x: Math.max(0, Math.min(SIGNATURE_CSS_W, x)),
        y: Math.max(0, Math.min(SIGNATURE_CSS_H, y))
    }
}

function commitSignatureImage() {
    const canvas = signatureCanvasRef.value
    if (canvas) {
        editForm.doctor_signature = canvas.toDataURL('image/png')
    }
    nextTick(() => {
        formRef.value?.validateField('doctor_signature').catch(() => {})
    })
}

function onSignaturePointerDown(e: PointerEvent) {
    if (e.pointerType === 'mouse' && e.button !== 0) return
    const canvas = signatureCanvasRef.value
    const ctx = canvas?.getContext('2d')
    if (!canvas || !ctx) return
    canvas.setPointerCapture(e.pointerId)
    signatureActivePointerId.value = e.pointerId
    const { x, y } = getSignatureLocalPoint(e)
    ctx.beginPath()
    ctx.moveTo(x, y)
}

function onSignaturePointerMove(e: PointerEvent) {
    if (signatureActivePointerId.value !== e.pointerId) return
    const ctx = signatureCanvasRef.value?.getContext('2d')
    if (!ctx) return
    const { x, y } = getSignatureLocalPoint(e)
    ctx.lineTo(x, y)
    ctx.stroke()
    ctx.beginPath()
    ctx.moveTo(x, y)
}

function onSignaturePointerUp(e: PointerEvent) {
    if (signatureActivePointerId.value !== e.pointerId) return
    signatureActivePointerId.value = null
    const canvas = signatureCanvasRef.value
    if (canvas) {
        try {
            canvas.releasePointerCapture(e.pointerId)
        } catch {
            /* 已释放 */
        }
    }
    commitSignatureImage()
}

function clearSignature() {
    initSignatureCanvas()
    editForm.doctor_signature = ''
    nextTick(() => {
        formRef.value?.validateField('doctor_signature').catch(() => {})
    })
}

function initSignatureCanvas() {
    const canvas = signatureCanvasRef.value
    if (!canvas) return
    const dpr = Math.min(typeof window !== 'undefined' ? window.devicePixelRatio || 1 : 1, 2.5)
    canvas.style.width = `${SIGNATURE_CSS_W}px`
    canvas.style.height = `${SIGNATURE_CSS_H}px`
    canvas.width = Math.round(SIGNATURE_CSS_W * dpr)
    canvas.height = Math.round(SIGNATURE_CSS_H * dpr)
    const ctx = canvas.getContext('2d')
    if (!ctx) return
    ctx.setTransform(1, 0, 0, 1, 0, 0)
    ctx.scale(dpr, dpr)
    ctx.fillStyle = '#fff'
    ctx.fillRect(0, 0, SIGNATURE_CSS_W, SIGNATURE_CSS_H)
    ctx.strokeStyle = '#333'
    ctx.lineWidth = 2.5
    ctx.lineCap = 'round'
    ctx.lineJoin = 'round'
}

/** 抽屉打开后初始化画布；编辑时若有已存签名则绘制到画布 */
function scheduleEditSignatureInit() {
    if (editMode.value === 'view') return
    nextTick(() => {
        setTimeout(() => {
            initSignatureCanvas()
            const sig = editForm.doctor_signature
            if (sig && String(sig).trim().startsWith('data:image') && signatureCanvasRef.value) {
                const img = new Image()
                img.onload = () => {
                    const canvas = signatureCanvasRef.value
                    const ctx = canvas?.getContext('2d')
                    if (!canvas || !ctx) return
                    ctx.drawImage(img, 0, 0, SIGNATURE_CSS_W, SIGNATURE_CSS_H)
                    commitSignatureImage()
                }
                img.onerror = () => {
                    commitSignatureImage()
                }
                img.src = sig
            }
        }, 100)
    })
}

function formatVisibleRoleNames(ids: number[] | undefined) {
    if (!ids || !ids.length) return '—'
    const names = ids
        .map((id) => roleOptions.value.find((r) => r.id === id)?.name)
        .filter(Boolean)
    return names.length ? names.join('、') : ids.join('、')
}

function normalizeVisibleRoleIds(row: any): number[] {
    const v = row?.visible_role_ids
    if (Array.isArray(v)) return v.map((n) => Number(n)).filter((n) => !Number.isNaN(n))
    if (typeof v === 'string' && v)
        return v
            .split(',')
            .map((s) => parseInt(s.trim(), 10))
            .filter((n) => !Number.isNaN(n))
    return []
}

function openAuditDialog(row: any) {
    auditTargetId.value = row.id
    auditRemark.value = ''
    auditDialogVisible.value = true
}

async function submitAudit(action: 'approve' | 'reject') {
    if (action === 'reject' && !auditRemark.value.trim()) {
        feedback.msgError('驳回时请填写审核意见')
        return
    }
    auditLoading.value = true
    try {
        const auditData = (await prescriptionAudit({
            id: auditTargetId.value,
            action,
            remark: auditRemark.value.trim()
        })) as { wecom_notify_ok?: boolean; wecom_notify_hint?: string } | void
        feedback.msgSuccess(action === 'reject' ? '已驳回并作废处方' : '审核通过')
        if (auditData && auditData.wecom_notify_ok === false && auditData.wecom_notify_hint) {
            feedback.msgWarning(auditData.wecom_notify_hint)
        }
        auditDialogVisible.value = false
        getLists()
    } catch {
        /* 拦截器已提示 */
    } finally {
        auditLoading.value = false
    }
}

async function loadRoleOptions() {
    try {
        const list = await roleAll({})
        roleOptions.value = Array.isArray(list) ? list : []
    } catch {
        roleOptions.value = []
    }
}

// —— 处方库导入（与 components/tcm-prescription 一致，按 creator_id 拉取该医师库内处方）——
const showLibraryDialog = ref(false)
const libraryLoading = ref(false)
const libraryList = ref<any[]>([])
const librarySearchName = ref('')
const librarySearchFormulaType = ref('')
const libraryImportMode = ref<'replace' | 'append'>('replace')
const libraryPage = ref(1)
const libraryPageSize = ref(15)
const libraryTotal = ref(0)

/** 当前用于检索处方库的开方医师 ID：编辑用处方 creator_id，新增用当前登录账号 */
const libraryDoctorId = computed(() => {
    const cid = Number(editForm.creator_id)
    if (cid > 0) return cid
    const uid = Number(userStore.userInfo?.id)
    return uid > 0 ? uid : 0
})

function normalizeHerbNameLocal(s: string) {
    return String(s || '')
        .trim()
        .toLowerCase()
}

function findDuplicateHerbNamesLocal(): string[] {
    const map = new Map<string, number>()
    for (const h of editForm.herbs) {
        const key = normalizeHerbNameLocal(h?.name)
        if (!key) continue
        map.set(key, (map.get(key) ?? 0) + 1)
    }
    return [...map.entries()]
        .filter(([, c]) => c > 1)
        .map(([name]) => name)
}

const loadLibraryList = async () => {
    const doctorId = libraryDoctorId.value
    if (!doctorId) {
        feedback.msgWarning('无法确定开方医师，无法加载处方库')
        libraryList.value = []
        libraryTotal.value = 0
        return
    }
    libraryLoading.value = true
    try {
        const res: any = await prescriptionLibraryLists({
            page_no: libraryPage.value,
            page_size: libraryPageSize.value,
            prescription_name: librarySearchName.value,
            formula_type: librarySearchFormulaType.value,
            prescribing_creator_id: doctorId
        })
        libraryList.value = res?.lists || []
        libraryTotal.value = res?.count || 0
    } catch (e) {
        console.error(e)
        feedback.msgError('加载处方库失败')
    } finally {
        libraryLoading.value = false
    }
}

const searchLibrary = () => {
    libraryPage.value = 1
    loadLibraryList()
}

const openLibraryDialog = () => {
    const doctorId = libraryDoctorId.value
    if (!doctorId) {
        feedback.msgWarning('无法确定开方医师，无法从处方库导入')
        return
    }
    showLibraryDialog.value = true
}

const handleSelectLibraryRow = (row: any) => {
    handleImportLibrary(row)
}

const handleImportLibrary = (row: any) => {
    if (!row.herbs || row.herbs.length === 0) {
        feedback.msgWarning('该处方没有药材信息')
        return
    }
    const formulaType = normalizeFormulaType(row.formula_type)
    const imported = (JSON.parse(JSON.stringify(row.herbs)) as any[]).map((h) => ({
        ...normalizeHerbRow(h),
        formula_type: formulaType
    }))
    if (libraryImportMode.value === 'replace') {
        const kept = editForm.herbs.filter((h) => normalizeFormulaType(h.formula_type) !== formulaType)
        editForm.herbs = [...kept, ...imported]
    } else {
        editForm.herbs.push(...imported)
    }
    const modeHint = libraryImportMode.value === 'append' ? '（已追加）' : ''
    if (findDuplicateHerbNamesLocal().length) {
        feedback.msgWarning(
            `已导入处方「${row.prescription_name}」${modeHint}，共${imported.length}味药材。存在重复药名，请合并剂量或删除多余行`
        )
    } else {
        feedback.msgSuccess(`已导入处方「${row.prescription_name}」${modeHint}，共${imported.length}味药材`)
    }
    showLibraryDialog.value = false
}

watch(showLibraryDialog, (open) => {
    if (open) {
        librarySearchName.value = ''
        librarySearchFormulaType.value = ''
        libraryImportMode.value = 'replace'
        libraryPage.value = 1
        loadLibraryList()
    }
})

/** 粘贴药方导入（与 components/tcm-prescription 一致） */
const showPasteRecipeDialog = ref(false)
const pasteRecipeText = ref('')
const pasteRecipeImportMode = ref<'replace' | 'append'>('replace')
const pasteRecipeImportLoading = ref(false)

const PASTE_RECIPE_SKIP_SEGMENT =
    /^(用法|用量|医嘱|忌口|水煎服|空腹|饭后|温水|内服|外用|备注|顿服|分服|ml|毫升|[×xX]\s*\d)/

function normalizeRecipePasteInput(raw: string): string {
    let s = raw.replace(/\r\n/g, '\n').replace(/\r/g, '\n')
    s = s.replace(/[０-９]/g, (ch) => String.fromCharCode(ch.charCodeAt(0) - 0xff10 + 48))
    return s.trim()
}

function stripRecipePasteHeaders(text: string): string {
    return text
        .replace(/^\s*Rp[:：＊*\s]*/i, '')
        .replace(/^\s*处方[:：\s]*/, '')
        .replace(/^\s*中药处方[:：\s]*/, '')
        .trimStart()
}

function stripHerbPasteNote(name: string): string {
    return name
        .replace(/（[^）]*）$/u, '')
        .replace(/\([^)]*\)$/u, '')
        .trim()
}

function parseHerbPasteToken(seg: string): { name: string; dosage: number }[] | null {
    const s = seg.trim()
    if (!s || PASTE_RECIPE_SKIP_SEGMENT.test(s)) return null
    if (/^\d/.test(s)) return null
    if (/^\d+\s*剂$/.test(s)) return null

    const ge = s.match(/^(.+)\s*各\s*(\d+(?:\.\d+)?)\s*(?:克|g|G)?$/i)
    if (ge) {
        const dose = parseFloat(ge[2])
        if (!Number.isFinite(dose) || dose <= 0) return null
        const names = ge[1]
            .split(/[、，,\s]+/)
            .map((x) => x.trim())
            .filter(Boolean)
        if (!names.length) return null
        return names.map((name) => ({ name: stripHerbPasteNote(name), dosage: dose }))
    }

    const m = s.match(/^(.+?)\s*(\d+(?:\.\d+)?)\s*(?:克|g|G|钱)?$/i)
    if (m) {
        const name = stripHerbPasteNote(m[1].trim())
        const dose = parseFloat(m[2])
        if (!name || !Number.isFinite(dose) || dose <= 0) return null
        return [{ name, dosage: dose }]
    }

    const nameOnly = stripHerbPasteNote(s)
    if (nameOnly.length >= 2 && nameOnly.length <= 16) {
        return [{ name: nameOnly, dosage: 6 }]
    }
    return null
}

function chunkRecipePasteText(text: string): string[] {
    const t = stripRecipePasteHeaders(normalizeRecipePasteInput(text))
    const out: string[] = []
    for (const line of t.split(/\n+/)) {
        const ln = line.trim()
        if (!ln) continue
        for (const piece of ln.split(/[、，,；;]/)) {
            const p = piece.trim()
            if (!p) continue
            if (/\s/.test(p) && !parseHerbPasteToken(p)) {
                const sub = p.split(/\s+(?=[\u4e00-\u9fff]{2,})/)
                for (const x of sub) {
                    const c = x.trim()
                    if (c) out.push(c)
                }
            } else {
                out.push(p)
            }
        }
    }
    return out
}

function parseRecipePasteToHerbs(text: string): { name: string; dosage: number }[] {
    const herbs: { name: string; dosage: number }[] = []
    for (const c of chunkRecipePasteText(text)) {
        const parsed = parseHerbPasteToken(c)
        if (!parsed) continue
        herbs.push(...parsed)
    }
    return herbs
}

async function resolvePasteHerbNameFromLibrary(rawName: string): Promise<string | null> {
    const q = rawName.trim()
    if (!q) return null
    try {
        const res = await medicineLists({
            name: q,
            page_no: 1,
            page_size: 200,
            status: 1
        })
        const lists = (res.lists || []) as { id: number; name: string }[]
        const exact = lists.find((item) => (item.name ?? '').trim() === q)
        return exact ? exact.name.trim() : null
    } catch {
        return null
    }
}

function openPasteRecipeDialog() {
    showPasteRecipeDialog.value = true
}

async function handlePasteRecipeImport() {
    const parsed = parseRecipePasteToHerbs(pasteRecipeText.value)
    if (!parsed.length) {
        feedback.msgWarning('未能从文本中解析出药材，请检查格式（药名 + 剂量，或用顿号/换行分隔）')
        return
    }
    pasteRecipeImportLoading.value = true
    try {
        const resolved: HerbRow[] = []
        const skippedNames: string[] = []
        for (const row of parsed) {
            const name = await resolvePasteHerbNameFromLibrary(row.name)
            if (!name) {
                skippedNames.push(row.name.trim())
                continue
            }
            resolved.push({ name, dosage: row.dosage, formula_type: '主方' })
        }
        const skippedUnique = [...new Set(skippedNames.filter(Boolean))]
        if (resolved.length === 0) {
            feedback.msgWarning(
                skippedUnique.length
                    ? `药品库中无以下完全同名药材，未录入：${skippedUnique.join('、')}`
                    : '未能匹配到药品库中的药材'
            )
            return
        }
        if (pasteRecipeImportMode.value === 'replace') {
            const auxKept = editForm.herbs.filter((h) => normalizeFormulaType(h.formula_type) === '辅方')
            editForm.herbs = [...auxKept, ...resolved]
        } else {
            editForm.herbs.push(...resolved)
        }
        const dupNames = findDuplicateHerbNamesLocal()
        const skipHint =
            skippedUnique.length > 0 ? `；药品库未收录已跳过：${skippedUnique.join('、')}` : ''
        if (dupNames.length) {
            feedback.msgWarning(
                `已导入 ${resolved.length} 味药材${skipHint}。存在重复药名：${dupNames.join(
                    '、'
                )}，请合并剂量或删除多余行`
            )
        } else if (skippedUnique.length) {
            feedback.msgSuccess(`已导入 ${resolved.length} 味药材${skipHint}，请核对剂量`)
        } else {
            feedback.msgSuccess(`已导入 ${resolved.length} 味药材，请核对药名与剂量`)
        }
        showPasteRecipeDialog.value = false
        pasteRecipeText.value = ''
    } finally {
        pasteRecipeImportLoading.value = false
    }
}

// 添加药材（主方 / 辅方）
const addHerb = (formulaType: FormulaType = '主方') => {
    editForm.herbs.push({
        name: '',
        dosage: 0,
        formula_type: formulaType
    })
}

// 删除药材
const removeHerb = (index: number) => {
    editForm.herbs.splice(index, 1)
}

// 重置表单
const resetForm = () => {
    editForm.id = 0
    editForm.prescription_type = '浓缩水丸'
    editForm.dosage_amount = 1
    editForm.dosage_unit = 'g'
    editForm.dosage_bag_count = 1
    editForm.need_decoction = false
    editForm.bags_per_dose = 1
    editForm.patient_name = ''
    editForm.gender = 1
    editForm.age = 0
    editForm.visit_no = ''
    editForm.prescription_date = new Date().toISOString().split('T')[0]
    editForm.tongue = ''
    editForm.tongue_image = ''
    editForm.pulse = ''
    editForm.pulse_condition = ''
    editForm.clinical_diagnosis = ''
    editForm.herbs = []
    editForm.dose_count = 7
    editForm.dose_unit = '剂'
    editForm.usage_days = 7
    editForm.usage_instruction = ''
    editForm.usage_time = '饭后'
    editForm.usage_way = '温水送服'
    editForm.dietary_taboo = []
    editForm.usage_notes = ''
    editForm.doctor_name = ''
    editForm.doctor_signature = ''
    editForm.is_shared = 0
    editForm.visible_role_ids = []
    editForm.audit_status = 1
    editForm.audit_time = null
    editForm.audit_by_name = ''
    editForm.audit_remark = ''
    editForm.diagnosis_id = 0
    editForm.creator_id = Number(userStore.userInfo?.id) || 0
    editForm.is_system_auto = 0
    editForm.business_prescription_audit_rejected = 0
    editForm.business_prescription_audit_remark = ''
    editForm.times_per_day = 2
    Object.assign(editForm.aux_usage, defaultAuxUsage('浓缩水丸'))
    clearRxLinkedOrderHint()
}

// 新增处方
const handleAdd = () => {
    resetForm()
    editForm.doctor_name = String(userStore.userInfo?.name || '')
    editingWasVoid.value = false
    editingWasRejected.value = false
    editMode.value = 'add'
    // 新建时允许watch自动设置默认值
    isLoadingData.value = false
    showEdit.value = true
    nextTick(() => {
        formRef.value?.clearValidate()
        scheduleEditSignatureInit()
    })
}

// 查看处方（处方笺样式，详情接口补全电话、签名等）
const handleView = async (row: any) => {
    editingWasVoid.value = false
    editingWasRejected.value = false
    editMode.value = 'view'
    slipView.value = rowToSlipView(row)
    showEdit.value = true
    viewDetailLoading.value = true
    try {
        const d = await prescriptionDetail({ id: row.id })
        if (d && typeof d === 'object') {
            slipView.value = {
                ...d,
                herbs: normalizeSlipHerbs((d as any).herbs)
            }
        }
    } catch (e: any) {
        feedback.msgError(e?.msg || '加载处方详情失败')
    } finally {
        viewDetailLoading.value = false
    }
}

// 编辑处方
const handleEdit = async (row: any) => {
    editingWasVoid.value = Number(row.void_status) === 1
    editingWasRejected.value = Number(row.audit_status) === 2
    editMode.value = 'edit'
    
    // 开始加载数据，暂时禁用watch自动重置
    isLoadingData.value = true

    let src = row
    if (row?.id && !row.doctor_signature) {
        try {
            const d = await prescriptionDetail({ id: row.id })
            if (d && typeof d === 'object') {
                src = { ...row, ...d }
            }
        } catch {
            /* 保持列表行 */
        }
    }
    
    // 深拷贝数据到表单
    editForm.id = src.id
    editForm.prescription_type = src.prescription_type || '浓缩水丸'
    
    // 确保 dosage_amount 是数字类型，以匹配下拉框的 :value
    if (src.dosage_amount !== null && src.dosage_amount !== undefined && src.dosage_amount !== '') {
        editForm.dosage_amount = Number(src.dosage_amount)
    } else {
        editForm.dosage_amount = undefined
    }
    
    // 如果数据库中没有 dosage_unit，根据 prescription_type 设置默认值
    if (src.dosage_unit) {
        editForm.dosage_unit = src.dosage_unit
    } else {
        if (editForm.prescription_type === '饮片') {
            editForm.dosage_unit = 'ml'
        } else {
            editForm.dosage_unit = 'g'
        }
    }
    
    editForm.dosage_bag_count = src.dosage_bag_count ? Number(src.dosage_bag_count) : 1
    editForm.need_decoction = src.need_decoction === 1 || src.need_decoction === true
    editForm.bags_per_dose = src.bags_per_dose ? Number(src.bags_per_dose) : 1
    editForm.patient_name = src.patient_name || ''
    editForm.gender = src.gender ?? 1
    editForm.age = src.age ?? 0
    editForm.visit_no = src.visit_no || ''
    editForm.prescription_date = src.prescription_date || ''
    editForm.tongue = src.tongue || ''
    editForm.tongue_image = src.tongue_image || ''
    editForm.pulse = src.pulse || ''
    editForm.pulse_condition = src.pulse_condition || ''
    editForm.clinical_diagnosis = src.clinical_diagnosis || ''
    editForm.herbs = src.herbs ? (src.herbs as any[]).map((h) => normalizeHerbRow(h)) : []
    editForm.dose_count = src.dose_count ?? 7
    editForm.dose_unit = src.dose_unit || '剂'
    editForm.usage_days = src.usage_days ?? 7
    editForm.times_per_day = src.times_per_day ?? 2
    editForm.usage_instruction = src.usage_instruction || ''
    editForm.usage_time = src.usage_time || '饭后'
    editForm.usage_way = src.usage_way || '温水送服'
    editForm.dietary_taboo = src.dietary_taboo
        ? (Array.isArray(src.dietary_taboo) ? src.dietary_taboo : String(src.dietary_taboo).split(',').filter((v: string) => v))
        : []
    editForm.usage_notes = src.usage_notes || ''
    editForm.doctor_name = src.doctor_name || ''
    editForm.doctor_signature = String(src.doctor_signature || '')
    editForm.is_shared = src.is_shared ?? 0
    editForm.visible_role_ids = normalizeVisibleRoleIds(src)
    editForm.audit_status = src.audit_status ?? 1
    editForm.audit_time = src.audit_time ?? null
    editForm.audit_by_name = src.audit_by_name || ''
    editForm.audit_remark = src.audit_remark || ''
    editForm.diagnosis_id = src.diagnosis_id ?? 0
    editForm.creator_id = Number(src.creator_id) > 0 ? Number(src.creator_id) : 0
    editForm.is_system_auto = Number(src.is_system_auto) === 1 ? 1 : 0
    editForm.business_prescription_audit_rejected = Number(src.business_prescription_audit_rejected) === 1 ? 1 : 0
    editForm.business_prescription_audit_remark = String(src.business_prescription_audit_remark || '')
    Object.assign(
        editForm.aux_usage,
        normalizeAuxUsageForm(src.aux_usage, editForm.prescription_type)
    )
    
    // 数据加载完成，重新启用watch
    // 使用 setTimeout 确保所有数据都已经渲染完成
    setTimeout(() => {
        isLoadingData.value = false
    }, 0)

    showEdit.value = true
    void loadRxLinkedOrderHintForEdit(Number(editForm.id))
    nextTick(() => {
        formRef.value?.clearValidate()
        scheduleEditSignatureInit()
    })
}

// 提交表单
const handleSubmit = async () => {
    if (!formRef.value) return

    try {
        await formRef.value.validate()
    } catch {
        // Element Plus：校验失败会 reject，表单项已展示错误，勿再向外抛成 Uncaught
        return
    }

    // 验证药材
    if (!editForm.herbs || editForm.herbs.length === 0) {
        feedback.msgError('请至少添加一味药材')
        return
    }
    
    for (let i = 0; i < editForm.herbs.length; i++) {
        const herb = editForm.herbs[i]
        const label = herbValidationLabel(i)
        if (!herb.name || !herb.name.trim()) {
            feedback.msgError(`${label}药材名称不能为空`)
            return
        }
        if (!herb.dosage || herb.dosage <= 0) {
            feedback.msgError(`${label}药材剂量必须大于0`)
            return
        }
    }
    
    submitLoading.value = true
    
    try {
        const params: Record<string, unknown> = { ...editForm }

        if (editMode.value === 'add') {
            params.audit_status = 0
            await prescriptionAdd(params)
            feedback.msgSuccess('添加成功，已提交审核')
        } else {
            await prescriptionEdit(params)
            feedback.msgSuccess('保存成功，处方已重新进入待审核')
        }
        
        showEdit.value = false
        getLists()
    } catch (error) {
        console.error(error)
    } finally {
        submitLoading.value = false
    }
}

// 删除处方
const handleDelete = async (id: number) => {
    await feedback.confirm('确定要删除该处方吗？')
    await prescriptionDelete({ id })
    feedback.msgSuccess('删除成功')
    getLists()
}

onMounted(async () => {
    await loadRoleOptions()
    await loadRegionData()
    await loadServicePackageOptions()
    try {
        const list = await getDoctors()
        doctorOptions.value = Array.isArray(list) ? list : []
    } catch {
        doctorOptions.value = []
    }
    try {
        if (!userStore.userInfo?.id) {
            await userStore.getUserInfo()
        }
    } catch {
        /* 已登录页仍可无用户信息，保持默认筛选 */
    }
    getLists()
})
</script>

<style scoped lang="scss">
.prescription-list {
    padding: 12px 16px 20px;
}

/* 紧凑检索条：少占纵向空间，表格才是主体 */
.filter-toolbar {
    border-radius: 8px;
    border: 1px solid var(--el-border-color-lighter);
    background: var(--el-fill-color-blank);
}

.pl-toolbar {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.pl-toolbar__line {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 10px;
}

.pl-toolbar__line--second {
    padding-top: 2px;
    border-top: 1px dashed var(--el-border-color-lighter);
    justify-content: flex-start;
}

.pl-toolbar__k {
    flex-shrink: 0;
    font-size: 12px;
    font-weight: 500;
    color: var(--el-text-color-secondary);
    line-height: 1;
}

.pl-toolbar__sep {
    width: 1px;
    height: 18px;
    background: var(--el-border-color);
    opacity: 0.7;
    margin: 0 2px;
}

.pl-toolbar__rg {
    flex-wrap: wrap;
}

.pl-toolbar__rg :deep(.el-radio-button__inner) {
    padding: 5px 10px;
    font-size: 12px;
}

/* 审核人员最常用：待审核 */
.pl-toolbar__rg--audit :deep(.pl-audit-pending-btn .el-radio-button__inner) {
    font-weight: 600;
    padding: 6px 14px;
    font-size: 13px;
}

.pl-toolbar__rg--audit :deep(.pl-audit-pending-btn:not(.is-active) .el-radio-button__inner) {
    color: var(--el-color-primary);
    border-color: var(--el-color-primary-light-5);
    background: var(--el-color-primary-light-9);
}

.pl-toolbar__rg--audit :deep(.pl-audit-pending-btn.is-active .el-radio-button__inner) {
    background: var(--el-color-primary) !important;
    border-color: var(--el-color-primary) !important;
    color: #fff !important;
    box-shadow: none;
}

.pl-toolbar__range {
    flex: 1 1 240px;
    min-width: 220px;
    max-width: 380px;
}

.pl-toolbar__range :deep(.el-date-editor) {
    width: 100%;
}

.pl-toolbar__range :deep(.el-date-editor.el-input__wrapper) {
    min-height: 30px;
    padding: 2px 8px;
}

.pl-toolbar__form {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0 4px;
    flex: 1;
    min-width: 0;
}

.pl-toolbar__form :deep(.el-form-item) {
    margin-bottom: 0;
    margin-right: 12px;
}

.pl-toolbar__form :deep(.el-form-item__label) {
    font-size: 12px;
    padding-right: 6px;
}

.pl-toolbar__input {
    width: 132px;
}

.pl-toolbar__select {
    width: 108px;
}

.pl-toolbar__select--doctors {
    width: min(320px, 100%);
    min-width: 200px;
}

.pl-toolbar__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-left: auto;
}

.table-card {
    border-radius: 8px;
    border: 1px solid var(--el-border-color-lighter);
}

.pl-table-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
}

.pl-table-head__title {
    font-size: 16px;
    font-weight: 600;
    color: var(--el-text-color-primary);
    letter-spacing: 0.02em;
}

/* 查看处方：互联网医院处方笺（对齐诊间 tcm-prescription 打印版式） */
.cf-prescription-drawer :deep(.el-drawer__body) {
    padding-top: 8px;
    overflow-y: auto;
}

/* ============================================================
 * 处方笺（A4 药房联）样式
 * 严格按 A4：210mm × 297mm，padding 12mm
 * ============================================================ */
.rx-wrap {
    min-height: 160px;
    background: #f5f6f8;
    padding: 12px;
    margin: -20px;
}

.rx-toolbar {
    display: flex;
    align-items: center;
    gap: 8px;
    background: #fff;
    border: 1px solid var(--el-border-color-lighter);
    border-radius: 6px;
    padding: 8px 12px;
    margin-bottom: 10px;

    .flex-1 { flex: 1; }
}

.rx-status {
    margin-bottom: 10px;
    padding: 8px 12px;
    border-radius: 4px;
    font-size: 13px;
    line-height: 1.6;
}

.rx-status-danger {
    background: #fef0f0;
    color: #b91c1c;
    border: 1px solid #fecaca;
}

/* === A4 纸 === */
.rx-paper {
    width: 210mm;
    min-height: 297mm;
    margin: 0 auto;
    background: #fff;
    box-sizing: border-box;
    padding: 8mm 10mm;
    color: #1f1f1f;
    font-size: 13px;
    line-height: 1.5;
    font-family: "Microsoft YaHei", "PingFang SC", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    box-shadow: 0 0 0 1px #d6d6d6, 0 6px 24px rgba(0, 0, 0, 0.06);
    /* 防止 html2canvas 把内部表格裁切 */
    overflow: visible;
}

/* === 顶部告知 === */
.rx-notice {
    display: flex;
    align-items: center;
    justify-content: space-between;
    background: #f3f4f6;
    border: 1px solid #e5e7eb;
    padding: 6px 10px;
    border-radius: 2px;
    font-size: 12px;
    color: #1f1f1f;
    margin-bottom: 6px;

    .rx-notice-text {
        flex: 1;
    }

    .rx-notice-meta {
        display: inline-flex;
        gap: 24px;
        white-space: nowrap;
    }
}

/* === 患者信息表 === */
.rx-info {
    border: 1px solid #c8c8c8;
    border-bottom: none;
}

.rx-info-row {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    border-bottom: 1px solid #c8c8c8;
}

.rx-info-row-full {
    grid-template-columns: 1fr;
}

.rx-info-cell {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 10px;
    font-size: 13px;
    border-right: 1px solid #c8c8c8;
    min-height: 32px;

    &:last-child { border-right: none; }

    .rx-key {
        color: #1f1f1f;
        flex-shrink: 0;
    }

    .rx-val {
        flex: 1;
        min-width: 0;
        word-break: break-all;
    }
}

/* === Rp 区域 + 水印 === */
.rx-rp {
    position: relative;
    border-left: 1px solid #c8c8c8;
    border-right: 1px solid #c8c8c8;
    padding: 8px 10px 16px;
    overflow: hidden;
    box-sizing: border-box;
    width: 100%;
}

.rx-watermark {
    position: absolute;
    /* 不使用 inset 简写：html2canvas 对 inset 解析不稳定，
     * 会导致水印容器尺寸异常，进而影响内层网格对齐 */
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 88px;
    font-weight: 700;
    color: rgba(0, 0, 0, 0.06);
    transform: rotate(-22deg);
    letter-spacing: 0.18em;
    pointer-events: none;
    user-select: none;
    z-index: 0;
}

.rx-rp-head {
    display: grid;
    grid-template-columns: 36px 1fr;
    align-items: end;
    column-gap: 8px;
    padding-bottom: 4px;
    border-bottom: 1px solid #d4d4d4;
    margin-bottom: 6px;
    position: relative;
    z-index: 1;
    width: 100%;
    box-sizing: border-box;
}

.rx-rp-label {
    font-size: 16px;
    font-weight: 700;
    color: #1f1f1f;
    line-height: 1;
}

.rx-rp-cols-head {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: 24px;
    width: 100%;
    box-sizing: border-box;
    min-width: 0;
}

/* 注意：列内 1fr 64px 与 .rx-herb-cell 完全一致，
 * 配合 .rx-herbs 与 .rx-rp-cols-head 同样的左侧 44px 缩进，
 * 即可保证「用药 (单剂)」与药材名、「总量」与总量数字精确对齐。 */
.rx-rp-col-head {
    display: grid;
    grid-template-columns: 1fr 64px;
    column-gap: 8px;
    font-size: 13px;
    color: #1f1f1f;
    min-width: 0;

    & > span:last-child {
        text-align: right;
    }
}

.rx-herbs {
    /* 与 .rx-rp-head 中 Rp. 列(36px) + column-gap(8px) 等宽缩进，
     * 这样下方两列的左右边界与表头两列完全对齐。 */
    padding-left: 44px;
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: 24px;
    row-gap: 6px;
    position: relative;
    z-index: 1;
    width: 100%;
    box-sizing: border-box;
}

.rx-herb-section-label {
    grid-column: 1 / -1;
    font-size: 12px;
    font-weight: 600;
    color: #409eff;
    line-height: 1.4;
}

.rx-herb-section-label--aux {
    color: #e6a23c;
    margin-top: 4px;
}

.herb-formula-block__head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
}

.usage-formula-title {
    font-size: 13px;
    font-weight: 600;
    margin: 8px 0 4px;
    color: #409eff;
}

.usage-formula-title--aux {
    color: #e6a23c;
    margin-top: 12px;
}

.rx-herb-cell {
    display: grid;
    grid-template-columns: 1fr 64px;
    column-gap: 8px;
    font-size: 13px;
    line-height: 1.85;
    min-width: 0;
}

.rx-herb-name {
    color: #1f1f1f;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.rx-herb-total {
    color: #1f1f1f;
    text-align: right;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* === 服法 / 备注 文本块 === */
.rx-text {
    border: 1px solid #c8c8c8;
    border-top: none;
    padding: 10px 12px;
    font-size: 13px;
    line-height: 1.85;

    p { margin: 0; }

    .rx-text-warn {
        color: #d72424;
        font-weight: 600;
    }
}

/* === 底部表格 === */
.rx-bottom {
    border: 1px solid #c8c8c8;
    border-top: none;
}

.rx-bot-row {
    display: grid;
    border-bottom: 1px solid #c8c8c8;

    &:last-child { border-bottom: none; }
}

.rx-bot-row-1 {
    /* 类型/剂数/单剂量 三个 meta 列适当加宽，
     * 避免"浓缩丸-浓缩水丸"被强制折行后把整行挤错位 */
    grid-template-columns: 1.4fr 0.6fr 0.6fr 0.6fr 0.6fr 1.7fr 0.95fr 1.25fr;
    min-height: 70px;
}

.rx-bot-row-2 {
    grid-template-columns: repeat(6, 1fr);
}

/* 默认：单行内容左对齐、上下居中（适配 类型/剂数/单剂量/费用 等格子）。
 * 需要"标题置顶 + 签名留白"的格子（医师/审方/配药/复核/发药）请加 .rx-bot-stack。
 * 这样无需任何 !important 反向覆盖，html2canvas/原生渲染表现一致。 */
.rx-bot-cell {
    border-right: 1px solid #c8c8c8;
    padding: 6px 10px;
    font-size: 12px;
    color: #1f1f1f;
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: flex-start;
    min-height: 32px;
    box-sizing: border-box;

    &:last-child { border-right: none; }
}

.rx-bot-stack {
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-start;
}

.rx-bot-label {
    font-size: 13px;
    color: #1f1f1f;
    margin-bottom: 4px;
}

.rx-bot-doctor {
    .rx-bot-doctor-body {
        flex: 1;
        display: flex;
        align-items: center;
        gap: 6px;
        min-height: 36px;
    }

    .rx-bot-doctor-name {
        font-size: 13px;
        color: #1f1f1f;
    }

    .rx-bot-sign-img {
        max-height: 40px;
        max-width: 110px;
        object-fit: contain;
    }
}

.rx-bot-meta {
    flex-wrap: nowrap;

    .rx-bot-meta-key {
        color: #1f1f1f;
        margin-right: 6px;
        white-space: nowrap;
        flex-shrink: 0;
        line-height: 1.4;
    }

    .rx-bot-meta-val {
        font-weight: 500;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        min-width: 0;
        line-height: 1.4;
    }
}

.rx-fee {
    font-size: 13px;
    line-height: 1.4;
    padding: 8px 10px;

    .rx-fee-key {
        color: #1f1f1f;
        margin-right: 6px;
        white-space: nowrap;
    }

    .rx-fee-val {
        font-variant-numeric: tabular-nums;
        white-space: nowrap;
    }
}

.rx-fee-total {
    font-weight: 700;
    background: #fafafa;

    .rx-fee-val { font-weight: 700; }
}

/* === 审核痕迹（不打印） === */
.rx-audit {
    margin-top: 12px;
    padding: 8px 12px;
    background: #fafafa;
    border: 1px dashed #d4d4d4;
    color: #6b7280;
    font-size: 12px;
    line-height: 1.6;
    border-radius: 4px;
}

/* 打印控制规则放到非 scoped 的全局 style 中，参见底部 <style> */

/* 创建业务订单弹窗：宽松留白、默认字号、卡片化信息区 */
.create-order-dialog {
    :deep(.el-dialog__header) {
        padding: 20px 24px 12px;
        margin-right: 0;
    }

    :deep(.el-dialog__title) {
        font-size: 18px;
        font-weight: 600;
        letter-spacing: 0.02em;
    }

    :deep(.el-dialog__body) {
        padding: 8px 24px 20px;
        max-height: calc(100vh - 200px);
        overflow: hidden;
    }

    :deep(.el-dialog__footer) {
        padding: 16px 24px 20px;
        border-top: 1px solid var(--el-border-color-lighter);
        background: var(--el-fill-color-blank);
    }
}

.create-order-dialog__inner {
    display: flex;
    flex-direction: column;
    gap: 0;
}

.create-order-rx-card {
    border-radius: 10px;
    border: 1px solid var(--el-color-primary-light-5);
    background: linear-gradient(135deg, var(--el-color-primary-light-9) 0%, var(--el-fill-color-blank) 100%);
    padding: 16px 18px;
    margin-bottom: 20px;
    box-shadow: 0 1px 2px rgb(0 0 0 / 4%);
}

.create-order-rx-card__head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px 14px;
    margin-bottom: 10px;
}

.create-order-rx-card__badge {
    display: inline-flex;
    align-items: center;
    padding: 4px 10px;
    border-radius: 6px;
    font-size: 12px;
    font-weight: 600;
    color: #fff;
    background: var(--el-color-primary);
    letter-spacing: 0.04em;
}

.create-order-rx-card__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 12px;
    font-size: 14px;
    color: var(--el-text-color-regular);
}

.create-order-rx-card__id {
    font-weight: 600;
    color: var(--el-text-color-primary);
}

.create-order-rx-card__sn {
    padding: 2px 8px;
    border-radius: 4px;
    background: var(--el-fill-color);
    font-size: 13px;
    color: var(--el-text-color-secondary);
}

.create-order-rx-card__patient {
    font-weight: 500;
    color: var(--el-text-color-primary);
}

.create-order-rx-card__herbs {
    font-size: 13px;
    line-height: 1.55;
    color: var(--el-text-color-secondary);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    cursor: default;
    padding-top: 2px;
}

.create-order-steps {
    margin-bottom: 8px;
    padding: 8px 12px 4px;

    :deep(.el-step__title) {
        font-size: 14px;
        font-weight: 500;
        line-height: 1.4;
    }

    :deep(.el-step__description) {
        font-size: 12px;
        margin-top: 4px;
        line-height: 1.35;
        padding-right: 6px;
    }

    :deep(.el-step__head) {
        padding-right: 8px;
    }

    :deep(.el-step.is-horizontal .el-step__line) {
        top: 14px;
    }
}

.create-order-step-lead {
    margin: 0 0 20px;
    padding: 12px 16px;
    font-size: 13px;
    line-height: 1.6;
    color: var(--el-text-color-secondary);
    background: var(--el-fill-color-light);
    border-radius: 8px;
    border-left: 3px solid var(--el-color-primary-light-5);
}

.create-order-step-panel {
    max-height: min(56vh, 480px);
    overflow-y: auto;
    overflow-x: hidden;
    padding: 4px 8px 12px 4px;
    margin-right: -4px;
}

.create-order-step-panel__row-after-bar {
    margin-top: 20px;
}

.create-order-unit-suffix {
    flex-shrink: 0;
    font-size: 13px;
    color: var(--el-text-color-secondary);
    padding-left: 4px;
}

.create-order-footer {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    width: 100%;
}

.create-order-footer__hint {
    flex: 1;
    min-width: 200px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    font-size: 13px;
    line-height: 1.5;
    color: var(--el-text-color-secondary);
}

.create-order-footer__step {
    color: var(--el-text-color-placeholder);
}

.create-order-footer__warn {
    color: var(--el-color-warning);
    font-weight: 500;
}

.create-order-footer__actions {
    flex-shrink: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    justify-content: flex-end;
}

.create-order-deposit-bar {
    display: flex;
    align-items: stretch;
    border-radius: 10px;
    border: 1px solid var(--el-border-color-lighter);
    overflow: hidden;
    font-size: 13px;
    box-shadow: 0 1px 2px rgb(0 0 0 / 4%);
}

.create-order-deposit-bar__cell {
    flex: 1;
    padding: 16px 20px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    background: var(--el-fill-color-light);

    strong {
        font-size: 20px;
        font-weight: 600;
        color: var(--el-text-color-primary);
        letter-spacing: 0.02em;
    }
}

.create-order-deposit-bar__label {
    font-size: 13px;
    color: var(--el-text-color-secondary);
}

.create-order-deposit-bar__sub {
    font-size: 12px;
    color: var(--el-text-color-placeholder);
}

.create-order-deposit-bar__sep {
    width: 1px;
    background: var(--el-border-color-lighter);
    flex-shrink: 0;
}

.create-order-deposit-bar.is-ok .create-order-deposit-bar__cell:last-child strong {
    color: var(--el-color-success);
}

.create-order-deposit-bar.is-warn .create-order-deposit-bar__cell:last-child strong {
    color: var(--el-color-danger);
}

.create-order-pay-hint {
    font-size: 12px;
    line-height: 1.55;
    margin-top: 8px;
    color: var(--el-text-color-secondary);
}

.create-order-form {
    :deep(.el-form-item) {
        margin-bottom: 20px;
    }

    :deep(.el-form-item__label) {
        font-size: 14px;
        padding-right: 12px;
    }

    :deep(.el-input__inner),
    :deep(.el-textarea__inner) {
        font-size: 14px;
    }
}

.create-order-form-item--inline-num {
    :deep(.el-form-item__content) {
        line-height: normal;
    }
}

.signature-pad-wrap {
    width: 100%;
    max-width: 600px;
    border: 1px solid #dcdfe6;
    border-radius: 4px;
    overflow: hidden;
    background: #fff;

    .signature-canvas {
        display: block;
        cursor: crosshair;
        touch-action: none;
    }

    .signature-actions {
        padding: 8px;
        border-top: 1px solid #ebeef5;
    }
}
</style>

<!-- 全局打印样式（不能 scoped，否则 body * 不生效） -->
<style>
@media print {
    body * { visibility: hidden !important; }

    .rx-paper, .rx-paper * { visibility: visible !important; }

    .rx-paper {
        position: fixed !important;
        left: 0 !important;
        top: 0 !important;
        width: 210mm !important;
        height: 297mm !important;
        margin: 0 !important;
        padding: 8mm 10mm !important;
        box-shadow: none !important;
        page-break-after: always;
    }

    @page {
        size: A4;
        margin: 0;
    }
}
</style>
