Files
his/backup/vxetable-migration-20260602/medicationmanagement/chkstock/chkstockPart/index.vue
华佗 893cbf1fe0 refactor: 彻底清除所有openhis痕迹
- 重命名目录: openhis-server-new → healthlink-his-server
- 重命名目录: openhis-ui-vue3 → healthlink-his-ui
- 重命名Java类: OpenHisApplication → HealthLinkHisApplication
- 重命名Java类: OpenHisMiniApp → HealthLinkHisMiniApp
- 重命名组件目录: OpenHis → HealthLinkHis
- 重命名样式文件: openhis.scss → healthlink-his.scss
- 重命名配置: nginx-openhis.conf → nginx-healthlink-his.conf
- 更新所有源码引用 (0个残留)
- 更新所有文档/脚本/配置中的引用
2026-06-05 13:36:28 +08:00

1390 lines
45 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
v-loading="loading"
class="app-container"
:element-loading-text="'审批中。。。'"
>
<el-row
:gutter="10"
class="mb8"
>
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="Plus"
@click="handleSave"
>
批量保存
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="Plus"
@click="submitAudit"
>
提交审核
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="Printer"
@click="handlePrint"
>
打印单据
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="Export"
@click="handleExport"
>
导出
</el-button>
</el-col>
<!-- <el-col :span="1.5">
<el-button type="primary" plain icon="EditPen" @click="handleTotalAmount">
计算盈亏金额
</el-button>
</el-col> -->
</el-row>
<el-button
type="primary"
plain
icon="Printer"
@click="handlePrint"
>
打印单据
</el-button>
<el-form
ref="receiptHeaderRef"
:model="receiptHeaderForm"
:inline="true"
label-width="120px"
:rules="rules"
>
<el-form-item
label="单据号:"
prop="busNo"
>
<el-input
v-model="receiptHeaderForm.busNo"
placeholder="单据号:"
clearable
style="width: 260px"
disabled
/>
</el-form-item>
<el-form-item
label="仓库类型:"
prop="purposeTypeEnum"
>
<el-select
v-model="receiptHeaderForm.purposeTypeEnum"
placeholder=""
clearable
style="width: 150px"
:disabled="data.isEdit"
@change="(value) => handleChangePurposeTypeEnum(value, false)"
>
<el-option
v-for="dict in warehous_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item
label="盘点仓库:"
prop="purposeLocationId"
>
<el-select
v-model="receiptHeaderForm.purposeLocationId"
placeholder=""
clearable
style="width: 150px"
:disabled="data.isEdit"
@change="handleCabinetChange(receiptHeaderForm.purposeLocationId)"
>
<el-option
v-for="cabinet in purposeTypeListOptions"
:key="cabinet.id"
:label="cabinet.name"
:value="cabinet.id"
/>
</el-select>
</el-form-item>
<el-form-item
label="货位:"
prop="purposeLocation"
>
<el-select
v-model="receiptHeaderForm.purposeLocation"
placeholder=""
clearable
style="width: 150px"
:disabled="data.isEdit"
>
<el-option
v-for="freight in freightListOptions"
:key="freight.id"
:label="freight.name"
:value="freight.id"
/>
</el-select>
</el-form-item>
<el-form-item label="盘点日期:">
<el-date-picker
v-model="receiptHeaderForm.occurrenceTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="datetime"
:disabled="data.isEdit"
/>
</el-form-item>
<el-form-item
label="药品类型:"
prop="medicationType"
>
<el-select
v-model="receiptHeaderForm.medicationType"
placeholder=""
clearable
style="width: 150px"
:disabled="data.isEdit"
@change="
(value) => {
itemType = value;
}
"
>
<el-option
v-for="itemType in purchase_type"
:key="itemType.value"
:label="itemType.label"
:value="itemType.value"
/>
</el-select>
</el-form-item>
</el-form>
<el-tabs type="border-card">
<el-tab-pane label="盘点单明细">
<el-row
v-if="!viewStatus"
:gutter="10"
class="mb8"
>
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="Plus"
@click="addNewRow"
>
添加行
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Delete"
:disabled="multiple"
@click="deleteSelectedRows"
>
删除行
</el-button>
</el-col>
</el-row>
<el-form
ref="formRef"
:model="form"
:rules="tableRules"
:disabled="viewStatus == 'apply'"
>
<el-table
ref="tableRef"
v-loading="loading"
:data="form.purchaseinventoryList"
max-height="500"
@selection-change="handleSelectionChange"
>
<el-table-column
type="selection"
width="50"
align="center"
/>
<el-table-column
key="name"
label="项目"
align="center"
prop="name"
width="200"
fixed
>
<template #default="scope">
<el-form-item
:prop="`purchaseinventoryList.${scope.$index}.name`"
:rules="tableRules.name"
required
>
<el-input
v-if="viewStatus == 'view'"
v-model="scope.row.name"
placeholder=""
disabled
/>
<PopoverList
v-else
:width="1000"
:model-value="scope.row.name"
@search="handleSearch"
>
<template #popover-content="{}">
<MedicineList
:search-key="medicineSearchKey"
:purpose-location-id="receiptHeaderForm.purposeLocationId"
:item-type="receiptHeaderForm.medicationType"
@select-row="(row) => selectRow(row, scope.$index)"
/>
</template>
</PopoverList>
</el-form-item>
</template>
</el-table-column>
<el-table-column
key="volume"
label="规格"
align="center"
prop="volume"
width="140"
:show-overflow-tooltip="true"
>
<template #default="scope">
<el-form-item
:prop="`purchaseinventoryList.${scope.$index}.volume`"
:rules="tableRules.volume"
>
<el-input
v-model="scope.row.volume"
disabled
placeholder=""
/>
</el-form-item>
</template>
</el-table-column>
<el-table-column
key="manufacturerText"
label="厂家/产地"
align="center"
prop="manufacturerText"
:show-overflow-tooltip="true"
width="220"
>
<template #default="scope">
<el-form-item
:prop="`purchaseinventoryList.${scope.$index}.manufacturerText`"
:rules="tableRules.manufacturerText"
>
<el-input
v-model="scope.row.manufacturerText"
disabled
placeholder=""
/>
</el-form-item>
</template>
</el-table-column>
<el-table-column
key="lotNumber"
label="产品批号"
align="center"
prop="lotNumber"
width="150"
>
<template #default="scope">
<el-form-item :prop="`purchaseinventoryList.${scope.$index}.lotNumber`">
<el-input
v-model="scope.row.lotNumber"
placeholder=""
disabled
@blur="lotNumberBlur(scope.row, scope.$index)"
/>
</el-form-item>
</template>
</el-table-column>
<el-table-column
key="price"
label="单价 "
align="center"
prop="price"
width="130"
>
<template #default="scope">
<el-form-item
:prop="`purchaseinventoryList.${scope.$index}.price`"
:rules="tableRules.price"
>
<div class="select_wrapper_div">
<el-input
v-model="scope.row.price"
disabled
placeholder=""
:class="{ 'error-border': scope.row.error }"
>
<template #suffix>
</template>
</el-input>
</div>
</el-form-item>
</template>
</el-table-column>
<el-table-column
key="unitCode"
label="盘点单位"
align="center"
prop="unitCode"
:show-overflow-tooltip="true"
width="90"
>
<template #default="scope">
<el-form-item
:prop="`purchaseinventoryList.${scope.$index}.unitCode`"
:rules="tableRules.unitCode"
>
<div class="select_wrapper_div">
<el-select
v-model="scope.row.unitCode"
placeholder="盘点单位"
:disabled="viewStatus == 'view'"
:class="{ 'error-border': scope.row.error }"
@change="(value) => handleUnitCodeChange(scope.row, value)"
>
<el-option
v-for="(item, index) in scope.row.unitList"
:key="index"
:label="item.label"
:value="item.value"
@click="scope.row.currentUnitCode_dictText = item.label"
/>
</el-select>
</div>
</el-form-item>
</template>
</el-table-column>
<el-table-column
key="orgQuantity"
label="盘前库存"
align="center"
prop="orgQuantity"
width="120"
>
<template #default="scope">
<el-form-item
:prop="`purchaseinventoryList.${scope.$index}.orgQuantity`"
:rules="tableRules.orgQuantity"
>
<el-input
v-model="scope.row.orgQuantity"
placeholder=""
disabled
/>
</el-form-item>
</template>
</el-table-column>
<el-table-column
key="totalQuantityDisplay"
label="实盘数量"
align="center"
prop="totalQuantityDisplay"
width="120"
>
<template #default="scope">
<el-form-item
:prop="`purchaseinventoryList.${scope.$index}.totalQuantityDisplay`"
:rules="tableRules.totalQuantityDisplay"
>
<el-input
v-model="scope.row.totalQuantityDisplay"
:disabled="viewStatus == 'view'"
placeholder=""
@input="handleTotalQuantity(scope.row)"
/>
</el-form-item>
</template>
</el-table-column>
<el-table-column
key="totalPrice"
label="实盘金额"
align="center"
prop="totalPrice"
width="150"
>
<template #default="scope">
<el-form-item
:prop="`purchaseinventoryList.${scope.$index}.totalPrice`"
:rules="tableRules.totalPrice"
>
<div class="select_wrapper_div">
<el-input
v-model="scope.row.totalPrice"
placeholder=""
:class="{ 'error-border': scope.row.error }"
disabled
>
<template #suffix>
</template>
</el-input>
</div>
</el-form-item>
</template>
</el-table-column>
<el-table-column
key="itemQuantityDisplay"
label="盈亏数量"
align="center"
prop="itemQuantityDisplay"
width="110"
>
<template #default="scope">
<el-form-item
:prop="`purchaseinventoryList.${scope.$index}.itemQuantityDisplay`"
:rules="tableRules.itemQuantityDisplay"
>
<el-input
v-model="scope.row.itemQuantityDisplay"
placeholder=""
@input="handleItemQuantity(scope.row)"
/>
</el-form-item>
</template>
</el-table-column>
<el-table-column
key="profitAmount"
label="盈亏金额"
align="center"
prop="profitAmount"
width="150"
>
<template #default="scope">
<el-form-item
:prop="`purchaseinventoryList.${scope.$index}.profitAmount`"
:rules="tableRules.profitAmount"
>
<el-input
v-model="scope.row.profitAmount"
placeholder=""
disabled
/>
</el-form-item>
</template>
</el-table-column>
<el-table-column
key="reasonCode"
label="盈亏类型"
align="center"
prop="reasonCode"
:show-overflow-tooltip="true"
width="120"
>
<template #default="scope">
<el-form-item
:prop="`purchaseinventoryList.${scope.$index}.reasonCode`"
:rules="tableRules.reasonCode"
>
<div class="select_wrapper_div">
<el-select
v-model="scope.row.reasonCode"
:disabled="viewStatus == 'view'"
placeholder="请选择盈亏类型"
:class="{ 'error-border': scope.row.error }"
clearable
>
<el-option
v-for="(item, index) in profit_reason"
:key="index"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
</el-form-item>
</template>
</el-table-column>
<el-table-column
key="reason"
label="盈亏原因"
align="center"
prop="reason"
:show-overflow-tooltip="true"
width="150"
>
<template #default="scope">
<el-form-item
:prop="`purchaseinventoryList.${scope.$index}.reason`"
:rules="tableRules.reason"
>
<el-input
v-model="scope.row.reason"
:disabled="viewStatus == 'view'"
placeholder=""
/>
</el-form-item>
</template>
</el-table-column>
<el-table-column
key="traceNo"
label="药品追溯码"
align="center"
prop="traceNo"
width="130"
>
<template #default="scope">
<el-tooltip
:content="formatContent(scope.row.traceNo)"
placement="top"
popper-class="custom-tooltip"
>
<el-form-item
:prop="`purchaseinventoryList.${scope.$index}.traceNo`"
:rules="tableRules.traceNo"
>
<el-input
:id="'traceNo' + `${scope.$index}`"
v-model="scope.row.traceNo"
placeholder=""
:disabled="viewStatus == 'view'"
@change="(value) => handleTraceNo(value, scope.row)"
/>
</el-form-item>
</el-tooltip>
</template>
</el-table-column>
<el-table-column
v-if="!viewStatus"
label="操作"
align="center"
width="80"
class-name="small-padding fixed-width"
fixed="right"
>
<template #default="scope">
<el-button
link
type="primary"
icon="Edit"
@click="handleScan(scope.row, scope.$index)"
>
扫码
</el-button>
</template>
</el-table-column>
</el-table>
<!-- <pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getTransferProductDetails(1)"
/> -->
</el-form>
</el-tab-pane>
</el-tabs>
<el-row
:gutter="10"
class="mb8"
style="margin-top: 15px; display: flex; align-items: center; justify-content: flex-start"
>
<el-col :span="3">
<span>制单人:{{ userStore.name }}</span>
</el-col>
<el-col :span="2">
<span>审核人:</span>
</el-col>
<el-col :span="2">
<span>单据状态:</span>
</el-col>
<el-col :span="6">
<el-row
:gutter="8"
style="display: flex; align-items: center; justify-content: flex-start"
>
<el-col :span="10">
<span>合计盈亏金额:{{ totalAmountFormatted }}</span>
</el-col>
</el-row>
</el-col>
</el-row>
<TraceNoDialog
:yp-name="ypName"
:row-data="rowData"
:open-dialog="openTraceNoDialog"
@submit="submit"
@cancel="openTraceNoDialog = false"
/>
</div>
</template>
<script setup name="chkstockPart">
import {
addProductStocktaking,
delProductStocktaking,
getCount,
getDetailInit,
getDispensaryList,
getPharmacyList,
getstocktakingDetail,
submitApproval,
} from '../components/api';
import PopoverList from '@/components/HealthLinkHis/popoverList/index.vue';
import TraceNoDialog from '@/components/HealthLinkHis/TraceNoDialog/index.vue';
import MedicineList from '../components/medicineList.vue';
import {formatDate} from '@/utils/index';
import useUserStore from '@/store/modules/user';
import {useRoute} from 'vue-router';
import {computed, defineEmits, getCurrentInstance, reactive, ref, toRefs, watch} from 'vue';
import {useStore} from '@/store/store';
import useTagsViewStore from '@/store/modules/tagsView';
import templateJson from './components/template';
import {hiprint} from 'vue-plugin-hiprint';
import Decimal from 'decimal.js';
const tagsViewStore = useTagsViewStore();
const store = useStore();
const route = useRoute();
const userStore = useUserStore();
const { proxy } = getCurrentInstance();
const { warehous_type, purchase_type, profit_reason } = proxy.useDict(
'warehous_type',
'purchase_type',
'profit_reason'
);
const viewStatus = ref('');
const loading = ref(false);
const ids = ref([]);
const single = ref(true);
const multiple = ref(true);
const visible = ref(false);
const rowIndex = ref(-1);
const totalAmount = computed(() => {
return form.purchaseinventoryList.reduce((accumulator, currentRow) => {
return new Decimal(accumulator || 0).plus(currentRow.profitAmount || 0).toNumber();
}, 0);
});
const totalAmountFormatted = computed(() => {
return new Decimal(totalAmount.value || 0).toFixed(4);
});
const openTraceNoDialog = ref(false);
const ypName = ref('');
const rowData = ref({});
const form = reactive({
purchaseinventoryList: [],
});
const receiptHeaderForm = reactive({
busNo: undefined,
occurrenceTime: formatDate(new Date()),
locationId: '',
time: '',
});
const data = reactive({
isEdit: false,
isAdding: true,
queryParams: {
pageNo: 1,
pageSize: 10,
searchKey: undefined, // 供应商名称
busNo: undefined, // 编码
statusEnum: undefined, // 状态
supplierId: undefined, // 供应商ID
applyTimeStart: undefined, // 申请时间开始
practitionerId: undefined, // 经手人ID
},
rules: {
purposeLocationId: [{ required: true, message: '请选择盘点仓库', trigger: 'change' }],
medicationType: [{ required: true, message: '请选择药品类型', trigger: 'change' }],
},
tableRules: {
name: [{ required: true, message: '项目不能为空', trigger: 'change' }],
unitCode: [{ required: true, message: '计量单位不能为空', trigger: 'change' }],
itemQuantity: [{ required: true, message: '盈亏数量不能为空', trigger: 'blur' }],
totalQuantity: [{ required: true, message: '实盘数量不能为空', trigger: 'blur' }],
},
});
const { queryParams, rules, tableRules } = toRefs(data);
const purposeTypeListOptions = ref(undefined); // 仓库列表
const freightListOptions = ref(undefined); // 货位列表
const selectedRows = ref([]); // 用于存储选中的行
const emit = defineEmits(['refresh']);
const tableRef = ref(undefined); // 表格引用
const medicineSearchKey = ref('');
const itemType = ref('');
// 监听路由变化
watch(
() => route.query,
(newValue) => {
if (newValue.isEdit) {
data.isEdit = true;
getstocktakingDetail({ busNo: newValue.supplyBusNo }).then((res) => {
editTable(res.data.records);
handleChangePurposeTypeEnum(res.data.records[0].purposeTypeEnum);
});
}
},
{ immediate: true }
);
const currentIndex = ref('');
function handleScan(row, index) {
rowData.value = row;
rowData.value.locationId = receiptHeaderForm.purposeLocationId;
rowData.value.itemType = receiptHeaderForm.medicationType;
ypName.value = row.name;
openTraceNoDialog.value = true;
currentIndex.value = index;
}
function submit(value) {
if (form.purchaseinventoryList[currentIndex.value].traceNo) {
form.purchaseinventoryList[currentIndex.value].traceNo =
form.purchaseinventoryList[currentIndex.value].traceNo + ',' + value;
} else {
form.purchaseinventoryList[currentIndex.value].traceNo = value;
}
openTraceNoDialog.value = false;
}
function formatContent(value) {
let content = '';
if (value) {
value.split(',').forEach((item, index) => {
content += `[${index + 1}] ${item}\n`;
});
return content;
}
}
function addNewRow() {
proxy.$refs['receiptHeaderRef'].validate((valid) => {
if (valid) {
// if (data.isAdding) {
// proxy.$message.warning("请先保存当前行后再新增");
// return;
// }
const newRow = {
id: '',
definitionId: '',
name: '',
itemBusNo: '',
itemTableName: '',
itemTable: '',
itemType: '',
itemType_enumText: '',
itemQuantity: '',
itemMaxQuantity: '',
itemId: '',
detailJson: '',
supplierId: '',
purposeTypeEnum: '',
purposeLocationId: '',
purposeLocationStoreId: '',
practitionerId: '',
traceNo: '',
invoiceNo: '',
lotNumber: '',
occurrenceTime: '',
startTime: '',
endTime: '',
partPercent: '',
price: '',
totalPrice: '',
sellPrice: '',
minSellPrice: '',
unitCode: '',
unitCode_dictText: '',
minUnitCode: '',
minUnitCode_dictText: '',
volume: '',
wbStr: '',
ybNo: '',
unitList: {}, // 单位列表
isEditing: true, // 标记当前行是否正在编辑
error: false, // 新增 error 字段
isSave: false, // 当前行是否保存
};
form.purchaseinventoryList.push(newRow);
data.isEdit = true;
data.isAdding = true; // 设置标志位为 true表示有未保存的
}
});
}
// 药品列表搜索
function handleSearch(value) {
medicineSearchKey.value = value;
}
// 选择药品
function selectRow(rowValue, index) {
rowIndex.value = index;
form.purchaseinventoryList[index].busNo = receiptHeaderForm.busNo; //单据号
form.purchaseinventoryList[index].purposeLocationId = receiptHeaderForm.purposeLocationId; //盘点仓库
form.purchaseinventoryList[index].purposeTypeEnum = receiptHeaderForm.purposeTypeEnum; //盘点仓库
form.purchaseinventoryList[index].itemId = rowValue.definitionId; // 盘点项目id
form.purchaseinventoryList[index].itemTable = rowValue.itemTableName; // 项目表名,耗材表/药品表
form.purchaseinventoryList[index].name = rowValue.name; // 项目名称
form.purchaseinventoryList[index].volume = rowValue.volume; // 规格
form.purchaseinventoryList[index].manufacturerText = rowValue.manufacturerText; // 厂家产地
form.purchaseinventoryList[index].partPercent = rowValue.partPercent; // 拆零比
form.purchaseinventoryList[index].lotNumber = rowValue.lotNumber; // 批号
form.purchaseinventoryList[index].totalQuantity = 0; // 实盘数量 默认0
form.purchaseinventoryList[index].currentUnitCode = rowValue.unitCode; // 当前选中单位
form.purchaseinventoryList[index].currentUnitCode_dictText = rowValue.unitCode_dictText; // 当前选中单位
form.purchaseinventoryList[index].unitCode = rowValue.unitCode; // 盘点单位,默认大单位
form.purchaseinventoryList[index].unitCode_dictText = rowValue.unitCode_dictText; // 大单位label
form.purchaseinventoryList[index].minUnitCode = rowValue.minUnitCode; // 小单位value
form.purchaseinventoryList[index].minUnitCode_dictText = rowValue.minUnitCode_dictText; // 小单位label
// 维护一个大小单位的map用来判断当前选中单位是大/小单位
form.purchaseinventoryList[index].unitCodeMap = {};
form.purchaseinventoryList[index].unitCodeMap[rowValue.unitCode] = 'unit';
form.purchaseinventoryList[index].unitCodeMap[rowValue.minUnitCode] = 'minUnit';
// 构造单位下拉列表
form.purchaseinventoryList[index].unitList = [
{ label: rowValue.unitCode_dictText, value: rowValue.unitCode },
];
// 拆零比大于1添加小单位选项
if (rowValue.partPercent > 1) {
form.purchaseinventoryList[index].unitList.push({
label: rowValue.minUnitCode_dictText,
value: rowValue.minUnitCode,
});
}
// 获取当前项目当前批次的库存信息
getCount({
itemId: rowValue.definitionId,
orgLocationId: receiptHeaderForm.purposeLocationId,
lotNumber: rowValue.lotNumber,
}).then((res) => {
if (res.data.length > 1) {
proxy.$modal.msgWarning(
`${rowValue.name},批次${rowValue.lotNumber}库存有误,请先确认后再盘点`
);
} else if (res.data.length == 1) {
let inventoryInfo = res.data[0];
form.purchaseinventoryList[index].orgQuantity = formatInventory(
inventoryInfo.orgQuantity,
rowValue.partPercent,
rowValue.unitCode_dictText,
rowValue.minUnitCode_dictText
); // 原仓库数量(小单位)
form.purchaseinventoryList[index].orgQuantityTemp = inventoryInfo.orgQuantity; // 原库存临时变量,用于切换单位显示
form.purchaseinventoryList[index].price = inventoryInfo.price; // 单价 默认大单位价格
form.purchaseinventoryList[index].priceTemp = inventoryInfo.price; // 临时存一下大单位的价格
form.purchaseinventoryList[index].startTime = proxy.formatDateStr(
inventoryInfo.productionDate
); // 生产日期
form.purchaseinventoryList[index].endTime = proxy.formatDateStr(inventoryInfo.expirationDate); // 有效期
form.purchaseinventoryList[index].supplierId = inventoryInfo.supplierId; // 供应商
form.purchaseinventoryList[index].minUnitPrice = (
inventoryInfo.price / rowValue.partPercent
).toFixed(2); // 计算出小单位价格
}
});
}
// 编辑表格 传入获取到的详情列表
function editTable(list) {
list.forEach((item) => {
const rowItem = {};
receiptHeaderForm.purposeLocationId = item.purposeLocationId;
receiptHeaderForm.medicationType = item.itemType;
receiptHeaderForm.purposeTypeEnum = item.purposeTypeEnum.toString();
rowItem.busNo = item.busNo;
rowItem.itemId = item.itemId; // 盘点项目id
rowItem.itemTable =
item.itemType == '1' ? 'med_medication_definition' : 'adm_device_definition'; // 项目表名,耗材表/药品表
rowItem.name = item.itemName; // 项目名称
rowItem.volume = item.totalVolume; // 规格
rowItem.manufacturerText = item.manufacturerText; // 厂家产地
rowItem.partPercent = item.partPercent; // 拆零比
rowItem.lotNumber = item.lotNumber; // 批号
rowItem.currentUnitCode = item.measurementUnitCode; // 盘点时保存的单位
rowItem.unitCode = item.measurementUnitCode; // 盘点时保存的单位
rowItem.unitCode_dictText = item.unitCode_dictText; // 大单位label
rowItem.minUnitCode = item.minUnitCode; // 小单位value
rowItem.minUnitCode_dictText = item.minUnitCode_dictText; // 小单位label
rowItem.reasonCode = item.reasonCode; // 盈亏类型
rowItem.reason = item.reason; // 盈亏原因
rowItem.purposeLocationId = item.purposeLocationId;
rowItem.supplierId = item.supplierId;
// 维护一个大小单位的map用来判断当前选中单位是大/小单位
rowItem.unitCodeMap = {};
rowItem.unitCodeMap[item.unitCode] = 'unit';
rowItem.unitCodeMap[item.minUnitCode] = 'minUnit';
// 构造单位下拉列表
rowItem.unitList = [{ label: item.unitCode_dictText, value: item.unitCode }];
// 拆零比大于1添加小单位选项
if (item.partPercent > 1) {
rowItem.unitList.push({
label: item.minUnitCode_dictText,
value: item.minUnitCode,
});
}
// 判断保存时的盘点单位是大还是小
const isUnit = item.measurementUnitCode == item.unitCode;
rowItem.orgQuantity = isUnit
? formatInventory(
item.orgQuantity,
item.partPercent,
item.unitCode_dictText,
item.minUnitCode_dictText
)
: item.orgQuantity; // 原仓库数量(小单位)
rowItem.itemQuantityDisplay = isUnit
? formatInventory(
item.itemQuantity,
item.partPercent,
item.unitCode_dictText,
item.minUnitCode_dictText
)
: item.itemQuantity; // 盈亏数量(小单位)
rowItem.totalQuantityDisplay = isUnit
? formatInventory(
item.orgQuantity + item.itemQuantity,
item.partPercent,
item.unitCode_dictText,
item.minUnitCode_dictText
)
: item.orgQuantity + item.itemQuantity; // 实盘数量(小单位)
rowItem.itemQuantity = item.itemQuantity;
rowItem.totalQuantity = item.orgQuantity + item.itemQuantity;
rowItem.minUnitPrice = (item.price / item.partPercent).toFixed(2); // 单价 默认大单位价格
rowItem.price = isUnit ? item.price : rowItem.minUnitPrice; // 单价 默认大单位价格
rowItem.priceTemp = item.price; // 临时存一下大单位的价格
rowItem.totalPrice = new Decimal(rowItem.totalQuantity || 0)
.mul(rowItem.minUnitPrice || 0)
.toFixed(2);
// 盈亏金额
rowItem.profitAmount = new Decimal(rowItem.itemQuantity || 0)
.mul(rowItem.minUnitPrice || 0)
.toFixed(2);
// 校验盘前库存 + 盈亏数量 是否等于实盘数量 不相等证明库存有变动
if (item.orgQuantity + item.itemQuantity != item.totalQuantity) {
proxy.$modal.msgWarning(
`${item.itemName},批次${item.lotNumber}库存有变动,实盘数量已自动计算为当前实际库存数量`
);
}
console.log(rowItem, '34567890-');
form.purchaseinventoryList.push(rowItem);
});
console.log(form.purchaseinventoryList, '34567890-');
}
/**
* 格式化库存数量显示(大单位情况)
* @param quantity 小单位库存数量
* @param partPercent 拆零比
* @param unitCode 大单位
* @param minUnitCode 小单位
*/
function formatInventory(quantity, partPercent, unitCode, minUnitCode) {
// 处理负数情况
const isNegative = quantity < 0;
const absQuantity = Math.abs(quantity);
if (absQuantity % partPercent !== 0) {
const integerPart = Math.floor(absQuantity / partPercent);
const decimalPart = absQuantity % partPercent;
let result = integerPart.toString() + ' ' + unitCode;
if (decimalPart > 0) {
result += decimalPart.toString() + ' ' + minUnitCode;
}
return isNegative ? '-' + result : result;
}
// 整除情况
const result = absQuantity / partPercent;
return isNegative ? '-' + result : result;
}
// 单位处理
function handleUnitCodeChange(row, value) {
if (row.unitCodeMap[value] == 'unit') {
// 大单位情况处理
row.price = row.priceTemp;
row.orgQuantity = formatInventory(
row.orgQuantityTemp,
row.partPercent,
row.unitCode_dictText,
row.minUnitCode_dictText
);
} else {
// 小单位处理
row.price = row.minUnitPrice;
row.orgQuantity = row.orgQuantityTemp;
}
// 判断上一次选中的单位是大还是小,如果上一次是大单位,到这里是切换为小的,
if (row.unitCodeMap[row.currentUnitCode] == 'unit') {
// 实盘数量
// row.totalQuantity = row.totalQuantity * row.partPercent;
row.totalQuantityDisplay = row.totalQuantity;
// 实盘金额
row.totalPrice = new Decimal(row.totalQuantity || 0).mul(row.minUnitPrice || 0).toFixed(2);
// 盈亏数量
row.itemQuantityDisplay = row.itemQuantity;
// 盈亏金额
row.profitAmount = new Decimal(row.itemQuantity || 0).mul(row.minUnitPrice || 0).toFixed(2);
} else {
// 实盘数量
row.totalQuantityDisplay = formatInventory(
row.totalQuantity,
row.partPercent,
row.unitCode_dictText,
row.minUnitCode_dictText
);
// 实盘金额
row.totalPrice = new Decimal(row.totalQuantity || 0).mul(row.minUnitPrice || 0).toFixed(2);
// 盈亏数量
row.itemQuantityDisplay = formatInventory(
row.itemQuantity,
row.partPercent,
row.unitCode_dictText,
row.minUnitCode_dictText
);
// 盈亏金额
row.profitAmount = new Decimal(row.itemQuantity || 0).mul(row.minUnitPrice || 0).toFixed(2);
}
row.currentUnitCode = value;
}
// 处理实盘数量(全都转换为小单位数量传给后端)
function handleTotalQuantity(row) {
if (row.unitCodeMap[row.unitCode] == 'unit') {
// 实盘数量
row.totalQuantity = new Decimal(row.totalQuantityDisplay || 0)
.mul(row.partPercent || 0)
.toNumber();
// 实盘金额
row.totalPrice = new Decimal(row.totalQuantity || 0).mul(row.minUnitPrice || 0).toFixed(2);
// 盈亏数量
row.itemQuantity = new Decimal(row.totalQuantity || 0)
.minus(row.orgQuantityTemp || 0)
.toNumber();
row.itemQuantityDisplay = formatInventory(
row.itemQuantity,
row.partPercent,
row.unitCode_dictText,
row.minUnitCode_dictText
);
// 盈亏金额
row.profitAmount = new Decimal(row.itemQuantity || 0).mul(row.minUnitPrice || 0).toFixed(2);
} else {
// 实盘数量
row.totalQuantity = row.totalQuantityDisplay;
// 实盘金额
row.totalPrice = new Decimal(row.totalQuantity || 0).mul(row.minUnitPrice || 0).toFixed(2);
// 盈亏数量
row.itemQuantity = new Decimal(row.totalQuantity || 0)
.minus(row.orgQuantityTemp || 0)
.toNumber();
row.itemQuantityDisplay = row.itemQuantity;
// 盈亏金额
row.profitAmount = new Decimal(row.itemQuantity || 0).mul(row.minUnitPrice || 0).toFixed(2);
}
}
// 处理盈亏数量(全都转换为小单位数量传给后端)
function handleItemQuantity(row) {
if (row.unitCodeMap[row.unitCode] == 'unit') {
row.itemQuantity = new Decimal(row.itemQuantityDisplay || 0)
.mul(row.partPercent || 0)
.toNumber();
// 实盘数量
row.totalQuantity = new Decimal(row.orgQuantityTemp || 0)
.plus(row.itemQuantity || 0)
.toNumber();
row.totalQuantityDisplay = formatInventory(
row.totalQuantity,
row.partPercent,
row.unitCode_dictText,
row.minUnitCode_dictText
);
// 实盘金额
row.totalPrice = new Decimal(row.totalQuantity || 0).mul(row.minUnitPrice || 0).toFixed(2);
// 盈亏金额
row.profitAmount = new Decimal(row.itemQuantity || 0).mul(row.minUnitPrice || 0).toFixed(2);
} else {
row.itemQuantity = row.itemQuantityDisplay;
// 实盘数量
row.totalQuantity = new Decimal(row.orgQuantityTemp || 0)
.plus(row.itemQuantity || 0)
.toNumber();
row.totalQuantityDisplay = row.totalQuantity;
// 实盘金额
row.totalPrice = new Decimal(row.totalQuantity || 0).mul(row.minUnitPrice || 0).toFixed(2);
// 盈亏金额
row.profitAmount = new Decimal(row.itemQuantity || 0).mul(row.minUnitPrice || 0).toFixed(2);
}
}
// 打印盘点单
function handlePrint() {
const result = [];
form.purchaseinventoryList = form.purchaseinventoryList.map((item) => {
return {
...item,
price: Number(item.price).toFixed(2),
profitAmount: Number(item.profitAmount).toFixed(2),
reasonCode_dictText: profit_reason.value.filter((k) => k.value == item.reasonCode)[0]?.label,
};
});
result.push({
purposeLocationName: form.purchaseinventoryList[0].purposeLocationName,
name: userStore.name,
totalAmount: new Decimal(totalAmount.value || 0).toFixed(2),
...receiptHeaderForm,
purchaseinventoryList: form.purchaseinventoryList,
});
console.log(result, '345678987654');
const printElements = JSON.parse(
JSON.stringify(templateJson).replace(/{{HOSPITAL_NAME}}/g, userStore.hospitalName)
);
var hiprintTemplate = new hiprint.PrintTemplate({ template: printElements }); // 定义模板
hiprintTemplate.print2(result, {
// printer: 'EPSON LQ-80KFII',
title: '打印标题',
}); //开始打印
}
// 保存
function handleSave() {
addProductStocktaking(form.purchaseinventoryList).then((res) => {
if (res.code == 200) {
proxy.$modal.msgSuccess('保存成功');
}
});
}
/** 选择条数 */
function handleSelectionChange(selection) {
// selectedData.value = selection.map((item) => ({ ...item })); // 存储选择的行数据
ids.value = selection.map((item) => item.id);
selectedRows.value = selection;
single.value = selection.length != 1;
multiple.value = !selection.length;
}
function deleteSelectedRows() {
let length = selectedRows.value.length;
if (length === 0) return;
// 收集需要删除的ID包括已保存和未保存的行
let idsToDelete = selectedRows.value
.filter((item) => item.id) // 只有有ID的才需要从数据库删除
.map((item) => item.id);
let deletePromise;
if (idsToDelete.length > 0) {
// 有需要从数据库删除的行
deletePromise = delProductStocktaking(idsToDelete);
} else {
// 没有需要从数据库删除的行创建一个立即resolve的Promise
deletePromise = Promise.resolve({ code: 200 });
}
deletePromise
.then((res) => {
if (res.code == 200) {
form.purchaseinventoryList = form.purchaseinventoryList.filter(
(row) => !selectedRows.value.includes(row)
);
// 更新状态
if (form.purchaseinventoryList && form.purchaseinventoryList.length > 0) {
data.isEdit = true;
} else {
data.isEdit = false;
}
data.isAdding = false;
proxy.$message.success('删除成功');
} else {
proxy.$message.error('删除失败');
}
})
.catch(() => {
proxy.$message.error('删除失败');
});
}
/**计算合计金额 - 已改为计算属性,自动更新,不再需要手动调用 */
// function handleTotalAmount() {
// totalAmount.value = form.purchaseinventoryList.reduce((accumulator, currentRow) => {
// return accumulator + (Number(currentRow.profitAmount) || 0);
// }, 0);
// }
// function formatSuffixUnitCode(row, quantityField) {
// if (row.unitCode) {
// return (
// row.unitCodeMap[scope.row?.unitCode] == 'minUnit' || row.totalQuantity % row.partPercent == 0
// );
// } else {
// return true;
// }
// }
/** 提交审核 */
function submitAudit() {
let length = form.purchaseinventoryList.length;
if (length < 1) {
proxy.$modal.msgWarning('请先添加单据');
} else {
submitApproval(receiptHeaderForm.busNo).then((res) => {
if (res.code == 200) {
proxy.$modal.msgSuccess('提交审批成功');
tagsViewStore.delView(router.currentRoute.value);
// 跳转到盘点管理页面
router.replace({ path: 'chkstockRecord' });
store.clearCurrentDataPD();
emit('refresh');
visible.value = false;
}
});
}
}
function handleTraceNo(value, row) {
row.traceNo = value + ',';
}
// 切换仓库类型获取药房/药库列表 目的仓库切换
function handleChangePurposeTypeEnum(value, type) {
if (value == 16) {
getPharmacyList().then((res) => {
purposeTypeListOptions.value = res.data;
if (!route.query.supplyBusNo && !type) {
receiptHeaderForm.purposeLocationId = '';
}
});
} else if (value == 11) {
getDispensaryList().then((res) => {
purposeTypeListOptions.value = res.data;
if (!route.query.supplyBusNo && !type) {
receiptHeaderForm.purposeLocationId = '';
}
});
} else if (value === 17) {
// 处理耗材库类型
// 参考采购订单模块的实现,硬编码设置中心耗材库信息
purposeTypeListOptions.value = [
{
id: "1",
name: "中心耗材库",
formEnum: 17,
children: []
}
];
// 设置默认仓库和货位
getinitValue();
} else {
console.log('未知的仓库类型值:', value);
purposeTypeListOptions.value = [];
freightListOptions.value = [];
}
}
// 获取默认值
function getinitValue() {
if (purposeTypeListOptions.value.length > 0) {
// 判断是否有盘点仓库
receiptHeaderForm.purposeLocationId = purposeTypeListOptions.value[0].id; // 盘点仓库默认值
if (
purposeTypeListOptions.value[0].children &&
purposeTypeListOptions.value[0].children.length > 0
) {
// 判断盘点仓库内是否有货位
freightListOptions.value = purposeTypeListOptions.value[0].children;
receiptHeaderForm.purposeLocation = purposeTypeListOptions.value[0].children[0].name;
}
}
}
// 切换仓库获取货位列表 -20250414
function handleCabinetChange(value) {
receiptHeaderForm.purposeLocation = '';
if (value) {
let purposeTypeListOption = purposeTypeListOptions.value.filter(
(item) => item.id === value.toString()
);
freightListOptions.value = purposeTypeListOption[0] ? purposeTypeListOption[0].children : [];
receiptHeaderForm.purposeLocation =
freightListOptions.value && freightListOptions.value.length > 0
? purposeTypeListOption[0].children[0].name
: '';
} else {
freightListOptions.value = [];
}
}
function getbusNo() {
if (route.query.supplyBusNo) {
receiptHeaderForm.busNo = route.query.supplyBusNo;
viewStatus.value = route.query.view;
sessionStorage.setItem('busNopd', '');
} else {
if (!sessionStorage.getItem('busNopd')) {
getDetailInit().then((response) => {
receiptHeaderForm.busNo = response.data.busNo;
sessionStorage.setItem('busNopd', receiptHeaderForm.busNo);
// busNoAdd.value = response.data.busNo; // 单据号新增
});
} else {
receiptHeaderForm.busNo = sessionStorage.getItem('busNopd');
}
}
}
getbusNo(); // 单据号取得
// 导出
function handleExport() {
proxy.downloadGet(
'/inventory-manage/stocktaking/excel-out',
{
busNo: supplyBusNo.value,
},
`盘点单明细_${proxy.formatDateStr(new Date(), 'YYYY-MM-DD')}.xlsx`
);
}
</script>
<style scoped>
.custom-tree-node {
display: flex;
align-items: center;
}
.title {
font-weight: bold;
font-size: large;
margin-bottom: 10px;
}
.error-border {
border: 1px solid red;
}
</style>