Files
his/openhis-ui-vue3/src/views/pharmacymanagement/dispensingOrder/components/orderTable.vue
zhangfei 9c3e603b94 Fix Bug #443: 手术计费:点击签发耗材时异常报错
当手术计费弹窗中点击"签发"耗材时,因耗材的locationId(发放库房)为空导致后端异常。
在DoctorStationAdviceAppServiceImpl.handDevice方法中,当locationId为null时,使用登录用户的科室ID作为默认值,
与NurseBillingAppService中的处理方式保持一致。
2026-05-08 09:14:18 +08:00

1350 lines
40 KiB
Vue
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div>
<el-row :gutter="10">
<el-form ref="formRef" :model="localForm" label-width="100px" inline :rules="rules">
<el-row :gutter="10">
<el-form-item label="单据号" prop="busNo">
<el-input v-model="localForm.busNo" placeholder="" style="width: 220px" disabled />
</el-form-item>
<el-form-item label="开单日期" prop="applyTime">
<el-date-picker
v-model="localForm.applyTime"
placeholder="请选择开单日期"
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
:disabled="!localIsAddOrEditOrder.isAddOrder && !localIsAddOrEditOrder.isEditOrder"
clearable
/>
</el-form-item>
<el-form-item label="供应商" prop="supplierId">
<el-select
v-model="localForm.supplierId"
placeholder="请输入供应商"
style="width: 180px"
:disabled="!localIsAddOrEditOrder.isAddOrder && !localIsAddOrEditOrder.isEditOrder"
clearable
>
<el-option
v-for="item in props.supplierOption || []"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="采购员" prop="applicantId">
<el-select
v-model="localForm.applicantId"
placeholder="请输入采购员"
style="width: 140px"
:disabled="!localIsAddOrEditOrder.isAddOrder && !localIsAddOrEditOrder.isEditOrder"
clearable
>
<el-option
v-for="item in props.practitionerOption || []"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="单据分类" prop="categoryEnum">
<el-select
v-model="localForm.categoryEnum"
placeholder="请输入单据分类"
style="width: 140px"
:disabled="!localIsAddOrEditOrder.isAddOrder && !localIsAddOrEditOrder.isEditOrder"
clearable
>
<el-option
v-for="item in props.supplyCategoryOptions || []"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="摘要(A)" prop="reason">
<el-input
type="textarea"
v-model="localForm.reason"
placeholder="请输入摘要"
style="width: 300px"
:rows="1"
:disabled="!localIsAddOrEditOrder.isAddOrder && !localIsAddOrEditOrder.isEditOrder"
clearable
/>
</el-form-item>
</el-row>
</el-form>
</el-row>
<!-- 审核信息 -->
<el-row :gutter="10">
<el-col :span="8">
<div class="form-item">
<label class="form-label">审核人</label>
<el-tag type="warning" plain>
{{
(props.practitionerOption || []).find(
(item) => item.value === localAuditForm.approverId
)?.label || '暂无'
}}
</el-tag>
</div>
</el-col>
<el-col :span="8">
<div class="form-item">
<label class="form-label">审核日期</label>
<el-tag type="primary" plain>
{{ parseTime(localAuditForm.approvalTime, '{y}-{m}-{d} {h}:{i}:{s}') || '暂无' }}
</el-tag>
</div>
</el-col>
<el-col :span="8">
<div class="form-item">
<label class="form-label">审核状态:</label>
<el-tag
:type="localAuditForm.statusEnum_enumText === '同意' ? 'success' : 'danger'"
plain
>
{{ localAuditForm.statusEnum_enumText || '' }}
</el-tag>
</div>
</el-col>
</el-row>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="Plus"
@click="handleAddRow"
v-if="buttonShow.isAddShow"
>
添加行
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Delete"
@click="handleDeleteRow"
v-if="buttonShow.isDeleteShow"
>
删除行
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="Check"
@click="handleSave"
v-if="buttonShow.isSaveShow"
>
保存
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="info"
plain
icon="Warning"
@click="handleAlertOrder"
v-if="buttonShow.isAlertShow"
>
警戒订货
</el-button>
</el-col>
</el-row>
<el-row :gutter="10">
<el-form ref="tableFormRef" :model="{ localTableData }" :rules="rules" style="width: 100%">
<el-table
:data="localTableData"
ref="tableRef"
class="table-container"
max-height="calc(100vh - 400px)"
min-height="100px"
@selection-change="handleSelectionChange"
@row-click="handleRowClick"
>
<el-table-column type="selection" width="55" />
<el-table-column prop="itemBusNo" label="编号" width="180">
<template #default="scope">
<el-form-item
:prop="`localTableData.${scope.$index}.itemBusNo`"
:rules="rules.itemBusNo"
>
<span>
{{ localTableData[scope.$index].itemBusNo || '' }}
</span>
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="itemName" label="品名">
<template #default="scope">
<el-form-item
:prop="`localTableData.${scope.$index}.itemName`"
:rules="rules.itemName"
>
<PopoverList
v-if="localTableData[scope.$index].isEditing"
@search="handleSearch"
:width="1000"
:modelValue="localTableData[scope.$index].itemName"
>
<template #popover-content="{}">
<medicineList
ref="medicineListRef"
@selectRow="(row) => selectRow(row, scope.$index)"
:searchKey="medicineSearchKey"
/>
</template>
</PopoverList>
<span v-else-if="localTableData[scope.$index].isViewing">
{{ localTableData[scope.$index].itemName || '' }}
</span>
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="totalVolume" label="规格">
<template #default="scope">
<el-form-item
:prop="`localTableData.${scope.$index}.totalVolume`"
:rules="rules.totalVolume"
>
<span>
{{ localTableData[scope.$index].totalVolume || '' }}
</span>
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="unitCode" label="单位">
<template #default="scope">
<el-form-item
:prop="`localTableData.${scope.$index}.unitCode`"
:rules="rules.unitCode"
>
<el-select
v-if="localTableData[scope.$index].isEditing"
v-model="localTableData[scope.$index].unitCode"
:disabled="!localTableData[scope.$index].unitCode"
@change="handleUnitCodeChange(localTableData[scope.$index])"
>
<el-option
v-for="item in localTableData[scope.$index].unitList || []"
:key="item.value"
:label="item.value_dictText"
:value="item.value"
/>
</el-select>
<span v-else-if="localTableData[scope.$index].isViewing">
{{ localTableData[scope.$index].unitCode_dictText || '' }}
</span>
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="itemQuantity" label="请领数量" width="180">
<template #default="scope">
<el-form-item
:prop="`localTableData.${scope.$index}.itemQuantity`"
:rules="rules.itemQuantity"
>
<el-input-number
v-if="localTableData[scope.$index].isEditing"
v-model="localTableData[scope.$index].itemQuantity"
@change="handleItemQuantityChange(localTableData[scope.$index])"
:min="0"
:controls-position="'right'"
/>
<span v-else-if="localTableData[scope.$index].isViewing">
{{ localTableData[scope.$index].itemQuantity || '' }}
</span>
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="retailPrice" label="销售价">
<template #default="scope">
<el-form-item
:prop="`localTableData.${scope.$index}.retailPrice`"
:rules="rules.retailPrice"
>
<span>
{{ getPriceDisplay(scope.$index, 'retailPrice') }}
</span>
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="totalRetailPrice" label="销售金额">
<template #default="scope">
<el-form-item
:prop="`localTableData.${scope.$index}.totalRetailPrice`"
:rules="rules.totalRetailPrice"
>
<span>
{{ getPriceDisplay(scope.$index, 'totalRetailPrice') }}
</span>
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="itemPrice" label="药库库存"> </el-table-column>
<el-table-column prop="manufacturerText" label="厂家/产地" width="200">
<template #default="scope">
<el-form-item
:prop="`localTableData.${scope.$index}.manufacturerText`"
:rules="rules.manufacturerText"
>
<span>
{{ localTableData[scope.$index].manufacturerText || '' }}
</span>
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="itemCode" label="供应商"> </el-table-column>
<el-table-column prop="approvalNumber" label="批注文号">
<template #default="scope">
<el-form-item
:prop="`localTableData.${scope.$index}.approvalNumber`"
:rules="rules.approvalNumber"
>
<span>
{{ localTableData[scope.$index].approvalNumber || '' }}
</span>
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="remake" label="备注">
<template #default="scope">
<el-form-item :prop="`localTableData.${scope.$index}.remake`" :rules="rules.remake">
<el-input
v-if="localTableData[scope.$index].isEditing"
v-model="localTableData[scope.$index].remake"
/>
<span v-else-if="localTableData[scope.$index].isViewing">
{{ localTableData[scope.$index].remake || '' }}
</span>
</el-form-item>
</template>
</el-table-column>
</el-table>
</el-form>
</el-row>
<el-row justify="end">
<el-pagination
:current-page="localForm.pageNo"
:page-size="localForm.pageSize"
:page-sizes="[10, 50, 100, 200]"
:small="small"
layout="total, sizes, prev, pager, next, jumper"
:total="localTableDataTotal"
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
v-show="localTableDataTotal > 0"
/>
</el-row>
</div>
</template>
<script setup>
import {addOrEditOrder, getBusNo, getMedicineList} from './api';
import {nextTick, ref, watch} from 'vue';
import medicineList from './medicineList.vue';
import PopoverList from '@/components/OpenHis/popoverList/index.vue';
import {parseTime} from '@/utils/his';
// 获取当前实例
const { proxy } = getCurrentInstance();
// 调用父组件方法
const emit = defineEmits(['update:form', 'getList', 'updateButtonState', 'clearForm']);
// 属性
const props = defineProps({
// 父组件 表格数据
tableData: {
type: Array,
default: () => [],
},
// 父组件 表格总条数
total: {
type: Number,
default: 0,
},
// 父组件 表格每页条数
small: {
type: Boolean,
default: false,
},
// 父组件 表单数据
form: {
type: Object,
default: () => ({
busNo: undefined,
applyTime: undefined,
supplierId: undefined,
applicantId: undefined,
reason: undefined,
status: undefined,
approverId: undefined,
}),
},
// 父组件 订单编辑还是新增
isAddOrEditOrder: {
type: Object,
default: () => ({
isAddOrder: false,
isEditOrder: false,
}),
},
// 父组件 审核表单数据
auditForm: {
type: Object,
default: () => ({
approvalTime: undefined,
statusEnum_enumText: undefined,
approverId_dictText: undefined,
}),
},
// 查询供应商列表 supplierOption
supplierOption: {
type: Array,
default: () => [],
},
// 查询经手人列表 practitionerOption
practitionerOption: {
type: Array,
default: () => [],
},
// 单据分类 supplyCategoryOptions
supplyCategoryOptions: {
type: Array,
default: () => [],
},
// 按钮显示
buttonShow: {
type: Object,
default: () => ({
isAddShow: false,
isDeleteShow: false,
isSaveShow: false,
isEditShow: false,
isAlertShow: false,
}),
},
// 单据类型 supplyTypeOptions
supplyTypeOptions: {
type: Array,
default: () => [],
},
// 审批状态 supplyStatusOptions
supplyStatusOptions: {
type: Array,
default: () => [],
},
// 表格数据总条数
tableDataTotal: {
type: Number,
default: 0,
},
});
// 本地表单数据,用于接收 props.form
const localForm = ref({
pageNo: 1,
pageSize: 10,
});
// 本地表格数据 用于接收 props.tableData
const localTableData = ref([]);
// 本地表格数据总条数
const localTableDataTotal = ref(0);
// 计算属性:获取指定行的当前单位数据
const getCurrentUnitData = (rowIndex) => {
const row = localTableData.value[rowIndex];
if (!row || !row.unitList) return null;
return row.unitList.find((item) => item.value === row.unitCode) || null;
};
// 计算属性:获取指定行的价格显示值
const getPriceDisplay = (rowIndex, priceType) => {
const row = localTableData.value[rowIndex];
if (!row) return '';
const currentUnit = getCurrentUnitData(rowIndex);
// 根据价格类型返回对应的值
switch (priceType) {
case 'price':
return currentUnit?.priceMask || '';
case 'totalPrice':
return row.totalPriceMask || currentUnit?.totalPriceMask || '';
case 'retailPrice':
return currentUnit?.retailPriceMask || '';
case 'totalRetailPrice':
return row.totalRetailPriceMask || currentUnit?.totalRetailPriceMask || '';
default:
return '';
}
};
// 计算属性:获取指定行的库存显示值
const getInventoryDisplay = (rowIndex, type) => {
const currentUnit = getCurrentUnitData(rowIndex);
if (!currentUnit) return '';
switch (type) {
case 'max':
return currentUnit.specificationInventoryMax || '';
case 'maxUnit':
return currentUnit.specificationInventoryMax > 0
? currentUnit.specificationInventoryMaxUnit
: '';
case 'min':
return currentUnit.specificationInventoryMin > 0 ? currentUnit.specificationInventoryMin : '';
case 'minUnit':
return currentUnit.specificationInventoryMin > 0
? currentUnit.specificationInventoryMinUnit
: '';
default:
return '';
}
};
// 加载
const loading = ref(false);
// 品名搜索
const medicineSearchKey = ref('');
// 选择相关变量
const ids = ref([]);
const selectedRows = ref([]);
const single = ref(true);
const multiple = ref(true);
// 审核表单数据
const localAuditForm = ref({
approvalTime: undefined,
statusEnum_enumText: undefined,
approverId_dictText: undefined,
});
// 订单编辑还是新增
const localIsAddOrEditOrder = ref({
isAddOrder: false,
isEditOrder: false,
});
// 验证规则
const rules = {
// busNo: [{ required: true, message: '请输入单据号', trigger: 'blur' }],
supplierId: [{ required: true, message: '请输入供应商', trigger: 'blur' }],
applicantId: [{ required: true, message: '请输入采购员', trigger: 'blur' }],
categoryEnum: [{ required: true, message: '请输入单据类型', trigger: 'blur' }],
applyTime: [{ required: true, message: '请输入开单日期', trigger: 'blur' }],
itemBusNo: [{ required: true, message: '请输入编号', trigger: ['blur', 'change'] }],
itemName: [{ required: true, message: '请输入品名', trigger: 'blur' }],
totalVolume: [{ required: true, message: '请输入规格', trigger: 'blur' }],
unitCode: [{ required: true, message: '请输入单位', trigger: 'blur' }],
itemQuantity: [{ required: true, message: '请输入数量', trigger: 'blur' }],
// price: [{ required: true, message: '请输入进货价', trigger: 'blur' }],
// totalPrice: [{ required: true, message: '请输入进价金额', trigger: 'blur' }],
// retailPrice: [{ required: true, message: '请输入销售价', trigger: 'blur' }],
// totalRetailPrice: [{ required: true, message: '请输入销售金额', trigger: 'blur' }],
manufacturerText: [{ required: true, message: '请输入厂家/产地', trigger: 'blur' }],
specificationInventory: [{ required: true, message: '请输入规格库存', trigger: 'blur' }],
approvalNumber: [{ required: true, message: '请输入批注文号', trigger: 'blur' }],
};
// 监听 props.isAddOrEditOrder 的变化
watch(
() => props.isAddOrEditOrder,
(newVal) => {
localIsAddOrEditOrder.value = { ...newVal };
}
);
// 监听 props.form 的变化
watch(
() => props.form,
(newVal) => {
localForm.value = { ...newVal };
},
{ deep: true }
);
// 监听 props.tableData 的变化
watch(
() => props.tableData,
(newVal) => {
localTableData.value = [...newVal];
},
{ deep: true }
);
// 监听 props.tableDataTotal 的变化
watch(
() => props.tableDataTotal,
(newVal) => {
localTableDataTotal.value = newVal;
}
);
// 监听 props.auditForm 的变化
watch(
() => props.auditForm,
(newVal) => {
localAuditForm.value = { ...newVal };
},
{ deep: true }
);
// 品名搜索
const handleSearch = (value) => {
medicineSearchKey.value = value;
};
// 获取单据号
const getInitBusNo = async () => {
const res = await getBusNo();
return res.data.busNo;
};
// 分页当前页
const handleCurrentChange = (page) => {
localForm.value.pageNo = page;
// 通知父组件更新查询参数并重新获取数据
emit('update:query-params', {
pageNo: page,
pageSize: localForm.value.pageSize,
});
};
// 分页每页条数
const handleSizeChange = (size) => {
localForm.value.pageSize = size;
localForm.value.pageNo = 1; // 切换每页条数时重置到第一页
// 通知父组件更新查询参数并重新获取数据
emit('update:query-params', {
pageNo: 1,
pageSize: size,
});
};
// 行点击
const handleRowClick = (row) => {
// 判断订单是否可以编辑
if (!isAllowEdit(row)) {
return;
}
// 设置表格编辑状态
row.isEditing = true;
// 设置表格查看状态
row.isViewing = false;
};
// 判断订单是否可以编辑
const isAllowEdit = (row) => {
// 已审批的订单不能编辑
if (
localAuditForm.value.statusEnum === 3 ||
localAuditForm.value.statusEnum_enumText === '同意'
) {
return false; // 已审批,不能编辑
}
return true; // 未审批,可以编辑
};
// 监听单位变化
const handleUnitCodeChange = (row) => {
// 进价金额
row.totalPrice =
row.unitList.find((item) => item.value === row.unitCode).priceMask * row.itemQuantity;
row.totalPriceMask =
row.unitList.find((item) => item.value === row.unitCode).priceMask * row.itemQuantity;
// 销售金额
row.totalRetailPriceMask =
row.unitList.find((item) => item.value === row.unitCode).retailPriceMask * row.itemQuantity;
row.totalRetailPrice =
row.unitList.find((item) => item.value === row.unitCode).retailPriceMask * row.itemQuantity;
};
// 监听数量变化
const handleItemQuantityChange = (row) => {
// 转换为数值并保留2位小数
const quantity = parseFloat(row.itemQuantity) || 0;
const price = parseFloat(row.price) || 0;
const retailPrice = parseFloat(row.retailPrice) || 0;
// 进价金额
row.totalPrice = (quantity * price).toFixed(2);
row.totalPriceMask = (quantity * price).toFixed(2);
// 销售金额
row.totalRetailPrice = (quantity * retailPrice).toFixed(2);
row.totalRetailPriceMask = (quantity * retailPrice).toFixed(2);
};
// 选择药品
const selectRow = (rowValue, index) => {
localTableData.value[index] = {
// 选中行药品数据
...rowValue,
// 药品 id
itemId: rowValue.id,
// 药品编号
itemBusNo: rowValue.busNo,
// 药品名称
itemName: rowValue.name,
// 单位
unitCode: rowValue.unitCode,
// 单位名称
unitCodeDictText: rowValue.unitCode_dictText,
// 备注
remake: rowValue.remake,
// 只用于显示
// 编辑状态
isEditing: true,
// 查看状态
isViewing: false,
};
// 重新构建价格单位 规格库存 进价 售价表格数据
rebuildTableData(localTableData.value[index]);
console.log(localTableData.value[index]);
// 手动触发验证
nextTick(() => {
proxy.$refs.tableFormRef.validateField(`localTableData.${index}.itemBusNo`);
proxy.$refs.tableFormRef.validateField(`localTableData.${index}.itemName`);
proxy.$refs.tableFormRef.validateField(`localTableData.${index}.totalVolume`);
proxy.$refs.tableFormRef.validateField(`localTableData.${index}.unitCode`);
// proxy.$refs.tableFormRef.validateField(`localTableData.${index}.price`);
// proxy.$refs.tableFormRef.validateField(`localTableData.${index}.retailPrice`);
proxy.$refs.tableFormRef.validateField(`localTableData.${index}.manufacturerText`);
proxy.$refs.tableFormRef.validateField(`localTableData.${index}.specificationInventory`);
proxy.$refs.tableFormRef.validateField(`localTableData.${index}.approvalNumber`);
});
};
// 重新构建价格单位 规格库存 进价 售价表格数据
const rebuildTableData = (row) => {
(row.unitList || []).forEach((item) => {
// 最大单位
if (item.value === row.unitCode) {
// 假数据 只做显示用 不参与计算 用于显示
// 进货价(假)
item.priceMask = row.price;
// 销售价(假)
item.retailPriceMask = row.retailPrice;
// 进价金额(假)
item.totalPriceMask = row.totalPrice;
// 销售金额(假)
item.totalRetailPriceMask = row.totalRetailPrice;
// 规格库存
item.specificationInventoryOriginal = row.specificationInventory;
// 规格库存最大单位
item.specificationInventoryMax = Math.floor(row.specificationInventory / row.partPercent);
// 规格库存最小单位
item.specificationInventoryMin = row.specificationInventory % row.partPercent;
// 单位名称
item.specificationInventoryMaxUnit = row.unitCode_dictText;
// 单位名称
item.specificationInventoryMinUnit = row.minUnitCode_dictText;
} else {
// 最小单位
// 假数据 只做显示用 不参与计算 用于显示
// 进货价(假)
item.priceMask = row.price / row.partPercent;
// 销售价(假)
item.retailPriceMask = row.retailPrice / row.partPercent;
// 进价金额(假)
item.totalPriceMask = row.totalPrice;
// 销售金额(假)
item.totalRetailPriceMask = row.totalRetailPrice;
// 规格库存
item.specificationInventoryOriginal = row.specificationInventory;
// 规格库存最大单位
item.specificationInventoryMin = row.specificationInventory;
// 单位名称
item.specificationInventoryMinUnit = row.minUnitCode_dictText;
}
});
};
// 校验是否有空行
const isEmptyRow = () => {
// 如果 localTableData的长度大于 1 时在判断否有空行
if (!localTableData.value) {
return true;
}
return localTableData.value.some((row) => !row.itemId || !row.itemQuantity || !row.itemName);
};
// 新增一个空行
const addEmptyRow = () => {
localTableData.value.push({
// 单据号
busNo: localForm.value.busNo,
// 开单日期
applyTime: localForm.value.applyTime,
// 采购员
applicantId: localForm.value.applicantId,
// 摘要
reason: localForm.value.reason,
// 单据分类
categoryEnum: localForm.value.categoryEnum,
// 供应商
supplierId: localForm.value.supplierId,
// 仓库
purposeLocationId: localForm.value.locationId,
// 表格需要的字段
itemBusNo: '',
// 药品 id
itemId: '',
// 品名
itemName: '',
// 规格
totalVolume: '',
// 单位
unitCode: '',
// 数量
itemQuantity: 0,
// 进货价
price: '',
// 进价金额
totalPrice: '',
// 销售价
retailPrice: '',
// 销售金额
totalRetailPrice: '',
// 生产厂家
manufacturerText: '',
// 规格库存
specificationInventory: '',
// 批注文号
approvalNumber: '',
// 备注
remake: '',
// 编辑状态
isEditing: true,
// 查看状态
isViewing: false,
});
nextTick(() => {
// 处理本地按钮状态
emit('updateButtonState', {
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: false,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: true,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: true,
// 删除行 按钮显示
isDeleteShow: true,
// 保存行 按钮显示
isSaveShow: true,
// 编辑行 按钮显示
isEditShow: true,
// 警戒订货 按钮显示
isAlertShow: true,
});
});
};
// 添加行
const handleAddRow = async () => {
// 验证表单
const formValid = await validateFormRef();
if (!formValid) {
return;
}
// 如果当前没有数据,直接添加空行
if (!localTableData.value || localTableData.value.length === 0) {
// 确保 localTableData 存在
if (!localTableData.value) {
localTableData.value = [];
}
// 添加一个包含所有字段的空对象
addEmptyRow();
return;
}
// 如果有数据,检查是否有空行
if (isEmptyRow()) {
proxy.$message.error('请填写完整信息');
return;
}
// 添加一个包含所有字段的空对象
addEmptyRow();
};
// 验证表单
const validateFormRef = () => {
return new Promise((resolve) => {
proxy.$refs.formRef.validate((valid) => {
resolve(valid);
});
});
};
// 验证表格
const validateTableFormRef = () => {
if (!localTableData.value || localTableData.value.length === 0) {
return false;
}
return new Promise((resolve) => {
proxy.$refs.tableFormRef.validate((valid) => {
resolve(valid);
});
});
};
// 警戒订货
const handleAlertOrder = async () => {
// 清空表格数据
localTableData.value = [];
// 验证表单
if (!localForm.value.supplierId || !localForm.value.locationId) {
proxy.$message.warning('请选择供应商和仓库');
return;
}
// 获取药品列表
const medicineListData = await getMedicineListData();
// 遍历药品列表
buildEditFormData(medicineListData);
// 更新按钮状态
emit('updateButtonState', {
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: true,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: true,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: true,
// 删除行 按钮显示
isDeleteShow: true,
// 保存行 按钮显示
isSaveShow: true,
// 编辑行 按钮显示
isEditShow: true,
// 警戒订货 按钮显示
isAlertShow: true,
});
};
// 构建编辑后的表单数据
const buildEditFormData = (data) => {
// 构建表格数据
if (data.length > 0) {
// 表格数据
data.forEach((item) => {
item.itemId = item.id;
item.itemBusNo = item.busNo;
item.itemName = item.name;
item.unitCode = item.unitCode;
item.unitCodeDictText = item.unitCode_dictText;
item.remake = item.remake;
// 表格编辑状态
item.isEditing = false;
// 表格查看状态
item.isViewing = true;
// 构建单位列表
buildUnitList(item);
});
// 更新表格数据
localTableData.value = localTableData.value.concat(data);
// 订单编辑还是新增
localIsAddOrEditOrder.value = {
isAddOrder: true,
isEditOrder: false,
};
}
};
// 构建单位列表
const buildUnitList = (item) => {
// 表格单位列表
(item.unitList || []).forEach((unit) => {
// 判断当前单位是最大单位还是最小单位
const isMaxUnit = unit.value === item.unitCode;
const isMinUnit = unit.value === item.minUnitCode;
// 进货价(假)
if (isMaxUnit) {
unit.priceMask = item.price;
} else {
unit.priceMask = item.price / item.partPercent;
}
// 销售价(假)
if (isMaxUnit) {
unit.retailPriceMask = item.retailPrice;
} else {
unit.retailPriceMask = item.retailPrice / item.partPercent;
}
// 进价金额(假)
unit.totalPriceMask = '';
// 销售金额(假)
unit.totalRetailPriceMask = '';
// 规格库存
unit.specificationInventoryOriginal = item.specificationInventory;
// 规格库存显示逻辑
if (isMaxUnit) {
// 最大单位:显示为 "X盒"
unit.specificationInventoryMax = Math.floor(
item.specificationInventory / parseInt(item.partPercent)
);
unit.specificationInventoryMaxUnit =
unit.specificationInventoryMax > 0 ? item.unitCode_dictText : '';
unit.specificationInventoryMin = item.specificationInventory % item.partPercent;
unit.specificationInventoryMinUnit =
unit.specificationInventoryMin > 0 ? item.minUnitCode_dictText : '';
} else if (isMinUnit) {
// 最小单位:显示为 "X瓶"
unit.specificationInventoryMax = item.specificationInventory;
unit.specificationInventoryMaxUnit =
unit.specificationInventoryMax > 0 ? item.minUnitCode_dictText : '';
unit.specificationInventoryMin = 0;
unit.specificationInventoryMinUnit =
unit.specificationInventoryMin > 0 ? item.minUnitCode_dictText : '';
} else {
// 其他单位:显示为 "X瓶"
unit.specificationInventoryMax = item.specificationInventory;
unit.specificationInventoryMaxUnit =
unit.specificationInventoryMax > 0 ? item.minUnitCode_dictText : '';
unit.specificationInventoryMin = 0;
unit.specificationInventoryMinUnit =
unit.specificationInventoryMin > 0 ? item.minUnitCode_dictText : '';
}
});
};
// 获取药品列表
const getMedicineListData = async () => {
const res = await getMedicineList({
supplierId: localForm.value.supplierId,
locationId: localForm.value.locationId,
pageNo: 1,
pageSize: 1000,
});
// 如果 res.data?.records 为空,则返回空数组
if (res.data.records.length === 0) {
proxy.$message.warning('本仓库和供应商没有找到药品信息');
return [];
}
// 更新分页数据
// localTableDataTotal.value = res.data?.total || 0;
return res.data?.records || [];
};
// 保存行
const handleSave = async () => {
// 验证表单头部
const formValid = await validateFormRef();
if (!formValid) {
return;
}
if (!formValid) {
return;
}
// 验证表格数据
const tableValid = await validateTableFormRef();
if (!tableValid) {
return;
}
// 保存当前数据状态,防止在确认过程中被修改
const currentTableData = JSON.parse(JSON.stringify(localTableData.value));
const currentFormData = JSON.parse(JSON.stringify(localForm.value));
// 是否确认保存数据
const isConfirm = await proxy.$modal.confirm('确认保存数据吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
});
if (!isConfirm) {
return;
}
// 加载中
loading.value = true;
// 使用保存的数据状态重构数据
const editData = await buildEditForm(currentTableData, currentFormData);
// 判断是新增还是编辑
if (localIsAddOrEditOrder.value.isAddOrder) {
addOrEditOrder(editData).then((res) => {
if (res.code === 200) {
proxy.$message.success('新增成功');
// 调用父组件的 getList 方法
emit('getList');
// 清空表单
// resetAllData();
// 清空 父组件 tableFormRef 表单数据
emit('clearForm');
// 关闭加载
loading.value = false;
}
});
} else if (localIsAddOrEditOrder.value.isEditOrder) {
addOrEditOrder(editData).then((res) => {
if (res.code === 200) {
proxy.$message.success('保存成功');
// 调用父组件的 getList 方法
emit('getList');
// 清空表单
// resetAllData();
// 清空 父组件 tableFormRef 表单数据
emit('clearForm');
} else {
proxy.$message.error('保存失败');
}
// 关闭加载
loading.value = false;
});
}
};
// 重构数据
const buildEditForm = async (data, formData = null) => {
const formDataCopy = [...data];
// 获取单据号
let busNo = '';
if (localIsAddOrEditOrder.value.isAddOrder) {
busNo = await getInitBusNo();
} else {
busNo = data[0].busNo;
}
// 订单数据
const orderData = data[0];
// 使用传入的表单数据如果没有则使用当前的localForm
const currentForm = formData || localForm.value;
// 表格数据
formDataCopy.forEach((item) => {
// 单据号
item.busNo = busNo;
// 开单日期
item.applyTime = currentForm.applyTime;
// 供应商
item.supplierId = currentForm.supplierId;
// 采购员
item.applicantId = currentForm.applicantId;
// 单据分类
item.categoryEnum = currentForm.categoryEnum;
// 摘要
item.reason = currentForm.reason;
// 仓库
item.purposeLocationId = orderData.purposeLocationId
? orderData.purposeLocationId
: currentForm.locationId;
});
// 重构数据
return formDataCopy;
};
// 清空表单
const resetAllData = () => {
// 清空表单数据
localForm.value = {};
// 清空审核表单数据
localAuditForm.value = {};
// 清空表格数据
localTableData.value = [];
// 重置订单状态
localIsAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: false,
};
// 重置按钮状态为初始状态
emit('updateButtonState', {
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: true,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: false,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
});
};
// 删除行
const handleDeleteRow = () => {
if (selectedRows.value.length === 0) {
proxy.$message.warning('请选择要删除的行');
return;
}
proxy
.$confirm('确认删除选中的行吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
// 从 tableData 中删除选中的行
const selectedIndexes = [];
// 获取选中行在 localTableData 中的索引
selectedRows.value.forEach((selectedRow) => {
const index = localTableData.value.findIndex(
(row) => row.itemBusNo === selectedRow.itemBusNo && row.itemName === selectedRow.itemName
);
if (index !== -1) {
selectedIndexes.push(index);
}
});
// 按索引从大到小排序,避免删除时索引变化的问题
selectedIndexes.sort((a, b) => b - a);
// 删除选中的行
selectedIndexes.forEach((index) => {
localTableData.value.splice(index, 1);
});
// 清空选择
selectedRows.value = [];
ids.value = [];
// 如果删除后没有数据了,更新按钮状态
if (localTableData.value.length === 0) {
emit('updateButtonState', {
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: true,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: true,
// 删除行 按钮显示
isDeleteShow: true,
// 保存行 按钮显示
isSaveShow: true,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: true,
});
}
proxy.$message.success('删除成功');
})
.catch(() => {
// 用户取消删除
});
};
// 选择变化处理
const handleSelectionChange = (selection) => {
ids.value = selection.map((item) => item.id);
selectedRows.value = selection;
single.value = selection.length != 1;
multiple.value = !selection.length;
};
// 组件名称
defineOptions({ name: 'orderTable' });
// 暴露方法给父组件
defineExpose({
resetAllData,
});
</script>
<style scoped>
/* 表格中的表单项样式 */
.table-form-item {
margin-bottom: 0 !important;
display: block !important;
}
/* 确保表格行有足够的高度显示错误信息 */
.el-table .el-table__row {
min-height: 100px;
}
/* 表格单元格样式 */
.el-table .el-table__cell {
padding-bottom: 25px;
}
/* 输入框样式 */
.el-table .el-input {
width: 100%;
}
/* 确保表格占满容器宽度 */
.el-table {
width: 100% !important;
}
/* 确保表格容器占满宽度 */
.el-form {
width: 100%;
}
/* 确保行容器占满宽度 */
.el-row {
width: 100%;
}
/* 自定义表单项样式 */
.form-item {
display: flex;
align-items: center;
margin-bottom: 18px;
}
.form-label {
width: 100px;
text-align: right;
padding-right: 12px;
font-size: 14px;
color: #606266;
line-height: 40px;
box-sizing: border-box;
}
/* 强制显示错误信息 */
.el-form-item__error {
position: static !important;
visibility: visible !important;
opacity: 1 !important;
display: block !important;
margin-top: 2px !important;
font-size: 12px !important;
color: #f56c6c !important;
}
/* 确保表单项内容正确显示 */
.el-form-item__content {
display: block !important;
width: 100% !important;
}
/* 表格单元格内容样式 */
.el-table .cell {
padding: 8px 0;
}
.table-container {
width: 100%;
}
</style>