订单
This commit is contained in:
@@ -326,6 +326,16 @@ export function prescriptionOrderComplete(params: { id: number }) {
|
||||
return request.post({ url: '/tcm.prescriptionOrder/complete', params })
|
||||
}
|
||||
|
||||
/** 甘草药管家:中药处方下单(服务端 CTM_PREVIEW → CTM_SUBMIT_RECIPEL) */
|
||||
export function prescriptionOrderSubmitGancaoRecipel(params: { id: number }) {
|
||||
return request.post({ url: '/tcm.prescriptionOrder/submitGancaoRecipel', params })
|
||||
}
|
||||
|
||||
/** 甘草药管家:预下单测试(仅 CTM_PREVIEW,不提交订单) */
|
||||
export function prescriptionOrderPreviewGancaoRecipel(params: { id: number; dose_count?: number; medication_days?: number }) {
|
||||
return request.post({ url: '/tcm.prescriptionOrder/previewGancaoRecipel', params })
|
||||
}
|
||||
|
||||
/** 订单操作日志 */
|
||||
export function prescriptionOrderLogs(params: { id: number }) {
|
||||
return request.get({ url: '/tcm.prescriptionOrder/logs', params })
|
||||
|
||||
@@ -135,11 +135,72 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<!-- 用量字段 -->
|
||||
<el-col :span="12">
|
||||
<el-form-item label="用量" prop="dosage_amount">
|
||||
<!-- 浓缩水丸:1-10g 下拉选择 -->
|
||||
<el-select
|
||||
v-if="formData.prescription_type === '浓缩水丸'"
|
||||
v-model="formData.dosage_amount"
|
||||
placeholder="请选择用量"
|
||||
class="!w-32"
|
||||
>
|
||||
<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="formData.prescription_type === '饮片'"
|
||||
v-model="formData.dosage_amount"
|
||||
placeholder="请选择用量"
|
||||
class="!w-32"
|
||||
>
|
||||
<el-option label="50ml" :value="50" />
|
||||
<el-option label="100ml" :value="100" />
|
||||
<el-option label="150ml" :value="150" />
|
||||
<el-option label="200ml" :value="200" />
|
||||
<el-option label="250ml" :value="250" />
|
||||
</el-select>
|
||||
<!-- 其他类型:自由输入 -->
|
||||
<el-input-number
|
||||
v-else
|
||||
v-model="formData.dosage_amount"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
class="!w-32"
|
||||
/>
|
||||
<span v-if="formData.prescription_type !== '浓缩水丸' && formData.prescription_type !== '饮片'" class="ml-2">{{ formData.dosage_unit }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<!-- 饮片代煎选项 -->
|
||||
<el-col v-if="formData.prescription_type === '饮片'" :span="12">
|
||||
<el-form-item label="是否代煎" prop="need_decoction">
|
||||
<el-radio-group v-model="formData.need_decoction">
|
||||
<el-radio :label="true">代煎</el-radio>
|
||||
<el-radio :label="false">不代煎</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="服用天数" prop="usage_days">
|
||||
<el-input-number v-model="formData.usage_days" :min="1" :max="365" class="!w-full" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="每天几次" prop="times_per_day">
|
||||
<el-input-number v-model="formData.times_per_day" :min="1" :max="10" class="!w-full" placeholder="每天服用次数" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!-- <el-col :span="8">
|
||||
<el-form-item label="剂数" prop="dose_count">
|
||||
<el-input-number v-model="formData.dose_count" :min="1" :max="999" class="!w-full" />
|
||||
@@ -319,7 +380,7 @@
|
||||
<div class="prescription-footer">
|
||||
<div class="footer-left">
|
||||
<div class="footer-dosage">
|
||||
服用{{ savedPrescription.usage_days || savedPrescription.dose_count }}天, {{ savedPrescription.prescription_type }}
|
||||
服用{{ savedPrescription.usage_days || savedPrescription.dose_count }}天{{ savedPrescription.times_per_day ? ',每天' + savedPrescription.times_per_day + '次' : '' }}, {{ savedPrescription.prescription_type }}
|
||||
{{ savedPrescription.usage_instruction }}
|
||||
|
||||
</div>
|
||||
@@ -577,6 +638,9 @@ interface PrescriptionForm {
|
||||
appointment_id: number
|
||||
prescription_name: string
|
||||
prescription_type: string
|
||||
dosage_amount: number | undefined // 用量数值
|
||||
dosage_unit: string // 用量单位 (g 或 ml)
|
||||
need_decoction: boolean // 是否代煎(仅饮片)
|
||||
patient_name: string
|
||||
gender: number
|
||||
gender_desc: string
|
||||
@@ -594,6 +658,7 @@ interface PrescriptionForm {
|
||||
dose_count: number
|
||||
dose_unit: string
|
||||
usage_days: number
|
||||
times_per_day: number
|
||||
usage_instruction: string
|
||||
usage_time: string
|
||||
usage_way: string
|
||||
@@ -653,6 +718,9 @@ const formData = reactive<PrescriptionForm>({
|
||||
appointment_id: 0,
|
||||
prescription_name: '',
|
||||
prescription_type: '浓缩水丸',
|
||||
dosage_amount: 1,
|
||||
dosage_unit: 'g',
|
||||
need_decoction: false,
|
||||
patient_name: '',
|
||||
gender: 0,
|
||||
gender_desc: '女',
|
||||
@@ -670,6 +738,7 @@ const formData = reactive<PrescriptionForm>({
|
||||
dose_count: 1,
|
||||
dose_unit: '剂',
|
||||
usage_days: 7,
|
||||
times_per_day: 2,
|
||||
usage_instruction: '水煎服,一日二次',
|
||||
usage_time: '饭前',
|
||||
usage_way: '温水送服',
|
||||
@@ -1054,6 +1123,23 @@ watch(showLibraryDialog, (newVal) => {
|
||||
}
|
||||
})
|
||||
|
||||
// 监听处方类型变化,自动调整用量单位和默认值
|
||||
watch(() => formData.prescription_type, (newType) => {
|
||||
if (newType === '浓缩水丸') {
|
||||
formData.dosage_unit = 'g'
|
||||
formData.dosage_amount = 1
|
||||
formData.need_decoction = false
|
||||
} else if (newType === '饮片') {
|
||||
formData.dosage_unit = 'ml'
|
||||
formData.dosage_amount = 50
|
||||
// need_decoction 保持用户选择
|
||||
} else {
|
||||
formData.dosage_unit = 'g'
|
||||
formData.dosage_amount = undefined
|
||||
formData.need_decoction = false
|
||||
}
|
||||
})
|
||||
|
||||
const handleSave = async () => {
|
||||
if (!formData.clinical_diagnosis?.trim()) {
|
||||
feedback.msgWarning('请输入临床诊断')
|
||||
@@ -1101,7 +1187,11 @@ const handleSave = async () => {
|
||||
herbs: formData.herbs,
|
||||
dose_count: formData.dose_count,
|
||||
dose_unit: formData.dose_unit,
|
||||
dosage_amount: formData.dosage_amount,
|
||||
dosage_unit: formData.dosage_unit,
|
||||
need_decoction: formData.need_decoction,
|
||||
usage_days: formData.usage_days,
|
||||
times_per_day: formData.times_per_day,
|
||||
usage_instruction: formData.usage_instruction,
|
||||
usage_time: formData.usage_time,
|
||||
usage_way: formData.usage_way,
|
||||
|
||||
@@ -576,6 +576,66 @@
|
||||
<el-option label="汤剂" value="汤剂" />
|
||||
</el-select>
|
||||
</el-form-item> </el-col>
|
||||
|
||||
<!-- 用量字段 -->
|
||||
<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="150ml" :value="150" />
|
||||
<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="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 :span="8">
|
||||
<el-form-item label="每天几次" prop="times_per_day">
|
||||
<el-input-number v-model="editForm.times_per_day" :min="1" :max="10" class="!w-full" placeholder="每天服用次数" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="服用天数" prop="usage_days">
|
||||
<el-input-number
|
||||
@@ -795,12 +855,26 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="收货地址" prop="shipping_address">
|
||||
<el-form-item label="省市区" prop="region">
|
||||
<el-cascader
|
||||
v-model="createOrderForm.region"
|
||||
:options="regionOptions"
|
||||
:props="{ value: 'name', label: 'name', children: 'children', emitPath: false, 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="2"
|
||||
placeholder="完整收货地址"
|
||||
placeholder="请输入街道、门牌号等详细地址"
|
||||
maxlength="200"
|
||||
show-word-limit
|
||||
/>
|
||||
@@ -1176,6 +1250,7 @@ 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,
|
||||
@@ -1191,6 +1266,146 @@ const createOrderForm = reactive({
|
||||
pay_order_ids: [] as number[]
|
||||
})
|
||||
|
||||
// 省市区数据(简化版,实际项目中应该从 API 获取或使用完整的省市区数据)
|
||||
const regionOptions = ref([
|
||||
{
|
||||
name: '四川省',
|
||||
children: [
|
||||
{
|
||||
name: '成都市',
|
||||
children: [
|
||||
{ name: '锦江区' },
|
||||
{ name: '青羊区' },
|
||||
{ name: '金牛区' },
|
||||
{ name: '武侯区' },
|
||||
{ name: '成华区' },
|
||||
{ name: '龙泉驿区' },
|
||||
{ name: '青白江区' },
|
||||
{ name: '新都区' },
|
||||
{ name: '温江区' },
|
||||
{ name: '双流区' },
|
||||
{ name: '郫都区' },
|
||||
{ name: '新津区' },
|
||||
{ name: '都江堰市' },
|
||||
{ name: '彭州市' },
|
||||
{ name: '邛崃市' },
|
||||
{ name: '崇州市' },
|
||||
{ name: '简阳市' },
|
||||
{ name: '金堂县' },
|
||||
{ name: '大邑县' },
|
||||
{ name: '蒲江县' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: '绵阳市',
|
||||
children: [
|
||||
{ name: '涪城区' },
|
||||
{ name: '游仙区' },
|
||||
{ name: '安州区' },
|
||||
{ name: '江油市' },
|
||||
{ name: '三台县' },
|
||||
{ name: '盐亭县' },
|
||||
{ name: '梓潼县' },
|
||||
{ name: '北川羌族自治县' },
|
||||
{ name: '平武县' }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: '北京市',
|
||||
children: [
|
||||
{
|
||||
name: '北京市',
|
||||
children: [
|
||||
{ name: '东城区' },
|
||||
{ name: '西城区' },
|
||||
{ name: '朝阳区' },
|
||||
{ name: '丰台区' },
|
||||
{ name: '石景山区' },
|
||||
{ name: '海淀区' },
|
||||
{ name: '门头沟区' },
|
||||
{ name: '房山区' },
|
||||
{ name: '通州区' },
|
||||
{ name: '顺义区' },
|
||||
{ name: '昌平区' },
|
||||
{ name: '大兴区' },
|
||||
{ name: '怀柔区' },
|
||||
{ name: '平谷区' },
|
||||
{ name: '密云区' },
|
||||
{ name: '延庆区' }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: '上海市',
|
||||
children: [
|
||||
{
|
||||
name: '上海市',
|
||||
children: [
|
||||
{ name: '黄浦区' },
|
||||
{ name: '徐汇区' },
|
||||
{ name: '长宁区' },
|
||||
{ name: '静安区' },
|
||||
{ name: '普陀区' },
|
||||
{ name: '虹口区' },
|
||||
{ name: '杨浦区' },
|
||||
{ name: '闵行区' },
|
||||
{ name: '宝山区' },
|
||||
{ name: '嘉定区' },
|
||||
{ name: '浦东新区' },
|
||||
{ name: '金山区' },
|
||||
{ name: '松江区' },
|
||||
{ name: '青浦区' },
|
||||
{ name: '奉贤区' },
|
||||
{ name: '崇明区' }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: '广东省',
|
||||
children: [
|
||||
{
|
||||
name: '广州市',
|
||||
children: [
|
||||
{ name: '荔湾区' },
|
||||
{ name: '越秀区' },
|
||||
{ name: '海珠区' },
|
||||
{ name: '天河区' },
|
||||
{ name: '白云区' },
|
||||
{ name: '黄埔区' },
|
||||
{ name: '番禺区' },
|
||||
{ name: '花都区' },
|
||||
{ name: '南沙区' },
|
||||
{ name: '从化区' },
|
||||
{ name: '增城区' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: '深圳市',
|
||||
children: [
|
||||
{ name: '罗湖区' },
|
||||
{ name: '福田区' },
|
||||
{ name: '南山区' },
|
||||
{ name: '宝安区' },
|
||||
{ name: '龙岗区' },
|
||||
{ name: '盐田区' },
|
||||
{ name: '龙华区' },
|
||||
{ name: '坪山区' },
|
||||
{ name: '光明区' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
])
|
||||
|
||||
// 处理省市区选择变化
|
||||
const handleRegionChange = (value: string[]) => {
|
||||
console.log('选择的省市区:', value)
|
||||
}
|
||||
|
||||
const createOrderLinkedPaidTotal = computed(() => {
|
||||
const ids = new Set(createOrderForm.pay_order_ids.map((x) => Number(x)))
|
||||
let s = 0
|
||||
@@ -1454,6 +1669,9 @@ const slipDietaryText = computed(() => {
|
||||
const editForm = reactive({
|
||||
id: 0,
|
||||
prescription_type: '浓缩水丸',
|
||||
dosage_amount: 1 as number | undefined,
|
||||
dosage_unit: 'g',
|
||||
need_decoction: false,
|
||||
patient_name: '',
|
||||
gender: 1,
|
||||
age: 0,
|
||||
@@ -1483,7 +1701,25 @@ const editForm = reactive({
|
||||
diagnosis_id: 0,
|
||||
/** 列表带入:业务订单「处方审核」驳回(消费者处方本身可能仍为已通过) */
|
||||
business_prescription_audit_rejected: 0,
|
||||
business_prescription_audit_remark: ''
|
||||
business_prescription_audit_remark: '',
|
||||
times_per_day: 2
|
||||
})
|
||||
|
||||
// 监听处方类型变化,自动调整用量单位和默认值
|
||||
watch(() => editForm.prescription_type, (newType) => {
|
||||
if (newType === '浓缩水丸') {
|
||||
editForm.dosage_unit = 'g'
|
||||
editForm.dosage_amount = 1
|
||||
editForm.need_decoction = false
|
||||
} else if (newType === '饮片') {
|
||||
editForm.dosage_unit = 'ml'
|
||||
editForm.dosage_amount = 50
|
||||
// need_decoction 保持用户选择
|
||||
} else {
|
||||
editForm.dosage_unit = 'g'
|
||||
editForm.dosage_amount = undefined
|
||||
editForm.need_decoction = false
|
||||
}
|
||||
})
|
||||
|
||||
// 表单验证规则
|
||||
@@ -1863,6 +2099,9 @@ const handleEdit = (row: any) => {
|
||||
// 深拷贝数据到表单
|
||||
editForm.id = row.id
|
||||
editForm.prescription_type = row.prescription_type || '浓缩水丸'
|
||||
editForm.dosage_amount = row.dosage_amount ?? undefined
|
||||
editForm.dosage_unit = row.dosage_unit || ''
|
||||
editForm.need_decoction = row.need_decoction === 1 || row.need_decoction === true
|
||||
editForm.patient_name = row.patient_name || ''
|
||||
editForm.gender = row.gender ?? 1
|
||||
editForm.age = row.age ?? 0
|
||||
@@ -1877,6 +2116,7 @@ const handleEdit = (row: any) => {
|
||||
editForm.dose_count = row.dose_count ?? 7
|
||||
editForm.dose_unit = row.dose_unit || '剂'
|
||||
editForm.usage_days = row.usage_days ?? 7
|
||||
editForm.times_per_day = row.times_per_day ?? 2
|
||||
editForm.usage_instruction = row.usage_instruction || '水煎服,一日二次'
|
||||
editForm.usage_time = row.usage_time || '饭前'
|
||||
editForm.usage_way = row.usage_way || '温水送服'
|
||||
|
||||
@@ -184,6 +184,14 @@
|
||||
link
|
||||
@click="confirmWithdraw(row)"
|
||||
>撤回</el-button>
|
||||
<el-button
|
||||
v-if="canUploadGancaoRow(row)"
|
||||
v-perms="['tcm.prescriptionOrder/submitGancaoRecipel']"
|
||||
type="warning"
|
||||
link
|
||||
:loading="gancaoSubmitId === row.id"
|
||||
@click="confirmSubmitGancaoRecipel(row)"
|
||||
>上传药方</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -206,6 +214,13 @@
|
||||
<div class="flex items-center">
|
||||
<span class="po-detail-drawer-title text-gray-800 font-semibold text-lg">业务订单详情</span>
|
||||
<el-tag v-if="detailData?.order_no" type="primary" effect="plain" round class="ml-3">{{ detailData.order_no }}</el-tag>
|
||||
<el-tag
|
||||
v-if="detailData?.gancao_reciperl_order_no"
|
||||
type="success"
|
||||
effect="plain"
|
||||
round
|
||||
class="ml-2"
|
||||
>甘草 {{ detailData.gancao_reciperl_order_no }}</el-tag>
|
||||
</div>
|
||||
<div v-if="detailData" class="flex items-center gap-2 mr-6">
|
||||
<el-button
|
||||
@@ -364,6 +379,17 @@
|
||||
>
|
||||
详细
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="detailData.id"
|
||||
type="warning"
|
||||
size="small"
|
||||
link
|
||||
:loading="gancaoPreviewLoading"
|
||||
:icon="Search"
|
||||
@click="testGancaoPreviewFromDetail"
|
||||
>
|
||||
测试价格
|
||||
</el-button>
|
||||
</div>
|
||||
<span class="text-xs text-gray-400">ID: {{ detailData.prescription_id || '—' }}</span>
|
||||
</div>
|
||||
@@ -391,7 +417,7 @@
|
||||
{{ detailPrescription.clinical_diagnosis || '—' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="剂数 / 用法" :span="2">
|
||||
{{ detailPrescription.dose_count ?? '—' }} 剂 ·
|
||||
{{ detailData.dose_count ?? detailPrescription.dose_count ?? '—' }} {{ detailData.dose_unit || '剂' }} ·
|
||||
{{ detailPrescription.usage_instruction || detailPrescription.usage_method || '—' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="处方金额">
|
||||
@@ -402,6 +428,23 @@
|
||||
{{ consumerRxAuditText(detailPrescription.audit_status) }}
|
||||
</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="用量">
|
||||
<template v-if="detailPrescription.dosage_amount">
|
||||
{{ detailPrescription.dosage_amount }}{{ detailPrescription.dosage_unit || 'g' }}
|
||||
<span v-if="detailPrescription.prescription_type === '饮片' && detailPrescription.need_decoction !== null" class="ml-2 text-gray-500">
|
||||
({{ detailPrescription.need_decoction ? '代煎' : '不代煎' }})
|
||||
</span>
|
||||
</template>
|
||||
<template v-else>—</template>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="服用方式">
|
||||
<template v-if="detailPrescription.usage_days || detailPrescription.times_per_day">
|
||||
<span v-if="detailPrescription.usage_days">服用{{ detailPrescription.usage_days }}天</span>
|
||||
<span v-if="detailPrescription.usage_days && detailPrescription.times_per_day">,</span>
|
||||
<span v-if="detailPrescription.times_per_day">每天{{ detailPrescription.times_per_day }}次</span>
|
||||
</template>
|
||||
<template v-else>—</template>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="状态" :span="2">
|
||||
<el-tag :type="Number(detailPrescription.void_status) === 1 ? 'danger' : 'success'" size="small">
|
||||
{{ Number(detailPrescription.void_status) === 1 ? '已作废' : '正常' }}
|
||||
@@ -710,7 +753,17 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-form-item label="收货地址" prop="shipping_address">
|
||||
<el-form-item label="省/市/区" prop="region">
|
||||
<el-cascader
|
||||
v-model="editForm.region"
|
||||
:options="regionOptions"
|
||||
placeholder="请选择省/市/区"
|
||||
clearable
|
||||
class="w-full"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="详细地址" prop="shipping_address">
|
||||
<el-input v-model="editForm.shipping_address" type="textarea" :rows="2" maxlength="500" show-word-limit />
|
||||
</el-form-item>
|
||||
|
||||
@@ -722,7 +775,55 @@
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="用药疗程">
|
||||
<el-input-number v-model="editForm.medication_days" :min="1" :max="999" :step="1" class="w-full" placeholder="天数(选填)" />
|
||||
<el-input-number v-model="editForm.medication_days" :min="1" :max="999" :step="1" class="w-full" placeholder="天数(选填)">
|
||||
<template #append>天</template>
|
||||
</el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="24">
|
||||
<el-col :span="12">
|
||||
<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="12">
|
||||
<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-row>
|
||||
|
||||
<!-- 甘草预下单测试按钮 -->
|
||||
<el-row v-if="editForm.id" :gutter="24">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="甘草预下单">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
:loading="gancaoPreviewLoading"
|
||||
:icon="Search"
|
||||
@click="testGancaoPreview"
|
||||
>
|
||||
测试价格
|
||||
</el-button>
|
||||
<span class="ml-3 text-xs text-gray-400">
|
||||
测试当前配置的甘草预下单价格(不会真实提交订单)
|
||||
</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -1194,12 +1295,142 @@
|
||||
</div>
|
||||
</div>
|
||||
</el-drawer>
|
||||
|
||||
<!-- 甘草预下单结果抽屉 -->
|
||||
<el-drawer
|
||||
v-model="gancaoPreviewDrawerVisible"
|
||||
title="甘草预下单测试结果"
|
||||
size="800px"
|
||||
destroy-on-close
|
||||
>
|
||||
<div v-if="gancaoPreviewData" class="px-4">
|
||||
<!-- 价格信息 -->
|
||||
<el-card shadow="never" class="mb-4">
|
||||
<template #header>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="font-semibold">价格信息</span>
|
||||
<el-tag type="success">预下单成功</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="药材成本">
|
||||
<span class="text-lg font-semibold text-orange-600">¥{{ gancaoPreviewData.fee?.m_cost || '0.00' }}</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="制作费">
|
||||
<span class="text-lg font-semibold text-blue-600">¥{{ ((gancaoPreviewData.fee?.proces_cost || 0) ).toFixed(2) }}</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="物流费">
|
||||
<span class="text-lg font-semibold text-green-600">¥{{ ((gancaoPreviewData.fee?.lis_cost || 0) ).toFixed(2) }}</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="总计">
|
||||
<span class="text-xl font-bold text-red-600">
|
||||
¥{{ calculateTotalFee(gancaoPreviewData.fee) }}
|
||||
</span>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-card>
|
||||
|
||||
<!-- 配送信息 -->
|
||||
<el-card shadow="never" class="mb-4">
|
||||
<template #header>
|
||||
<span class="font-semibold">配送信息</span>
|
||||
</template>
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="调配中心">
|
||||
{{ gancaoPreviewData.result?.ds_name || '—' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="调配中心ID">
|
||||
{{ gancaoPreviewData.result?.ds_id || '—' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="服用天数范围" :span="2">
|
||||
{{ gancaoPreviewData.result?.take_days?.min || '—' }} -
|
||||
{{ gancaoPreviewData.result?.take_days?.max || '—' }} 天
|
||||
(默认: {{ gancaoPreviewData.result?.take_days?.default || '—' }} 天)
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-card>
|
||||
|
||||
<!-- 规则检查/医嘱备注 -->
|
||||
<el-card v-if="gancaoPreviewData.result?.rule_check?.length" shadow="never" class="mb-4">
|
||||
<template #header>
|
||||
<span class="font-semibold">医嘱备注</span>
|
||||
</template>
|
||||
<div class="text-sm text-gray-700 leading-relaxed">
|
||||
{{ gancaoPreviewData.result.rule_check.map(r => r.msg).join(' ') }}
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 药材明细 -->
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="font-semibold">药材明细</span>
|
||||
<span class="text-sm text-gray-500">共 {{ gancaoPreviewData.result?.m_list?.length || 0 }} 味药</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-table
|
||||
:data="gancaoPreviewData.result?.m_list || []"
|
||||
border
|
||||
stripe
|
||||
max-height="400"
|
||||
>
|
||||
<el-table-column type="index" label="#" width="50" align="center" />
|
||||
<el-table-column prop="title" label="药材名称" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="quantity" label="用量" width="80" align="right">
|
||||
<template #default="{ row }">
|
||||
{{ row.quantity }}{{ row.unit }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="price" label="单价(元/克)" width="110" align="right">
|
||||
<template #default="{ row }">
|
||||
¥{{ Number(row.price).toFixed(4) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="小计" width="100" align="right">
|
||||
<template #default="{ row }">
|
||||
<span class="font-medium text-orange-600">
|
||||
¥{{ (Number(row.price) * Number(row.quantity)).toFixed(2) }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="is_available" label="库存状态" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.is_available === 1 ? 'success' : 'danger'" size="small">
|
||||
{{ row.is_available === 1 ? '有货' : '缺货' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="brief" label="备注" min-width="120" show-overflow-tooltip />
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<!-- 订单信息 -->
|
||||
<el-card shadow="never" class="mt-4">
|
||||
<template #header>
|
||||
<span class="font-semibold">订单信息</span>
|
||||
</template>
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="订单号" :span="2">
|
||||
{{ gancaoPreviewData.order_no || '—' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="剂数">
|
||||
<span class="text-base font-medium">{{ gancaoPreviewData.dose_count || '—' }}剂</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="单剂量">
|
||||
<span class="text-base font-medium">
|
||||
{{ calculateSingleDoseWeight(gancaoPreviewData.result?.m_list) }}克
|
||||
</span>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-card>
|
||||
</div>
|
||||
</el-drawer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="prescriptionOrderList">
|
||||
import { computed, onMounted, reactive, ref, nextTick } from 'vue'
|
||||
import { Refresh, Loading, ArrowDown, InfoFilled } from '@element-plus/icons-vue'
|
||||
import { Refresh, Loading, ArrowDown, InfoFilled, Search } from '@element-plus/icons-vue'
|
||||
import {
|
||||
prescriptionOrderAuditPayment,
|
||||
prescriptionOrderAuditPrescription,
|
||||
@@ -1216,6 +1447,8 @@ import {
|
||||
prescriptionOrderRevokeRxAudit,
|
||||
prescriptionOrderRevokePayAudit,
|
||||
prescriptionOrderLinkPayOrder,
|
||||
prescriptionOrderSubmitGancaoRecipel,
|
||||
prescriptionOrderPreviewGancaoRecipel,
|
||||
prescriptionDetail
|
||||
} from '@/api/tcm'
|
||||
import { usePaging } from '@/hooks/usePaging'
|
||||
@@ -1238,6 +1471,92 @@ const canViewFinanceFields = () => {
|
||||
return FINANCE_ROLE_IDS.some((rid) => ids.includes(rid))
|
||||
}
|
||||
|
||||
// 省市区数据
|
||||
const regionOptions = [
|
||||
{
|
||||
value: '四川省',
|
||||
label: '四川省',
|
||||
children: [
|
||||
{
|
||||
value: '成都市',
|
||||
label: '成都市',
|
||||
children: [
|
||||
{ value: '武侯区', label: '武侯区' },
|
||||
{ value: '锦江区', label: '锦江区' },
|
||||
{ value: '青羊区', label: '青羊区' },
|
||||
{ value: '金牛区', label: '金牛区' },
|
||||
{ value: '成华区', label: '成华区' },
|
||||
{ value: '高新区', label: '高新区' }
|
||||
]
|
||||
},
|
||||
{
|
||||
value: '绵阳市',
|
||||
label: '绵阳市',
|
||||
children: [
|
||||
{ value: '涪城区', label: '涪城区' },
|
||||
{ value: '游仙区', label: '游仙区' }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
value: '北京市',
|
||||
label: '北京市',
|
||||
children: [
|
||||
{
|
||||
value: '北京市',
|
||||
label: '北京市',
|
||||
children: [
|
||||
{ value: '朝阳区', label: '朝阳区' },
|
||||
{ value: '海淀区', label: '海淀区' },
|
||||
{ value: '东城区', label: '东城区' },
|
||||
{ value: '西城区', label: '西城区' }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
value: '上海市',
|
||||
label: '上海市',
|
||||
children: [
|
||||
{
|
||||
value: '上海市',
|
||||
label: '上海市',
|
||||
children: [
|
||||
{ value: '浦东新区', label: '浦东新区' },
|
||||
{ value: '黄浦区', label: '黄浦区' },
|
||||
{ value: '徐汇区', label: '徐汇区' },
|
||||
{ value: '静安区', label: '静安区' }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
value: '广东省',
|
||||
label: '广东省',
|
||||
children: [
|
||||
{
|
||||
value: '广州市',
|
||||
label: '广州市',
|
||||
children: [
|
||||
{ value: '天河区', label: '天河区' },
|
||||
{ value: '越秀区', label: '越秀区' },
|
||||
{ value: '海珠区', label: '海珠区' }
|
||||
]
|
||||
},
|
||||
{
|
||||
value: '深圳市',
|
||||
label: '深圳市',
|
||||
children: [
|
||||
{ value: '南山区', label: '南山区' },
|
||||
{ value: '福田区', label: '福田区' },
|
||||
{ value: '罗湖区', label: '罗湖区' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
const queryParams = reactive({
|
||||
order_no: '',
|
||||
prescription_id: '' as string | number,
|
||||
@@ -1403,6 +1722,16 @@ function canQuickTrackRow(row: { fulfillment_status?: number }) {
|
||||
return Number(row.fulfillment_status) === 5
|
||||
}
|
||||
|
||||
function canUploadGancaoRow(row: {
|
||||
prescription_audit_status?: number
|
||||
gancao_reciperl_order_no?: string
|
||||
}) {
|
||||
// 处方审核已通过(1) 且没有甘草订单号时才显示
|
||||
const rxStatus = Number(row.prescription_audit_status)
|
||||
const gancaoOrderNo = String(row.gancao_reciperl_order_no || '').trim()
|
||||
return rxStatus === 1 && gancaoOrderNo === ''
|
||||
}
|
||||
|
||||
function orderStatusText(s: number | undefined) {
|
||||
const m: Record<number, string> = {
|
||||
1: '待支付',
|
||||
@@ -1666,9 +1995,12 @@ const editForm = reactive({
|
||||
diagnosis_id: 0,
|
||||
recipient_name: '',
|
||||
recipient_phone: '',
|
||||
region: [] as string[],
|
||||
shipping_address: '',
|
||||
is_follow_up: 0,
|
||||
medication_days: undefined as number | string | undefined,
|
||||
dose_count: 1,
|
||||
dose_unit: '剂',
|
||||
prev_staff: '',
|
||||
service_channel: '',
|
||||
service_package: '',
|
||||
@@ -1773,9 +2105,22 @@ async function openEdit(row: { id: number }) {
|
||||
editForm.diagnosis_id = Number(d.diagnosis_id) || 0
|
||||
editForm.recipient_name = d.recipient_name || ''
|
||||
editForm.recipient_phone = d.recipient_phone || ''
|
||||
|
||||
// 填充省市区字段
|
||||
const province = d.shipping_province || ''
|
||||
const city = d.shipping_city || ''
|
||||
const district = d.shipping_district || ''
|
||||
if (province || city || district) {
|
||||
editForm.region = [province, city, district].filter(v => v !== '')
|
||||
} else {
|
||||
editForm.region = []
|
||||
}
|
||||
|
||||
editForm.shipping_address = d.shipping_address || ''
|
||||
editForm.is_follow_up = d.is_follow_up ? 1 : 0
|
||||
editForm.medication_days = d.medication_days > 0 ? d.medication_days : undefined
|
||||
editForm.dose_count = d.dose_count > 0 ? d.dose_count : 1
|
||||
editForm.dose_unit = d.dose_unit || '剂'
|
||||
editForm.prev_staff = d.prev_staff || ''
|
||||
editForm.service_channel = d.service_channel || ''
|
||||
editForm.service_package = d.service_package || ''
|
||||
@@ -1836,9 +2181,22 @@ async function submitEdit() {
|
||||
|
||||
// BUG FIX: 修复之前无法清空部分选填字段的问题
|
||||
medication_days: (editForm.medication_days != null && String(editForm.medication_days).trim() !== '') ? editForm.medication_days : '',
|
||||
dose_unit: editForm.dose_unit || '剂',
|
||||
dose_count: editForm.dose_count || 1,
|
||||
internal_cost: (editForm.internal_cost != null && String(editForm.internal_cost).trim() !== '') ? editForm.internal_cost : '',
|
||||
}
|
||||
|
||||
// 添加省市区字段
|
||||
if (editForm.region && editForm.region.length > 0) {
|
||||
payload.shipping_province = editForm.region[0] || ''
|
||||
payload.shipping_city = editForm.region[1] || ''
|
||||
payload.shipping_district = editForm.region[2] || ''
|
||||
} else {
|
||||
payload.shipping_province = ''
|
||||
payload.shipping_city = ''
|
||||
payload.shipping_district = ''
|
||||
}
|
||||
|
||||
payload.pay_order_ids = [...editForm.pay_order_ids]
|
||||
|
||||
await prescriptionOrderEdit(payload)
|
||||
@@ -1923,6 +2281,121 @@ async function confirmWithdraw(row: { id: number }) {
|
||||
}
|
||||
}
|
||||
|
||||
const gancaoSubmitId = ref(0)
|
||||
const gancaoPreviewDrawerVisible = ref(false)
|
||||
const gancaoPreviewLoading = ref(false)
|
||||
const gancaoPreviewData = ref<any>(null)
|
||||
|
||||
// 计算总费用
|
||||
function calculateTotalFee(fee: any) {
|
||||
if (!fee) return '0.00'
|
||||
const mCost = Number(fee.m_cost) || 0
|
||||
const procesCost = (Number(fee.proces_cost) || 0)
|
||||
const lisCost = (Number(fee.lis_cost) || 0)
|
||||
return (mCost + procesCost + lisCost).toFixed(2)
|
||||
}
|
||||
|
||||
// 计算单剂量(所有药材用量总和)
|
||||
function calculateSingleDoseWeight(mList: any[]) {
|
||||
if (!Array.isArray(mList) || mList.length === 0) return '0'
|
||||
const total = mList.reduce((sum, item) => {
|
||||
return sum + (Number(item.quantity) || 0)
|
||||
}, 0)
|
||||
return total.toFixed(0)
|
||||
}
|
||||
|
||||
async function testGancaoPreview() {
|
||||
if (!editForm.id) {
|
||||
feedback.msgError('请先保存订单')
|
||||
return
|
||||
}
|
||||
|
||||
gancaoPreviewLoading.value = true
|
||||
|
||||
try {
|
||||
const res: any = await prescriptionOrderPreviewGancaoRecipel({
|
||||
id: editForm.id,
|
||||
dose_count: editForm.dose_count || 1,
|
||||
medication_days: editForm.medication_days || undefined
|
||||
})
|
||||
const d = res?.data ?? res
|
||||
|
||||
if (d && d.success) {
|
||||
gancaoPreviewData.value = d
|
||||
gancaoPreviewDrawerVisible.value = true
|
||||
feedback.msgSuccess('预下单测试成功')
|
||||
} else {
|
||||
feedback.msgError(d?.error || '预下单失败')
|
||||
}
|
||||
} catch (e: any) {
|
||||
feedback.msgError(e?.message || '预下单失败')
|
||||
} finally {
|
||||
gancaoPreviewLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 从详情页测试甘草价格
|
||||
async function testGancaoPreviewFromDetail() {
|
||||
if (!detailData.value?.id) {
|
||||
feedback.msgError('订单数据不存在')
|
||||
return
|
||||
}
|
||||
|
||||
gancaoPreviewLoading.value = true
|
||||
|
||||
try {
|
||||
const res: any = await prescriptionOrderPreviewGancaoRecipel({
|
||||
id: detailData.value.id,
|
||||
dose_count: detailData.value.dose_count || 1,
|
||||
medication_days: detailData.value.medication_days || undefined
|
||||
})
|
||||
const d = res?.data ?? res
|
||||
|
||||
if (d && d.success) {
|
||||
gancaoPreviewData.value = d
|
||||
gancaoPreviewDrawerVisible.value = true
|
||||
feedback.msgSuccess('预下单测试成功')
|
||||
} else {
|
||||
feedback.msgError(d?.error || '预下单失败')
|
||||
}
|
||||
} catch (e: any) {
|
||||
feedback.msgError(e?.message || '预下单失败')
|
||||
} finally {
|
||||
gancaoPreviewLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function confirmSubmitGancaoRecipel(row: { id: number }) {
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
'将把本单关联处方提交至甘草药管家开放平台(先 CTM_PREVIEW 预检查再 CTM_SUBMIT_RECIPEL 正式下单;成功后将按甘草侧规则扣费,详见 https://apidoc.igancao.com/service-doc/scm-outer-recipel.html )。确定继续?',
|
||||
'上传甘草药方',
|
||||
{ type: 'warning', confirmButtonText: '确定上传', cancelButtonText: '取消' }
|
||||
)
|
||||
gancaoSubmitId.value = row.id
|
||||
const res: any = await prescriptionOrderSubmitGancaoRecipel({ id: row.id })
|
||||
const d = res?.data ?? res
|
||||
const no = d?.recipel_order_no != null ? String(d.recipel_order_no) : ''
|
||||
feedback.msgSuccess(no ? `上传成功,甘草处方单号:${no}` : '上传成功')
|
||||
getLists()
|
||||
if (detailVisible.value && Number(detailData.value?.id) === row.id) {
|
||||
try {
|
||||
const r: any = await prescriptionOrderDetail({ id: row.id })
|
||||
const dd = r?.data ?? r ?? null
|
||||
if (dd) detailData.value = dd
|
||||
} catch {
|
||||
/* 静默 */
|
||||
}
|
||||
}
|
||||
} catch (e: any) {
|
||||
if (e !== 'cancel' && e !== 'close') {
|
||||
/* 拦截器已提示 */
|
||||
}
|
||||
} finally {
|
||||
gancaoSubmitId.value = 0
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getLists()
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user