<template>
<div class="flex flex-col h-full overflow-hidden" v-loading="loading">
<div class="flex-1 h-full option-container">
<div class="container">
<el-form
:model="formData"
label-width="120px"
class="w-full"
ref="formRef"
>
<div class="tablle-top-view" v-if="step == 1">
<table
class="mt-7"
:class="{ 'disabled-style': !is_show }"
:style="{ backgroundColor: !is_show ? '#fff' : '#fffdec' }"
>
<tbody>
<tr class="flex">
<td class="flex-1">
<div class="label">领用单号</div>
<div class="title">{{ formData.order_no }}</div>
</td>
<td class="flex-1">
<div class="label">创建日期</div>
<div class="title">{{ formData.create_time }}</div>
</td>
<td class="flex-1">
<div class="label">门店</div>
<div class="title">{{ formData.store }}</div>
</td>
</tr>
<tr class="flex">
<td class="flex-1">
<div class="label">领用人</div>
<div class="title">{{ formData.receive_name }}</div>
</td>
<td class="flex-1">
<div class="label">领入库房</div>
<div class="title">
{{ formData.in_repertory_name }}
</div>
</td>
<td class="flex-1">
<div class="label">领出库房</div>
<div class="title">
{{ formData.out_repertory_name }}
</div>
</td>
</tr>
<tr>
<td class="flex-1">
<div class="label">备注</div>
<input
type="text"
name="source"
v-model="formData.remark"
placeholder=""
:style="{
backgroundColor: !is_show ? '#fff' : '#fffdec',
}"
/>
</td>
</tr>
</tbody>
</table>
</div>
<div class="table-center-view" v-if="step == 1">
<!-- 搜索框 -->
<!-- <DrugSearch
v-if="Number(formData.receive_status) === 0"
:in_repertory_id="formData.in_repertory_id"
:out_repertory_id="formData.out_repertory_id"
@add-drug="handleAddDrug"
/> -->
<!-- 表格 -->
<div class="table-container">
<div class="table-wrapper">
<table
border
style="width: 100%; border-collapse: collapse"
ref="drugTableRef"
>
<thead>
<tr>
<th width="40">
<input
type="checkbox"
v-model="isAllSelected"
@change="toggleAllSelection"
/>
</th>
<th>编码</th>
<th>药品名称</th>
<th>批次</th>
<th>生产批号</th>
<th>效期</th>
<th>进价</th>
<th>金额</th>
<th>领用数量</th>
<th>可退数量</th>
<th>退回数量</th>
</tr>
</thead>
<tbody>
<template v-for="(row, index) in tableData" :key="index">
<tr>
<td>
<input type="checkbox" v-model="row.selected" />
</td>
<!-- 药品编号 -->
<td width="80">
<span type="text">{{ row.commodity_no }}</span>
</td>
<!-- 药品名称 -->
<td>
<div type="text">{{ row.commodity_name }}</div>
<div type="text" style="color: #999; font-size: 11px">
{{ row.size }}
</div>
</td>
<!-- 批次 -->
<td>
<div v-if="!row.commodityRelateList" type="text">
{{ row.serial_no }}
</div>
<div v-else class="select-view">
<el-popover
placement="bottom-start"
trigger="click"
width="700"
:ref="(el) => setPopoverRef3(el, index)"
>
<!-- @selection-change="
(selection) =>
handleBatchSelection(selection, row, index)
" -->
<el-table
:data="row.commodityRelateList"
border
:ref="(el) => setTableRef(el, index)"
>
<el-table-column
type="selection"
width="40"
></el-table-column>
<el-table-column
label="批次"
prop="serial_no"
></el-table-column>
<el-table-column
label="生产批号"
prop="batch_no"
></el-table-column>
<el-table-column
label="入库时间"
prop="in_storage_date"
></el-table-column>
<el-table-column
label="效期"
prop="expiry_date"
></el-table-column>
<el-table-column
label="进价"
prop="pur_price"
></el-table-column>
<el-table-column
label="账面数量"
prop="show_memory_num"
></el-table-column>
</el-table>
<!-- 确定和取消 -->
<div
class="dialog-footer"
style="text-align: right; margin-top: 10px"
>
<el-button
size="small"
type="primary"
@click="confirmBatchSelection(index)"
>确定</el-button
>
<el-button
size="small"
@click="closePopover3(index)"
>取消</el-button
>
</div>
<template #reference>
<!-- 显示已选批次 -->
<div
class="reference-item flex justify-between items-center"
>
<div
v-if="
row.selectedBatches &&
row.selectedBatches.length
"
>
已选择批次({{ row.selectedBatches.length }})
</div>
<div
v-else
link
type="primary"
size="small"
style="margin-right: 10px; color: #999"
>
不指定批次
</div>
<bc-icon
name="ele-ArrowDown"
class="icon-grow"
></bc-icon>
</div>
</template>
</el-popover>
</div>
</td>
<!-- 生产批号 -->
<td>
<div type="text">{{ row.batch_no }}</div>
</td>
<!-- 效期 -->
<td width="120">
<div type="text">{{ row.expiry_date }}</div>
</td>
<!--进价 -->
<td>
<div type="text">{{ row.pur_price }}</div>
</td>
<td>
<div type="text">{{ row.sale_price }}</div>
</td>
<td>
<div type="text">
{{ row.show_commodity_num }}
<!-- <span
class="text"
v-if="Number(row.commodity_num) > 0"
>{{ row.commodity_num }}{{ row.unit }}</span
>
<span
class="text"
v-if="Number(row.commodity_split_num) > 0"
>{{ row.commodity_split_num
}}{{ row.min_dose_unit }}</span
> -->
</div>
</td>
<td>
<div type="text">
{{ row.show_returnable_num }}
<!-- <span
class="text"
v-if="Number(row.returnable_num) > 0"
>{{ row.returnable_num }}{{ row.unit }}</span
>
<span
class="text"
v-if="Number(row.returnable_split_num) > 0"
>{{ row.returnable_split_num
}}{{ row.min_dose_unit }}</span
> -->
</div>
</td>
<!-- 退回数量 -->
<td width="170">
<div
v-if="
row.selectedBatches && row.selectedBatches.length
"
class="relateList"
>
<span
class="text"
v-if="Number(row.application_num) > 0"
>{{ row.application_num }}{{ row.unit }}</span
>
<span
class="text"
v-if="Number(row.application_split_num) > 0"
>{{ row.application_split_num
}}{{ row.min_dose_unit }}</span
>
</div>
<div v-else class="input-group">
<el-input
v-model="row.application_num"
class="custom-input"
@change="handle_stock_num(row, 'application_num')"
>
<template #append>
<div class="unit">{{ row.unit || '' }}</div>
</template>
</el-input>
<el-input
v-model="row.application_split_num"
class="custom-input"
@change="
handle_stock_num(row, 'application_split_num')
"
>
<template #append>
<div class="unit">
{{ row.min_dose_unit || '' }}
</div>
</template>
</el-input>
</div>
</td>
</tr>
<!-- 子行 -->
<template
v-for="(rowItem, subIndex) in row?.selectedBatches"
:key="subIndex + '-sub'"
>
<tr>
<td></td>
<td></td>
<td></td>
<td>
<div type="text">{{ rowItem.serial_no }}</div>
</td>
<td>
<div type="text">{{ rowItem.batch_no }}</div>
</td>
<td>
<div type="text">{{ rowItem.expiry_date }}</div>
</td>
<!--进价 -->
<td>
<div type="text">{{ rowItem.pur_price }}</div>
</td>
<td>
<div type="text">{{ rowItem.sale_price }}</div>
</td>
<td>
<div type="text">
{{ rowItem.show_commodity_num }}
</div>
</td>
<td>
<div type="text">
{{ rowItem.show_returnable_num }}
</div>
</td>
<td width="170">
<div class="input-group">
<el-input
v-model="rowItem.application_num"
class="custom-input"
@change="
handle_stock_num(rowItem, 'application_num');
updateTotalNumForRow(row);
"
>
<template #append>
<div class="unit">
{{ rowItem.unit || '' }}
</div>
</template>
</el-input>
<el-input
v-model="rowItem.application_split_num"
class="custom-input"
@change="
handle_stock_num(
rowItem,
'application_split_num'
);
updateTotalNumForRow(row);
"
>
<template #append>
<div class="unit">
{{ rowItem.min_dose_unit || '' }}
</div>
</template>
</el-input>
</div>
</td>
</tr>
</template>
</template>
</tbody>
</table>
</div>
<div class="table-foot-view">
<div class="foot-view">
<span>品种</span> {{ tableData?.length || 0
}}<span>, 数量</span>{{ totalQuantity || 0 }}
</div>
</div>
</div>
<!-- 表格 -->
</div>
<div class="tablle-top-view" v-if="step == 2">
<table
class="mt-7"
:class="{ 'disabled-style': !is_show }"
:style="{ backgroundColor: !is_show ? '#fff' : '#fffdec' }"
>
<tbody>
<tr class="flex">
<td class="flex-1">
<div class="label">门店</div>
<div class="title">{{ formData.store }}</div>
</td>
<td class="flex-1">
<div class="label">原领用单号</div>
<div class="title">{{ formData.order_no }}</div>
</td>
<td class="flex-1">
<div class="label">原领用人</div>
<div class="title">{{ formData.receive_name }}</div>
</td>
</tr>
<tr class="flex">
<td class="flex-1">
<div class="label">入库库房</div>
<div class="title">
{{ formData.in_repertory_name }}
</div>
</td>
<td class="flex-1">
<div class="label">出库库房</div>
<div class="title">
{{ formData.out_repertory_name }}
</div>
</td>
<td class="flex-1">
<div class="label">备注</div>
<div class="title">
{{ formData.remark }}
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div class="table-center-view" v-if="step == 2">
<!-- 表格 -->
<div class="table-container">
<div class="table-wrapper">
<table
border
style="width: 100%; border-collapse: collapse"
ref="drugTableRef"
>
<thead>
<tr>
<th>编码</th>
<th>名称</th>
<th>批次</th>
<th>生产批号</th>
<th>效期</th>
<th>进价</th>
<th>退回数量</th>
<th>金额</th>
</tr>
</thead>
<tbody>
<template v-for="(row, index) in tableData" :key="index">
<!-- 子行 -->
<template
v-for="(rowItem, subIndex) in row?.selectedBatches"
:key="subIndex + '-sub'"
>
<tr>
<!-- 药品编号 -->
<td width="80">
<span type="text">{{ row.commodity_no }}</span>
</td>
<!-- 药品名称 -->
<td>
<div type="text">{{ row.commodity_name }}</div>
<div
type="text"
style="color: #999; font-size: 11px"
>
{{ row.size }}
</div>
</td>
<td>
<div type="text">{{ rowItem.serial_no }}</div>
</td>
<td>
<div type="text">{{ rowItem.batch_no }}</div>
</td>
<td>
<div type="text">{{ rowItem.expiry_date }}</div>
</td>
<!--进价 -->
<td>
<div type="text">{{ rowItem.pur_price }}</div>
</td>
<td>
<div type="text">
<span
class="text"
v-if="Number(row.application_num) > 0"
>{{ row.application_num }}{{ row.unit }}</span
>
<span
class="text"
v-if="Number(row.application_split_num) > 0"
>{{ row.application_split_num
}}{{ row.application_split_num }}</span
>
</div>
</td>
<td>
<div type="text">{{ rowItem.pur_price }}</div>
</td>
<!-- <td width="170">
<div class="input-group">
<el-input
v-model="rowItem.application_num"
class="custom-input"
@change="
handle_stock_num(rowItem, 'application_num');
updateTotalNumForRow(row);
"
>
<template #append>
<div class="unit">
{{ rowItem.unit || '' }}
</div>
</template>
</el-input>
<el-input
v-model="rowItem.application_split_num"
class="custom-input"
@change="
handle_stock_num(
rowItem,
'application_split_num'
);
updateTotalNumForRow(row);
"
>
<template #append>
<div class="unit">
{{ rowItem.min_dose_unit || '' }}
</div>
</template>
</el-input>
</div>
</td> -->
</tr>
</template>
</template>
</tbody>
</table>
</div>
<div class="table-foot-view">
<div class="foot-view">
<span>品种</span> {{ tableData?.length || 0
}}<span>, 数量</span>{{ totalQuantity || 0 }}
</div>
</div>
</div>
<!-- 表格 -->
</div>
<footer class="footer-view" v-if="formData.out_repertory_id">
<div class="left-btns">
<!-- 草稿 可以删除 -->
<el-button
v-if="Number(formData.receive_status) == 0"
type="primary"
@click="deleteReceiveDraft"
>删除</el-button
>
</div>
<div class="right-btns">
<el-button
v-if="Number(formData.receive_status) == 0"
type="primary"
@click="submitForm"
>提交</el-button
>
<el-button
v-if="Number(formData.receive_status) == 1"
type="primary"
@click="confirmCheckForm"
>审核</el-button
>
<el-button
v-if="step == 1"
type="primary"
@click="setStep(2)"
:disabled="!isAllSelected"
>下一步</el-button
>
<el-button v-if="step == 2" type="primary" @click="setStep(1)"
>上一步</el-button
>
<el-button
v-if="step == 2"
type="primary"
@click="backReceiveRecord"
>提交</el-button
>
<el-button
v-if="Number(formData.receive_status) == 0"
type="primary"
@click="saveDraft"
>保存草稿</el-button
>
<el-button @click="closeForm">关闭</el-button>
</div>
</footer>
</el-form>
</div>
</div>
</div>
</template>
<script lang="ts" setup name="requisitionBack">
import { ref, watch, onMounted, computed, watchEffect } from 'vue';
import {
useDeptController,
useRepertoryController,
useOutAndInStockController,
useInnerCodeController,
} from '/@/api';
import DrugSearch from '../drugSearch/index.vue';
import { DrugItem } from '../../type';
import { Utils, HsMessage, HsMessageBox } from 'hs-admin-ui';
import { showTextPopup } from '../textPopup/index.ts';
import { setLocalSystemParams } from 'hs-admin-ui/dist/types/utils';
const { getListAllRepertory } = useRepertoryController(); // 仓库(药房)
const { getDeptUserTree } = useDeptController(); // 领用人
const {
getCommodityRepertoryStock,
postSaveReceiveDraft,
postSaveReceiveRecord,
postSaveReceiveRecordReturn,
postAuditReceiveRecord,
getDetailReceive,
postRevokeReceiveRecord,
postDeleteReceiveDraft,
getGoodseatCommodityRepertory,
} = useOutAndInStockController(); //查询商品在仓库里的库存信息
const { getValueBySet } = useInnerCodeController();
const props = defineProps({
close: {
type: Function,
},
typeText: {
type: String,
},
id: {
type: String,
},
data: {
type: Object,
},
});
const loading = ref(false);
const step = ref(2);
const repertory_list = ref([]) as any; //仓库列表
const deptData = ref([]) as any; //领用人
// 表格数据
// 表格数据
const tableData = ref<DrugItem[]>([]);
const is_show = ref(true);
const formData = ref({
id: '',
order_no: '',
store: '', //门店
create_time: '', //创建日期
receive: [],
receive_status: '', //状态状态 0:草稿 1:待审核 2:已完成 3:审核驳回 4: 已撤回]
receive_time: '', //领用时间
receive_id: '', //领用人ID
receive_name: '', //领用人名称
receive_dept_id: '', //领用人部门ID
in_repertory_id: '', //入库药房ID
out_repertory_id: '', //出库药房ID
in_repertory_name: '',
out_repertory_name: '',
remark: '', //备注:
});
const FN = Utils.fixedNumAccuracy;
const totalQuantity = computed(() => {
return tableData.value?.reduce((sum, item) => {
const value = parseFloat(item.total_num);
return FN(Utils.add(sum, isNaN(value) ? 0 : value));
}, 0);
});
function setStep(stepNum: number) {
step.value = stepNum;
if (stepNum == 1) {
//下一步
}
}
const totalPurAmount = computed(() => {
return (
tableData.value?.reduce((sum, item) => {
const value = parseFloat(item.total_num);
const price = parseFloat(item.pur_price);
// 如果任意一个不是有效数字,则跳过该条目
if (isNaN(value) || isNaN(price)) {
return FN(sum);
}
return FN(Utils.add(sum, value * price));
}, 0) ?? 0
); // 如果 tableData 不存在,默认返回 0
});
const totalSaleAmount = computed(() => {
return (
tableData.value?.reduce((sum, item) => {
const value = parseFloat(item.total_num);
const price = parseFloat(item.sale_price);
// 如果任意一个不是有效数字,则跳过该条目
if (isNaN(value) || isNaN(price)) {
return FN(sum);
}
return FN(Utils.add(sum, value * price));
}, 0) ?? 0
); // 如果 tableData 不存在,默认返回 0
});
// 定义 refs
const inRepertoryRef = ref();
const receiverRef = ref();
const outRepertoryRef = ref();
const drugTableRef = ref();
const focusSelectInput = async (refName) => {
// await nextTick();
const selectComponent = refName?.value;
if (selectComponent && selectComponent.handleOpen) {
selectComponent.handleOpen(); // 推荐方式
} else {
const selectEl = refName?.value?.$el;
const selection = selectEl?.querySelector('.el-select__selection');
if (selection) {
selection.click();
}
}
};
const focusSelectCascader = async (refName) => {
// await nextTick();
const cascaderEl = document.querySelector('.el-cascader');
if (cascaderEl) {
const input = cascaderEl.querySelector('.el-input__inner');
if (input) {
input.click(); // 打开面板
}
}
};
// 滚动到指定元素
const scrollToElement = (element) => {
if (element && element.scrollIntoView) {
element.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
};
const focusTableRowInput = async (rowIndex = 0) => {
// await nextTick();
const tableEl = drugTableRef.value;
if (!tableEl) return;
console.log('tableEl', tableEl);
const rows = tableEl.querySelectorAll('tbody tr');
console.log('rows', rows);
if (rowIndex >= 0 && rowIndex < rows.length) {
const row = rows[rowIndex];
const input = row.querySelector('input');
console.log('input', input);
if (input) {
input.focus();
}
}
};
// 校验方法
const validateForm = () => {
const errors = [];
// 校验入库药房
if (!formData.value.in_repertory_id) {
errors.push({ field: 'in_repertory_id', message: '请选择入库药房' });
}
// 校验领用人
if (!formData.value.receive_id) {
errors.push({ field: 'receive', message: '请选择领用人' });
}
// 校验出库药房
if (!formData.value.out_repertory_id) {
errors.push({ field: 'out_repertory_id', message: '请选择出库药房' });
}
// 校验表格中的领用数量
const invalidIndex = tableData.value.findIndex(
(row) => !row.application_num || Number(row.application_num) <= 0
);
if (invalidIndex >= 0) {
errors.push({
field: 'table',
message: `第 ${invalidIndex + 1} 行领用数量必须大于0`,
});
// 聚焦 + 滚动
focusTableRowInput(invalidIndex);
const rows = drugTableRef.value?.querySelectorAll('tbody tr');
if (rows && rows.length > invalidIndex) {
scrollToElement(rows[invalidIndex]);
}
} else if (tableData.value?.length === 0) {
errors.push({
field: 'table',
message: '请输入药品名称或扫码添加',
});
}
if (errors.length > 0) {
const firstError = errors[0];
HsMessage.error(firstError.message);
switch (firstError.field) {
case 'in_repertory_id':
focusSelectInput(inRepertoryRef);
scrollToElement(inRepertoryRef.value);
break;
case 'receive':
focusSelectCascader(receiverRef);
scrollToElement(receiverRef.value);
break;
case 'out_repertory_id':
focusSelectInput(outRepertoryRef);
scrollToElement(outRepertoryRef.value);
break;
case 'table':
break;
}
return false;
}
return true;
};
//更新总量
const updateTotalNumForRow = (row) => {
if (row.selectedBatches && row.selectedBatches.length > 0) {
// 退回数量
const totalApplicationNum = row.selectedBatches.reduce(
(sum, batch) => sum + Number(batch.application_num || 0),
0
);
const totalApplicationSplitNum = row.selectedBatches.reduce(
(sum, batch) => sum + Number(batch.application_split_num || 0),
0
);
row.application_num = totalApplicationNum;
row.application_split_num = totalApplicationSplitNum;
//可退数量
const totalReturnableNum = row.selectedBatches.reduce(
(sum, batch) => sum + Number(batch.returnable_num || 0),
0
);
const totalReturnableSplitNum = row.selectedBatches.reduce(
(sum, batch) => sum + Number(batch.returnable_split_num || 0),
0
);
row.returnable_num = totalReturnableNum;
row.returnable_split_num = totalReturnableSplitNum;
//领用数量
const totalCommodityNum = row.selectedBatches.reduce(
(sum, batch) => sum + Number(batch.commodity_num || 0),
0
);
const totalCommoditySplitNum = row.selectedBatches.reduce(
(sum, batch) => sum + Number(batch.commodity_split_num || 0),
0
);
row.commodity_num = totalCommodityNum;
row.commodity_split_num = totalCommoditySplitNum;
// 计算总数量
let memory_num_total = Number(
FN(
row.application_num * 1 +
(row.application_split_num * 1) / row.min_package_num
)
).toFixed(2);
row.total_num = FN(memory_num_total * 1);
} else {
row.application_num = '';
row.application_split_num = '';
// 如果没有子行,用主行输入的值
handle_stock_num(row, 'application_num');
}
};
/**
* 获取流水号 商品领用单单号 --LYD
*/
const getOrderNo = async () => {
const res = await getValueBySet({ inner_code: 'LYD' });
formData.value.order_no = res.data;
};
/*保存草稿
* @param {[]} id [领用单ID] 是否必填:否
* @param {[]} order_no [订单编号] 是否必填:否 getiner
* @param {[]} receive_type [领用类型 1:领用 2:退回] 是否必填:否
* @param {[]} receive_status [状态 0:草稿 1:待审核 2:已完成 3:审核驳回 4: 已撤回] 是否必填:否
* @param {[]} receive_time [领用时间] 是否必填:否
* @param {[]} receive_id [领用人ID] 是否必填:否
* @param {[]} receive_name [领用人名称] 是否必填:否
* @param {[]} receive_dept_id [接收部门ID] 是否必填:否
* @param {[]} in_repertory_id [入库药房ID] 是否必填:否
* @param {[]} out_repertory_id [出库药房ID] 是否必填:否
* @param {[]} kind_num [商品种类数量] 是否必填:否
* @param {[]} total_num [总数量] 是否必填:否
* @param {[]} amount [金额] 是否必填:否
* @param {[]} amount_excluding_tax [税前金额] 是否必填:否
* @param {[]} remark [备注] 是否必填:否
* @param {[]} receiveCommodityList [领用商品集合[{id:领用商品ID commodity_id:商品ID application_num:申请商品整数量 application_split_num:申请商品拆零数量}]] 是否必填:是
* @return {[type]} [description]
*/
const saveDraft = () => {
console.log('保存草稿', formData.value, tableData.value);
// 调用校验方法
// if (!validateForm()) {
// return;
// }
let params = {
id: props.id || '',
order_no: formData.value.order_no || '',
receive_id: formData.value.receive_id || '',
receive_name: formData.value.receive_name || '',
receive_dept_id: formData.value.receive_dept_id || '',
in_repertory_id: formData.value.in_repertory_id || '',
out_repertory_id: formData.value.out_repertory_id || '',
remark: formData.value.remark || '',
kind_num: tableData.value?.length || 0,
total_num: totalQuantity.value || 0,
pur_amount: totalPurAmount.value,
sale_amount: totalSaleAmount.value,
receive_type: '1', // 领用类型
// receive_status: '0', // 草稿状态
} as any;
const receiveCommodityList = tableData.value.map((item) => ({
id: item.id || '',
commodity_id: item.commodity_id,
application_num: item.application_num,
application_split_num: item.application_split_num,
// 新增:批次信息
commodityRelateList: item.selectedBatches || [],
}));
params['receiveCommodityList'] = receiveCommodityList;
console.log('params', params);
postSaveReceiveDraft(params).then((res) => {
if (res.code == 1) {
HsMessage.success('草稿保存成功');
props.close!({ type: 'confirm' });
}
});
};
// try {
// loading.value = true;
// props.close!(_.cloneDeep(row));
// } finally {
// loading.value = false;
// }
//提交领用单 postSaveReceiveRecord
const submitForm = () => {
console.log('提交表单', formData.value, tableData.value);
// 调用校验方法
if (!validateForm()) {
return;
}
HsMessageBox.confirm(
`提交后将发送${formData.value.in_repertory_name}确认,确定提交吗?`,
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
closeOnClickModal: false,
}
)
.then(async () => {
loading.value = true;
let params = {
id: props.id || '',
order_no: formData.value.order_no || '',
receive_id: formData.value.receive_id || '',
receive_name: formData.value.receive_name || '',
receive_dept_id: formData.value.receive_dept_id || '',
in_repertory_id: formData.value.in_repertory_id || '',
out_repertory_id: formData.value.out_repertory_id || '',
remark: formData.value.remark || '',
kind_num: tableData.value?.length,
total_num: totalQuantity.value,
pur_amount: totalPurAmount.value,
sale_amount: totalSaleAmount.value,
receive_type: '1', // 领用类型
// receive_status: '1', // 待审核状态
} as any;
const receiveCommodityList = tableData.value.map((item) => ({
id: item.id || '',
commodity_id: item.commodity_id,
application_num: item.application_num,
application_split_num: item.application_split_num,
receiveCommodityRelateList: (item.selectedBatches ?? []).map(
(rowItem) => ({
out_goodseat_commodity_id: rowItem.id,
commodity_total_num: FN(
Utils.add(
rowItem.application_num,
Utils.div(
rowItem.application_split_num,
rowItem.min_package_num
)
)
),
commodity_num: rowItem.application_num,
commodity_split_num: rowItem.application_split_num,
})
),
}));
params['receiveCommodityList'] = receiveCommodityList;
console.log('params', params);
postSaveReceiveRecord(params)
.then((res) => {
loading.value = false;
if (res.code == 1) {
HsMessage.success('提交成功');
props.close!({ type: 'confirm' });
}
})
.catch(() => {
// 取消
loading.value = false;
});
})
.catch(() => {
// 取消
});
};
//确认审核 领用单 postSaveReceiveRecord
/**
* 接口分类: 仓储出入库操作接口 - OutAndInStockController
* 接口名称: 领用单审核 - 接口地址: /his-web/pri/out_in_stock/audit_receive_record
* 请求方式: post
* @param {[]} id [领用单ID] 是否必填:是
* @param {[]} receive_status [是否同意,同意:2,不同意:3] 是否必填:是
* @param {[]} audit_comment [意见] 是否必填:否
* @param {[]} kind_num [商品种类数量] 是否必填:否
* @param {[]} total_num [总数量] 是否必填:否
* @param {[]} pur_amount [采购总金额] 是否必填:否
* @param {[]} sale_amount [销售总金额] 是否必填:否
* @param {[]} receiveCommodityList [领用商品集合[{id:领用商品IDcommodity_id:商品IDcommodity_num:商品整数量(实发)commodity_split_num:商品拆零数量(实发)receiveCommodityRelateList:领用商品与库存关系[{id:领用商品与库存关系id out_goodseat_commodity_id:出库库存idcommodity_total_num:商品总数量(实发)commodity_num:商品整数量(实发)commodity_split_num:商品拆零数量(实发)}]}]] 是否必填:是
* @return {[type]} [description]
*/
const confirmCheckForm = () => {
console.log('审核表单', formData.value, tableData.value);
// 调用校验方法
if (!validateForm()) {
return;
}
showTextPopupClick();
// HsMessageBox.confirm(
// `确认后将锁定库存并发送${formData.value.in_repertory_name}核对,确定提交吗?`,
// '提示',
// {
// confirmButtonText: '确定',
// cancelButtonText: '取消',
// type: 'warning',
// closeOnClickModal: false,
// }
// )
// .then(async () => {
// })
// .catch(() => {
// // 取消
// });
};
function showTextPopupClick() {
showTextPopup().then((res: any) => {
console.log('res', res);
if (res.type === 'confirm') {
handleConfirm(res.data, '2');
} else if (res.type === 'refuse') {
handleConfirm(res.data, '3');
}
});
}
function handleConfirm(data: any, receive_status: string) {
// if (data.titleText === '商品名称') {
// goodsName.value.textarea
// updateQueryData('qry_like_in_str', data);
// }
// tableInstance.value?.searchTo();
let audit_comment = data;
loading.value = true;
let params = {
id: props.id || '',
order_no: formData.value.order_no || '',
receive_id: formData.value.receive_id || '',
receive_name: formData.value.receive_name || '',
receive_dept_id: formData.value.receive_dept_id || '',
in_repertory_id: formData.value.in_repertory_id || '',
out_repertory_id: formData.value.out_repertory_id || '',
remark: formData.value.remark || '',
kind_num: tableData.value?.length,
total_num: totalQuantity.value,
pur_amount: totalPurAmount.value,
sale_amount: totalSaleAmount.value,
receive_type: '1', // 领用类型
receive_status: receive_status || '', // 审核状态-通过
audit_comment: audit_comment || '',
} as any;
const receiveCommodityList = tableData.value.map((item) => ({
id: item.id || '',
commodity_id: item.commodity_id,
commodity_num: item.application_num,
commodity_split_num: item.application_split_num,
receiveCommodityRelateList: (item.selectedBatches ?? []).map((rowItem) => ({
// id: rowItem.id,
out_goodseat_commodity_id: rowItem.id,
commodity_total_num: FN(
Utils.add(
rowItem.application_num,
Utils.div(rowItem.application_split_num, rowItem.min_package_num)
)
),
commodity_num: rowItem.application_num,
commodity_split_num: rowItem.application_split_num,
})),
}));
params['receiveCommodityList'] = receiveCommodityList;
console.log('params', params);
postAuditReceiveRecord(params)
.then((res) => {
loading.value = false;
if (res.code == 1) {
if (receive_status === '2') {
HsMessage.success('审核确认成功');
} else {
HsMessage.success('审核驳回成功');
}
props.close!({ type: 'confirm' });
}
})
.catch(() => {
// 取消
loading.value = false;
});
}
// 添加药品到主表格
const addDrugToTable = (drug: any) => {
// tableData.value.push(drug);
// 使用 id 作为唯一标识
const drugMap = new Map(tableData.value.map((item) => [item.id, item]));
if (!drugMap.has(drug.id)) {
tableData.value.push(drug);
} else {
HsMessage.warning('该药品已存在');
}
// 校验表格中的领用数量
const invalidIndex = tableData.value?.length - 1;
// 聚焦 + 滚动
focusTableRowInput(invalidIndex);
};
/*
*搜索之后选中商品
* @param {[]} commodity_id [商品ID] 是否必填:是
* @param {[]} repertory_id [仓库id] 是否必填:是
*/
const handleAddDrug = async (drug: any) => {
if (!drug.id) {
return;
}
if (!formData.value.in_repertory_id) {
HsMessage.warning('请选择入库库房!');
return;
}
if (!formData.value.out_repertory_id) {
HsMessage.warning('请选择出库库房!');
return;
}
let params = {
commodity_id: drug.id,
repertory_id: formData.value.out_repertory_id,
};
// let resultData: any = await getCommodityRepertoryStock(params);
// console.log('resultData data', resultData.data);
// drug.show_memory_num = '0' + drug.unit;
// if (resultData.data) {
// drug.show_memory_num = resultData.data.show_memory_num || '0';
// }
let res1: any = await getGoodseatCommodityRepertory(params);
console.log('resultData data', res1.data);
let resultData = res1.data;
resultData.forEach((item: any) => {
item.selected = false;
item.application_num = item.memory_num;
item.application_split_num = item.split_memory_num;
});
// 设置药品字段
drug.commodityRelateList = resultData || [];
drug.selectedBatches = [];
addDrugToTable(drug);
};
// 新增行
function addRow() {
tableData.value.push({});
}
const popoverRefs = ref<Record<number, any>>({});
const popoverRefs2 = ref<Record<number, any>>({});
const popoverRefs3 = ref<Record<number, any>>({});
//批次选择
const tableRefs = ref<Record<number, any>>({});
const setPopoverRef = (el, index) => {
popoverRefs.value[index] = el;
};
const setPopoverRef2 = (el, index) => {
popoverRefs2.value[index] = el;
};
const setPopoverRef3 = (el, index) => {
popoverRefs3.value[index] = el;
};
const closePopover = (index) => {
if (popoverRefs.value[index]) {
popoverRefs.value[index].hide();
}
};
const closePopover2 = (index) => {
if (popoverRefs2.value[index]) {
popoverRefs2.value[index].hide();
}
};
const closePopover3 = (index) => {
if (popoverRefs3.value[index]) {
popoverRefs3.value[index].hide();
}
};
watch(
() => tableData.value,
() => {
console.log('表格数据更新,totalQuantity:', totalQuantity.value);
},
{ deep: true }
);
const closeForm = () => {
console.log('关闭表单');
props.close!({ type: 'close' });
};
function init() {
getRepertoryList();
getDeptDataList();
console.log('props', props);
if (!props.id) {
getOrderNo();
} else {
getDetailReceiveInfo();
}
if (props.data) {
formData.value.in_repertory_id = props.data?.in_repertory_id;
formData.value.out_repertory_id = props.data?.out_repertory_id;
formData.value.in_repertory_name = props.data?.in_repertory_name;
formData.value.out_repertory_name = props.data?.out_repertory_name;
}
getUserInfoFn();
}
let userInfo = {};
// 获取个人信息
async function getUserInfoFn() {
userInfo = await Utils.systemStore.get('userInfo');
if (userInfo) {
formData.value.store = userInfo.company_name;
}
}
// 获取领用单详情
async function getDetailReceiveInfo() {
if (!props.id) return;
let res: any = await getDetailReceive({ id: props.id });
let resultData: any = res.data;
if (resultData) {
formData.value = resultData;
resultData.commodityList.map((item: any) => {
if (item.commodityRelateList) {
// 赋值application_num和选中的批次和out_goodseat_commodity_id
item.commodityRelateList.map((listItem: any) => {
listItem.application_split_num = listItem.commodity_split_num;
listItem.application_num = listItem.commodity_num;
if (Number(resultData.receive_status) <= 1) {
listItem.id = listItem.out_goodseat_commodity_id;
}
});
item.selectedBatches = item.commodityRelateList;
}
});
tableData.value = resultData.commodityList;
formData.value.receive = [
resultData.receive_dept_id,
resultData.receive_id,
];
if (userInfo) {
formData.value.store = userInfo.company_name;
}
initSelection();
}
// repertory_list.value = res1.data;
}
// 撤回领用单
function revokeReceiveRecord() {
if (!props.id) return;
HsMessageBox.confirm('确定撤回领用单吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
closeOnClickModal: false,
})
.then(async () => {
loading.value = true;
postRevokeReceiveRecord({ id: props.id }).then((res) => {
loading.value = false;
if (res.code == 1) {
HsMessage.success('撤回领用单成功');
props.close!({ type: 'confirm' });
}
});
})
.catch(() => {
// 取消
loading.value = false;
});
}
// 退回领用单
function backReceiveRecord() {
if (!props.id) return;
HsMessageBox.confirm('确定退回领用单吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
closeOnClickModal: false,
})
.then(async () => {
loading.value = true;
let params = {
receive_source_record_id: props.id || '',
order_no: formData.value.order_no || '',
remark: formData.value.remark || '',
kind_num: tableData.value?.length,
total_num: totalQuantity.value,
pur_amount: totalPurAmount.value,
sale_amount: totalSaleAmount.value,
} as any;
const receiveCommodityList = tableData.value.map((item) => ({
id: item.id || '',
commodity_id: item.commodity_id,
application_num: item.application_num,
application_split_num: item.application_split_num,
receiveCommodityRelateList: (item.selectedBatches ?? []).map(
(rowItem) => ({
source_relate_id: rowItem.id,
commodity_total_num: FN(
Utils.add(
rowItem.application_num,
Utils.div(
rowItem.application_split_num,
rowItem.min_package_num
)
)
),
commodity_num: rowItem.application_num,
commodity_split_num: rowItem.application_split_num,
})
),
}));
params['receiveCommodityList'] = receiveCommodityList;
console.log('params', params);
postSaveReceiveRecordReturn(params)
.then((res) => {
loading.value = false;
if (res.code == 1) {
HsMessage.success('退回提交成功');
props.close!({ type: 'confirm' });
}
})
.catch(() => {
// 取消
loading.value = false;
});
})
.catch(() => {
// 取消
loading.value = false;
});
}
//删除领用单(草稿)
function deleteReceiveDraft() {
if (!props.id) return;
HsMessageBox.confirm('确定删除领用单(草稿)吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
closeOnClickModal: false,
})
.then(async () => {
loading.value = true;
postDeleteReceiveDraft({ id: props.id }).then((res) => {
loading.value = false;
if (res.code == 1) {
HsMessage.success('删除领用单(草稿)成功');
props.close!({ type: 'confirm' });
}
});
})
.catch(() => {
// 取消
loading.value = false;
});
}
//获取仓库列表
async function getRepertoryList() {
let res1 = await getListAllRepertory({ id_ne: '' });
repertory_list.value = res1.data;
}
//获取领用人列表
async function getDeptDataList() {
let res1 = await getDeptUserTree({ id_ne: '' });
deptData.value = res1.data;
console.log('deptData', deptData);
}
// computed 依赖 rawData.value
const cascaderOptions = computed(() => {
if (!Array.isArray(deptData.value)) return [];
return deptData.value.map((dept) => ({
value: dept.code,
label: dept.name,
children: dept.children.map((user) => ({
value: user.user_id,
label: user.user_name,
})),
}));
});
const cascaderProps = {
expandTrigger: 'hover', // 鼠标悬停展开下一级
};
const handleChange = (value) => {
console.log('选中值:', value);
// value 格式应为 [部门编码, 用户ID]
if (Array.isArray(value) && value.length >= 2) {
const deptCode = value[0]; // 接收部门ID
const userId = value[1]; // 领用人ID
// 查找用户信息
let userName = '';
// let deptName = '';
// 遍历 cascaderOptions 查找对应的部门和用户名称
for (const dept of cascaderOptions.value) {
if (dept.value === deptCode) {
// deptName = dept.label; // 接收部门名称
for (const user of dept.children) {
if (user.value === userId) {
userName = user.label; // 领用人名称
break;
}
}
break;
}
}
// 设置 formData 中的值
formData.value.receive_id = userId;
formData.value.receive_name = userName;
formData.value.receive_dept_id = deptCode;
console.log('formData after handleChange:', formData.value);
} else {
console.warn('无效的 cascader 选择值:', value);
}
};
onMounted(() => {
init();
});
const formatInput = (value) => {
if (isNaN(Number(value))) return 0;
return Math.max(0, Number(value));
};
function handle_stock_num(row: any, type: string) {
row[type] = formatInput(row[type]);
const splitnum = Number(row.min_package_num);
if (type === 'application_split_num') {
if (row.application_split_num >= splitnum) {
const split_num = row.application_split_num % splitnum;
const stock_num = Utils.div2(row.application_split_num, splitnum).toFixed(
0
);
row.application_split_num = split_num;
row.application_num = Number(FN(Number(row.application_num) + stock_num));
}
}
if (Number(row.application_split_num) <= 0) {
row.application_split_num = 0;
}
if (Number(row.application_num) <= 0) {
row.application_num = 0;
}
//重新计算整数数量
if (Number(row.application_num) >= Number(row.memory_num)) {
row.application_num = row.memory_num;
}
// 计算总数量
row.total_num = FN(
Utils.add(
row.application_num,
Utils.div(row.application_split_num, row.min_package_num)
)
);
}
const setTableRef = (el, index) => {
tableRefs.value[index] = el;
};
//批次选择
const confirmBatchSelection = (index) => {
const tableRef = tableRefs.value[index];
if (tableRef) {
const selection = tableRef?.getSelectionRows();
const row = tableData.value[index];
row.selectedBatches = selection;
updateTotalNumForRow(row);
}
closePopover3(index);
};
const isAllSelected = ref(false); // 控制全选状态
// 初始化每行的 selected 字段
function initSelection() {
tableData.value.forEach((row) => {
row.selected = false;
});
}
// 全选/取消全选
function toggleAllSelection() {
const isSelected = isAllSelected.value;
tableData.value.forEach((row) => {
row.selected = isSelected;
});
}
// 监听主行选中状态变化,更新全选按钮
watchEffect(() => {
const allSelected = tableData.value.every((row) => row.selected);
isAllSelected.value = allSelected;
});
// 获取所有选中的主行
function getSelectedRows() {
return tableData.value.filter((row) => row.selected);
}
function logSelected() {
const selectedRows = getSelectedRows();
console.log('选中的主行数据:', selectedRows);
}
</script>
<style scoped lang="scss">
@import './index.scss';
</style>
totalQuantity 刚开始怎么赋值