This commit is contained in:
Your Name
2026-04-18 11:08:44 +08:00
parent 91624bf3de
commit 7184640f8e
251 changed files with 1529 additions and 745 deletions
+538 -261
View File
@@ -799,50 +799,50 @@
<el-dialog
v-model="createOrderVisible"
title="创建业务订单"
width="850px"
width="940px"
top="4vh"
:close-on-click-modal="false"
@closed="resetCreateOrderForm"
class="create-order-dialog"
>
<!-- 关联处方信息卡片 -->
<div v-if="createOrderPrescription" class="mb-4 rounded-lg border border-blue-100 bg-blue-50 p-3">
<div class="flex items-start gap-2">
<div class="flex-shrink-0 mt-0.5">
<svg class="w-4 h-4 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
</div>
<div class="flex-1 min-w-0">
<div class="text-xs font-medium text-blue-900 mb-0.5">关联处方</div>
<div class="text-xs text-blue-700">
ID {{ createOrderPrescription.id }}
<span v-if="createOrderPrescription.sn"> · {{ createOrderPrescription.sn }}</span>
· {{ createOrderPrescription.patient_name || '—' }}
</div>
<div class="text-xs text-blue-600 mt-1 line-clamp-1">
{{ createOrderHerbSummary }}
<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>
</div>
<el-form
ref="createOrderFormRef"
:model="createOrderForm"
:rules="createOrderRules"
label-width="90px"
class="create-order-form"
>
<!-- 患者与收货信息 -->
<div class="form-section">
<div class="section-title">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" />
</svg>
<span>患者与收货</span>
</div>
<div class="section-content">
<el-row :gutter="16">
<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
@@ -866,12 +866,12 @@
</el-col>
<el-col :span="12">
<el-form-item label="收货人" prop="recipient_name">
<el-input v-model="createOrderForm.recipient_name" placeholder="收货人姓名" maxlength="50" />
<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-input v-model="createOrderForm.recipient_phone" placeholder="物流联系" maxlength="20" />
</el-form-item>
</el-col>
<el-col :span="24">
@@ -880,7 +880,7 @@
v-model="createOrderForm.region"
:options="regionOptions"
:props="{ value: 'name', label: 'name', children: 'children', emitPath: true, checkStrictly: false }"
placeholder="请选择省/市/区"
placeholder="省 / 市 / 区"
clearable
filterable
class="w-full"
@@ -893,45 +893,39 @@
<el-input
v-model="createOrderForm.shipping_address"
type="textarea"
:rows="2"
placeholder="请输入街道、门牌号等详细地址"
:rows="3"
placeholder="街道、小区、门牌号等详细地址"
maxlength="200"
show-word-limit
/>
</el-form-item>
</el-col>
</el-row>
</div>
</div>
<!-- 服务信息 -->
<div class="form-section">
<div class="section-title">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
</svg>
<span>服务信息</span>
</div>
<div class="section-content">
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="是否复诊">
<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 :span="8">
<el-form-item label="用药疗程">
<el-input-number
v-model="createOrderForm.medication_days"
:min="1"
:max="999"
:step="1"
placeholder="天数"
class="w-full"
/>
<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 :span="8">
<el-col :xs="24" :sm="8">
<el-form-item label="上次医生">
<el-input v-model="createOrderForm.prev_staff" placeholder="可选" maxlength="100" />
</el-form-item>
@@ -943,121 +937,98 @@
</el-col>
<el-col :span="12">
<el-form-item label="服务套餐">
<el-input v-model="createOrderForm.service_package" placeholder="可选" maxlength="100" />
</el-form-item>
</el-col>
</el-row>
</div>
</div>
<!-- 物流信息 -->
<!-- <div class="form-section">
<div class="section-title">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4" />
</svg>
<span>物流信息</span>
</div>
<div class="section-content">
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="快递公司">
<el-select v-model="createOrderForm.express_company" placeholder="查物流用" class="w-full">
<el-option label="自动识别" value="auto" />
<el-option label="顺丰速运" value="sf" />
<el-option label="京东快递" value="jd" />
<el-option label="极兔速递" value="jt" />
<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="12">
<el-form-item label="快递单号">
<el-input v-model="createOrderForm.tracking_number" placeholder="可创建后补录" maxlength="80" />
<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> -->
<!-- 关联收款 -->
<div class="form-section">
<div class="section-title">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 9V7a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2m2 4h10a2 2 0 002-2v-6a2 2 0 00-2-2H9a2 2 0 00-2 2v6a2 2 0 002 2zm7-5a2 2 0 11-4 0 2 2 0 014 0z" />
</svg>
<span>关联收款</span>
</div>
<div class="section-content">
<el-form-item label="关联支付单">
<el-select
v-model="createOrderForm.pay_order_ids"
class="w-full"
multiple
collapse-tags
collapse-tags-tooltip
placeholder="多选本诊单下的支付单"
: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="text-xs text-gray-500 mt-1.5 leading-relaxed">
主管或本诊单医助可见该诊单全部支付单(待支付/已支付),否则仅本人创建的收款单。已被其他有效业务订单占用的支付单不会出现在此列表。
</div>
</el-form-item>
</div>
</div>
<!-- 金额信息 -->
<div class="form-section">
<div class="section-title">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span>金额信息</span>
</div>
<div class="section-content">
<!-- 金额概览卡片 -->
<div class="mb-3 rounded-lg border border-gray-200 bg-gray-50 p-3">
<div class="grid grid-cols-2 gap-3">
<div>
<div class="text-xs text-gray-500 mb-0.5">定金门槛</div>
<div class="text-base font-semibold text-gray-900">
¥{{ formatPoDepositMoney(createOrderDepositMin) }}
</div>
<div class="text-xs text-gray-400 mt-0.5">
{{ createOrderDepositMin > 0 ? '订单和支付单总金额须 ≥ 此值' : '未设置' }}
</div>
</div>
<div>
<div class="text-xs text-gray-500 mb-0.5">已选收款单</div>
<div class="text-base font-semibold" :class="createOrderLinkedPaidTotal >= createOrderDepositMin ? 'text-green-600' : 'text-red-600'">
¥{{ formatPoDepositMoney(createOrderLinkedPaidTotal) }}
</div>
<div class="text-xs mt-0.5" :class="createOrderLinkedPaidTotal >= createOrderDepositMin ? 'text-green-600' : 'text-red-600'">
{{ createOrderLinkedPaidTotal >= createOrderDepositMin ? '✓ 已达标' : '✗ 未达标' }}
</div>
</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="16">
<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">
@@ -1072,14 +1043,15 @@
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="订单总金额" prop="amount">
<el-form-item label="总金额" prop="amount">
<el-input-number
v-model="createOrderForm.amount"
:min="createOrderAmountInputMin"
:step="0.01"
:precision="2"
class="w-full"
placeholder="业务订单金额(元)"
controls-position="right"
placeholder="元"
/>
</el-form-item>
</el-col>
@@ -1091,47 +1063,54 @@
:step="0.01"
:precision="2"
class="w-full"
placeholder="仅财务角色可见"
controls-position="right"
placeholder="财务可见"
/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注">
<el-input
v-model="createOrderForm.remark_extra"
type="textarea"
:rows="3"
placeholder="选填,对内说明"
maxlength="200"
show-word-limit
/>
</el-form-item>
</el-col>
</el-row>
</div>
</div>
<!-- 备注 -->
<div class="form-section">
<div class="section-title">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-3l-4 4z" />
</svg>
<span>备注说明</span>
</div>
<div class="section-content">
<el-form-item label="备注补充">
<el-input
v-model="createOrderForm.remark_extra"
type="textarea"
:rows="2"
placeholder="其他说明(可选)"
maxlength="200"
show-word-limit
/>
</el-form-item>
</div>
</div>
</el-form>
</div>
<template #footer>
<div class="flex items-center justify-between">
<div class="text-xs text-gray-500">
<span v-if="createOrderDepositMin > 0" class="text-amber-600">
提示:订单金额和关联支付单总金额须 ≥ ¥{{ formatPoDepositMoney(createOrderDepositMin) }}
<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="flex gap-2">
<el-button @click="createOrderVisible = false">取消</el-button>
<el-button type="primary" :loading="createOrderSubmitLoading" @click="submitCreateOrderFromPrescription">
<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>
@@ -1177,6 +1156,7 @@ import {
getDoctors
} from '@/api/tcm'
import { searchPatients as searchPatientsAPI } from '@/api/order'
import { getDictData } from '@/api/app'
import { roleAll } from '@/api/perms/role'
import { usePaging } from '@/hooks/usePaging'
import useUserStore from '@/stores/modules/user'
@@ -1239,6 +1219,21 @@ const auditLoading = ref(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)
@@ -1276,7 +1271,7 @@ const createOrderForm = reactive({
medication_days: undefined as number | undefined,
prev_staff: '',
service_channel: '',
service_package: '',
service_package: [] as string[],
express_company: 'auto',
tracking_number: '',
fee_type: 3,
@@ -1289,6 +1284,9 @@ const createOrderForm = reactive({
// 省市区数据(简化版,实际项目中应该从 API 获取或使用完整的省市区数据)
const regionOptions = ref([])
/** 服务套餐(字典 server_order,与业务订单编辑一致) */
const servicePackageOptions = ref<Array<{ name: string; value: string }>>([])
// 转换省市区数据格式
const transformRegionData = (data: any[]) => {
return data.map((province: any) => ({
@@ -1418,6 +1416,15 @@ const loadRegionData = async () => {
}
}
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)
@@ -1444,29 +1451,46 @@ const createOrderAmountInputMin = computed(() => {
return 0
})
const createOrderRules: 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'
}
]
}
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
@@ -1477,6 +1501,7 @@ const createOrderHerbSummary = computed(() => {
})
function resetCreateOrderForm() {
createOrderStep.value = 0
createOrderForm.patient_id = ''
createOrderForm.recipient_name = ''
createOrderForm.recipient_phone = ''
@@ -1485,7 +1510,7 @@ function resetCreateOrderForm() {
createOrderForm.medication_days = undefined
createOrderForm.prev_staff = ''
createOrderForm.service_channel = ''
createOrderForm.service_package = ''
createOrderForm.service_package = []
createOrderForm.express_company = 'auto'
createOrderForm.tracking_number = ''
createOrderForm.fee_type = 3
@@ -1617,8 +1642,32 @@ function onCreateOrderPatientChange(id: number | string) {
}
}
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
@@ -1632,7 +1681,10 @@ async function submitCreateOrderFromPrescription() {
is_follow_up: createOrderForm.is_follow_up,
prev_staff: createOrderForm.prev_staff || '',
service_channel: createOrderForm.service_channel || '',
service_package: createOrderForm.service_package || '',
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,
@@ -2268,6 +2320,7 @@ const handleDelete = async (id: number) => {
onMounted(async () => {
await loadRoleOptions()
await loadRegionData()
await loadServicePackageOptions()
try {
const list = await getDoctors()
doctorOptions.value = Array.isArray(list) ? list : []
@@ -2614,52 +2667,276 @@ onMounted(async () => {
line-height: 1.65;
}
/* 创建订单表单样式 */
/* 创建业务订单弹窗宽松留白默认字号卡片化信息区 */
.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-y: auto;
padding: 16px 20px;
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-form {
.form-section {
margin-bottom: 20px;
&:last-child {
margin-bottom: 0;
}
.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;
}
.section-title {
display: flex;
align-items: center;
gap: 6px;
font-size: 13px;
: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);
margin-bottom: 12px;
padding-bottom: 6px;
border-bottom: 1px solid var(--el-border-color-lighter);
svg {
color: var(--el-color-primary);
width: 14px;
height: 14px;
}
letter-spacing: 0.02em;
}
.section-content {
padding-left: 2px;
}
}
.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: 14px;
margin-bottom: 20px;
}
:deep(.el-form-item__label) {
font-size: 13px;
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;
}
}
</style>
File diff suppressed because it is too large Load Diff