提交merge1.3

This commit is contained in:
2025-12-27 15:30:25 +08:00
parent 8c607c8749
commit 088861f66e
1245 changed files with 220442 additions and 77616 deletions

View File

@@ -0,0 +1,65 @@
import request from '@/utils/request';
// 药房请领单单初始化
export function getInit () {
return request ({
url: '/pharmacy-dispensary/dispensing-order/init',
method: 'get',
});
}
// 请领单单据列表:显示所有单据 左边框
export function getOrderList (query) {
return request ({
url: '/pharmacy-dispensary/dispensing-order/dispensing-order-page',
method: 'get',
params: query,
});
}
// 根据供应商获取药品:对应添加/编辑时加下一行数据后,点击项目时调用的接口
export function getMedicineList (query) {
return request ({
url: '/pharmacy-dispensary/dispensing-order/medication-info',
method: 'get',
params: query,
});
}
// 获取单据号:添加时,获取新单据号。编辑的逻辑是先删除后新增。
export function getBusNo () {
return request ({
url: '/pharmacy-dispensary/dispensing-order/busNo-init',
method: 'get',
});
}
// 添加/编辑采购单:添加/编辑采购单
export function addOrEditOrder (data) {
return request ({
url: '/pharmacy-dispensary/dispensing-order/addOrEdit-dispensingOrder',
method: 'PUT',
data,
});
}
// 删除单据
export function deleteOrder (data) {
return request ({
url: '/pharmacy-dispensary/dispensing-order/delete-dispensingOrder?busNo=' +
data,
method: 'DELETE',
});
}
// 同意审批
export function agreeApproval (data) {
return request ({
url: '/pharmacy-dispensary/dispensing-order/agree-approval?busNo=' + data,
method: 'PUT',
});
}
// 获取单据详情
export function getOrderDetail (query) {
return request ({
url: '/pharmacy-dispensary/dispensing-order/dispensing-order-detail-page',
method: 'GET',
params: query,
});
}

View File

@@ -0,0 +1,79 @@
<template>
<div>
<el-table ref="medicineRef" height="400" :data="medicineList" @cell-click="clickRow">
<el-table-column label="项目编码" align="center" prop="busNo" width="150" />
<el-table-column label="项目名称" align="center" prop="name" width="180" />
<el-table-column label="进货价" align="center" prop="price" />
<el-table-column label="零售价" align="center" prop="retailPrice" />
<el-table-column label="包装单位" align="center" prop="unitCode_dictText" />
<el-table-column label="最小单位" align="center" prop="minUnitCode_dictText" />
<el-table-column label="规格" align="center" prop="totalVolume" />
<el-table-column label="规格库存" align="center" prop="specificationInventory" />
<el-table-column label="生产厂家" align="center" prop="manufacturerText" />
<el-table-column label="批准文号" align="center" prop="approvalNumber" />
</el-table>
</div>
</template>
<script setup>
import { getMedicineList } from './api';
import { watch } from 'vue';
import { throttle } from 'lodash-es';
const props = defineProps({
searchKey: {
type: String,
default: '',
},
});
// 选择药品
const emit = defineEmits(['selectRow']);
//
const queryParams = ref({
pageNum: 1,
pageSize: 50,
searchKey: props.searchKey,
// 13 药品
typeEnum: 13,
});
// 药品列表
const medicineList = ref([]);
// 节流函数
const throttledGetList = throttle(
() => {
getList();
},
300,
{ leading: true, trailing: true }
);
// 获取药品列表
const getList = (query) => {
getMedicineList(query || queryParams.value).then((res) => {
medicineList.value = res.data.records;
});
};
// 点击行
const clickRow = (row) => {
// console.log(row, 'row');
emit('selectRow', row);
};
// 监听搜索关键字
watch(
() => props,
(newValue) => {
queryParams.value.searchKey = newValue.searchKey;
throttledGetList();
},
{ immdiate: true, deep: true }
);
// 获取药品列表
getList();
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,997 @@
<!-- 药库订货单 -->
<template>
<div class="medicine-container app-container">
<!-- 顶部按钮 -->
<el-row :gutter="20" :xs="24" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
icon="Plus"
plain
@click="handleAdd"
:disabled="isAddDisabled"
v-hasPermi="['pharmacy-warehouse:purchase-order:add']"
>
新增
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
icon="Delete"
plain
@click="handleDelete"
:disabled="isDeleteDisabled"
v-hasPermi="['pharmacy-warehouse:purchase-order:delete']"
>
删除
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
icon="Close"
plain
@click="handleCancel"
:disabled="isCancelDisabled"
v-hasPermi="['pharmacy-warehouse:purchase-order:cancel']"
>
取消
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
icon="Check"
plain
@click="handleAudit"
:disabled="isAuditDisabled"
v-hasPermi="['pharmacy-warehouse:purchase-order:audit']"
>
审核
</el-button>
</el-col>
</el-row>
<el-row :gutter="20" :xs="24">
<!-- 左侧搜索 -->
<el-col :span="4" style="border: 1px solid #ebeef5; height: calc(100vh - 200px)">
<el-row :gutter="10" style="margin-top: 10px">
<el-col :span="24">
<el-form ref="tableFormRef" :model="tableForm" style="width: 100%" :rules="rules">
<el-form-item label="库房:" label-width="100px">
<el-select
v-model="tableForm.locationId"
placeholder="请选择库房"
clearable
filterable
@change="handleLocationChange(tableForm.locationId)"
>
<el-option
v-for="item in cabinetListOptions"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-form>
</el-col>
</el-row>
<el-row :gutter="10">
<el-form
ref="queryParamsRef"
:model="queryParams"
style="width: 100%"
:rules="rules"
@submit.prevent
>
<el-form-item label="单据搜索" label-width="100px">
<el-input
v-model="queryParams.searchKey"
placeholder="请输入单据号"
@keyup.enter="getList"
clearable
>
<template #append>
<el-button icon="Search" @click="getList" />
</template>
</el-input>
</el-form-item>
</el-form>
</el-row>
<el-row :gutter="10" :xs="24">
<el-scrollbar height="calc(100vh - 350px)" style="width: 100%">
<div class="order-list-container">
<!-- 有数据时显示列表 -->
<template v-if="orderList.length > 0">
<div
v-for="item in orderList"
:key="item.supplyBusNo"
:class="['order-item', { 'is-active': selectedOrder === item }]"
@click="handleOrderClick(item)"
>
<el-card class="order-card" shadow="hover">
<div class="order-header">
<div class="order-number">
<el-icon><Document /></el-icon>
<span class="number-text">{{ item.supplyBusNo }}</span>
</div>
</div>
<div class="order-content">
<div class="info-item">
<el-icon class="info-icon"><User /></el-icon>
<span class="label">采购员</span>
<span class="value">{{ item.applicantId_dictText }}</span>
</div>
<div class="info-item">
<el-icon class="info-icon"><Shop /></el-icon>
<span class="label">供应商</span>
<span class="value">{{ item.supplierId_dictText }}</span>
</div>
<div class="info-item">
<el-icon class="info-icon"><User /></el-icon>
<span class="label">审核状态</span>
<el-tag type="success" v-if="item.statusEnum_enumText === '同意'">
{{ item.statusEnum_enumText }}
</el-tag>
<el-tag type="danger" v-else>
{{ item.statusEnum_enumText }}
</el-tag>
</div>
<div class="info-item">
<el-icon class="info-icon"><Files /></el-icon>
<span class="label">单据类型</span>
<span class="value">{{ item.typeEnum_enumText }}</span>
</div>
<div class="info-item">
<el-icon class="info-icon"><Calendar /></el-icon>
<span class="label">单据日期</span>
<span class="value">{{
parseTime(item.applyTime, '{y}-{m}-{d} {h}:{i}:{s}')
}}</span>
</div>
</div>
</el-card>
</div>
</template>
<!-- 空状态显示 -->
<div v-else class="empty-state">
<el-empty description="暂无单据" :image-size="80">
<el-button type="primary" @click="handleAdd"> 新增单据 </el-button>
</el-empty>
</div>
</div>
</el-scrollbar>
</el-row>
</el-col>
<!-- 右侧表格 -->
<el-col :span="20">
<el-row :gutter="10">
<el-col :span="24">
<orderTable
ref="orderTableRef"
:form="tableForm"
:table-data="tableData"
:audit-form="auditForm"
:table-data-total="tableDataTotal"
:is-add-or-edit-order="isAddOrEditOrder"
:supplier-option="supplierOption"
:supply-type-options="supplyTypeOptions"
:supply-status-options="supplyStatusOptions"
:supply-category-options="supplyCategoryOptions"
:practitioner-option="practitionerOption"
:button-show="buttonShow"
@update:query-params="handleQueryParamsUpdate"
@update:form="handleFormUpdate"
@clearForm="clearForm"
@getList="getList"
@updateButtonState="handleUpdateButtonState"
>
</orderTable>
</el-col>
</el-row>
</el-col>
</el-row>
</div>
</template>
<script setup>
import { ref, onMounted, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import orderTable from './components/orderTable.vue';
import {
getInit,
getOrderList,
deleteOrder,
agreeApproval,
getOrderDetail,
} from './components/api';
import useUserStore from '@/store/modules/user';
import { parseTime } from '@/utils/his';
const route = useRoute();
const router = useRouter();
// 获取 pinia 中用户信息
const userInfo = useUserStore();
// 左侧查询参数
const queryParams = ref({
searchKey: '',
});
// 获取当前实例
const { proxy } = getCurrentInstance();
// 右侧表格查询参数 + 分页参数 + 添加查询参数
const tableForm = ref({
locationId: undefined,
busNo: undefined,
applyTime: undefined,
applicantId: undefined,
reason: undefined,
categoryEnum: undefined,
supplierId: undefined,
pageNo: 1,
pageSize: 10,
});
// 右侧表格数据
const tableData = ref([]);
// 右侧审核表单
const auditForm = ref({
approvalTime: undefined,
statusEnum: undefined,
statusEnum_enumText: undefined,
approverId: undefined,
});
// 订单编辑还是新增
const isAddOrEditOrder = ref({
isAddOrder: false,
isEditOrder: false,
});
// 仓库列表 cabinetList
const cabinetListOptions = ref([]);
// 查询经手人列表 practitionerOption
const practitionerOption = ref([]);
// 查询供应商列表 supplierOption
const supplierOption = ref([]);
// 审批状态 supplyStatusOptions
const supplyStatusOptions = ref([]);
// 单据类型 supplyTypeOptions
const supplyTypeOptions = ref([]);
// 单据分类 supplyCategoryOptions
const supplyCategoryOptions = ref([]);
// 订货单单据列表 orderList
const orderList = ref([]);
// 订货单单据列表总条数
const tableDataTotal = ref(0);
// 选中的单据ID
const selectedOrder = ref(null);
// 是否禁用新增按钮
const isAddDisabled = ref(false);
// 是否禁用编辑按钮
const isEditDisabled = ref(true);
// 是否禁用取消按钮
const isCancelDisabled = ref(true);
// 是否禁用删除按钮
const isDeleteDisabled = ref(true);
// 是否禁用审核按钮
const isAuditDisabled = ref(true);
// 按钮显示 buttonShow
const buttonShow = ref({
isAddShow: false,
isDeleteShow: false,
isSaveShow: false,
isEditShow: false,
});
const rules = ref({
locationId: [{ required: true, message: '请选择库房', trigger: 'blur' }],
});
// 初始化 获取下拉列表
const init = async () => {
const res = await getInit();
// 仓库列表 cabinetListOptions
cabinetListOptions.value = res.data.cabinetListOptions;
// 查询经手人列表 practitionerList
practitionerOption.value = res.data.practitionerOption;
// 查询供应商列表 supplierOption
supplierOption.value = res.data.supplierOption;
// 审批状态 supplyStatusOptions
supplyStatusOptions.value = res.data.supplyStatusOptions;
// 单据类型 supplyTypeOptions
supplyTypeOptions.value = res.data.supplyTypeOptions;
// 单据分类
supplyCategoryOptions.value = res.data.supplyCategoryOptions;
};
// 获取订货单单据列表
const getList = async () => {
const res = await getOrderList(queryParams.value);
// 订货单单据列表 orderList
orderList.value = res.data.records;
};
// 新增按钮
const handleAdd = async () => {
// 清空当前表格数据 和 选中状态
resetFormAndTableData();
// 校验库房ID
if (!tableForm.value.locationId) {
proxy.$modal.msgWarning('新增单据前,请选择库房');
return;
}
// 右侧表单数据
tableForm.value = {
// 采购员
applicantId: userInfo.practitionerId,
// 单据日期
applyTime: parseTime(new Date(), '{y}-{m}-{d} {h}:{i}:{s}'),
// 库房ID
locationId: tableForm.value.locationId,
};
// 订单编辑还是新增
isAddOrEditOrder.value = {
isAddOrder: true,
isEditOrder: false,
};
// 延迟执行
nextTick(() => {
// 更新按钮状态为编辑模式
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: false,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: true,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: true,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: true,
});
});
};
// 清空当前表格数据
const resetFormAndTableData = () => {
// 清空右侧表格数据
tableData.value = [];
// 清空审核表单数据
auditForm.value = {};
// 清空右侧表格数据总条数
tableDataTotal.value = 0;
};
// 编辑按钮
const handleEdit = async (order) => {
// 清空当前表格数据 和 选中状态
resetFormAndTableData();
if (!selectedOrder.value) {
proxy.$modal.msgError('请选择要编辑的单据');
return;
}
const res = await getOrderDetail({
busNo: selectedOrder.value.supplyBusNo,
pageNo: tableForm.value.pageNo,
pageSize: tableForm.value.pageSize,
});
// 构建编辑后的表单数据
buildEditForm(res.data.records);
// 更新表格数据总条数
tableDataTotal.value = res.data.total;
// 根据订单状态更新按钮状态
const isApproved = order.statusEnum_enumText === '同意' || order.statusEnum === 3;
if (isApproved) {
// 设置编辑状态
isAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: false,
};
// 更新按钮状态为初始状态
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: true,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: false,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: false,
});
return;
}
// 设置编辑状态
isAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: true,
};
// 更新按钮状态
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: isApproved,
// 取消 按钮禁用
isCancelDisabled: false,
// 删除 按钮禁用
isDeleteDisabled: isApproved,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: !isApproved,
// 删除行 按钮显示
isDeleteShow: !isApproved,
// 保存行 按钮显示
isSaveShow: !isApproved,
// 编辑行 按钮显示
isEditShow: !isApproved,
// 警戒订货 按钮显示
isAlertShow: !isApproved,
});
};
// 构建单位列表
const buildUnitList = (item) => {
// 表格单位列表
(item.unitList || []).forEach((unit) => {
// 判断当前单位是最大单位还是最小单位
const isMaxUnit = unit.value === item.maxUnitCode;
const isMinUnit = unit.value === item.minUnitCode;
// 进货价(假)
if (isMaxUnit) {
unit.priceMask = item.price;
} else {
unit.priceMask = item.price / parseInt(item.partPercent);
}
// 销售价(假)
if (isMaxUnit) {
unit.retailPriceMask = item.retailPrice;
} else {
unit.retailPriceMask = item.retailPrice / parseInt(item.partPercent);
}
// 进价金额(假)
unit.totalPriceMask = (parseFloat(item.price) * parseFloat(item.itemQuantity)).toFixed(2);
// 销售金额(假)
unit.totalRetailPriceMask = (
parseFloat(item.retailPrice) * parseFloat(item.itemQuantity)
).toFixed(2);
// 规格库存
unit.specificationInventoryOriginal = item.specificationInventory;
// 规格库存显示逻辑
if (isMaxUnit) {
// 最大单位:显示为 "X盒"
unit.specificationInventoryMax = Math.floor(
item.specificationInventory / parseInt(item.partPercent)
);
unit.specificationInventoryMaxUnit =
unit.specificationInventoryMax > 0 ? item.maxUnitCode_dictText : '';
unit.specificationInventoryMin = item.specificationInventory % parseInt(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 buildEditForm = (data) => {
// 构建表格数据
if (data.length > 0) {
// 表单数据
tableForm.value = {
// 单据号
busNo: data[0].busNo,
// 单据日期
applyTime: data[0].applyTime,
// 供应商
supplierId: data[0].supplierId,
// 采购员
applicantId: data[0].applicantId,
// 单据类型
categoryEnum: data[0].categoryEnum,
// 摘要
reason: data[0].reason,
// 仓库
locationId: data[0].purposeLocationId,
};
// 表格数据
data.forEach((item) => {
// 表格编辑状态
item.isEditing = false;
// 表格查看状态
item.isViewing = true;
// 构建单位列表
buildUnitList(item);
});
// 更新表格数据
tableData.value = data;
// 审核表格数据
auditForm.value = {
// 审核时间
approvalTime: data[0].approvalTime,
// 审核状态
statusEnum: data[0].statusEnum,
// 审核状态文本
statusEnum_enumText: data[0].statusEnum_enumText,
// 审核人
approverId: data[0].approverId,
};
// 订单编辑还是新增
isAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: true,
};
}
};
// 取消按钮
const handleCancel = () => {
// 更新按钮状态为初始状态
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: true,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: false,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: false,
});
// 清空表单
clearForm();
};
// 清空表单
const clearForm = () => {
// 清空表单数据
tableForm.value = {};
tableData.value = [];
// 清空右侧表格数据
proxy.$refs.orderTableRef.resetAllData();
// 重置订单状态
isAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: false,
};
};
// 删除按钮
const handleDelete = async () => {
if (!selectedOrder.value) {
proxy.$modal.msgError('请选择要删除的单据');
return;
}
// 校验是否可以删除(已审批的单据不能删除)
if (selectedOrder.value.statusEnum_enumText === '同意' || selectedOrder.value.statusEnum === 3) {
proxy.$modal.msgError('已审批的单据不能删除');
return;
}
try {
await proxy.$modal.confirm('确认删除该采购单吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
});
// 删除单据
await deleteOrder(selectedOrder.value.supplyBusNo);
proxy.$modal.msgSuccess('删除成功');
// 编辑
handleEdit(selectedOrder.value);
// 清空右侧表格数据
clearForm();
// 重新获取列表 库房ID
await getList(tableForm.value.locationId);
// 清空选中状态
selectedOrder.value = null;
// 更新按钮状态为初始状态
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: true,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: false,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: false,
});
} catch (error) {
if (error !== 'cancel') {
proxy.$modal.msgError('删除失败');
console.error('删除失败:', error);
}
}
};
// 审核按钮
const handleAudit = async () => {
if (!selectedOrder.value) {
proxy.$modal.msgError('请选择要审核的单据');
return;
}
// 校验是否是已审批状态
if (selectedOrder.value.statusEnum_enumText === '同意' || selectedOrder.value.statusEnum === 3) {
proxy.$modal.msgError('该单据已审批,不能重复审批');
return;
}
try {
await proxy.$modal.confirm('确认同意该采购单吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
});
// 同意审批
await agreeApproval(selectedOrder.value.supplyBusNo);
proxy.$modal.msgSuccess('同意审批成功');
// 编辑
handleEdit(selectedOrder.value);
// 清空右侧表格数据
clearForm();
// 重新获取列表 库房ID
await getList(tableForm.value.locationId);
// 清空选中状态
selectedOrder.value = null;
// 更新按钮状态为初始状态
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: true,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: false,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: false,
});
isAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: false,
};
} catch (error) {
if (error !== 'cancel') {
proxy.$modal.msgError('同意审批失败');
console.error('同意审批失败:', error);
}
}
};
// 处理订单点击事件
const handleOrderClick = (order) => {
// 选中订单
selectedOrder.value = order;
// 编辑
handleEdit(order);
};
// 处理查询参数更新
const handleQueryParamsUpdate = (newParams) => {
// 更新右侧表格的分页参数
tableForm.value.pageNo = newParams.pageNo;
tableForm.value.pageSize = newParams.pageSize;
// 如果有选中的订单,重新获取订单详情
if (selectedOrder.value) {
handleEdit(selectedOrder.value);
}
};
//
// 处理库房变化
const handleLocationChange = (locationId) => {
queryParams.value.locationId = locationId;
// 重新获取列表
getList();
};
//
// 处理表单更新
const handleFormUpdate = (newForm) => {
tableForm.value = { ...tableForm.value, ...newForm };
};
// 处理按钮状态更新
const handleUpdateButtonState = (buttonState) => {
// 按钮禁用
// 审核 按钮禁用
isAuditDisabled.value = buttonState.isAuditDisabled;
// 取消 按钮禁用
isCancelDisabled.value = buttonState.isCancelDisabled;
// 删除 按钮禁用
isDeleteDisabled.value = buttonState.isDeleteDisabled;
// 添加 按钮禁用
isAddDisabled.value = buttonState.isAddDisabled;
// 编辑 按钮禁用
isEditDisabled.value = buttonState.isEditDisabled;
// 按钮显示
// 添加行 按钮显示
buttonShow.value.isAddShow = buttonState.isAddShow;
// 删除行 按钮显示
buttonShow.value.isDeleteShow = buttonState.isDeleteShow;
// 保存行 按钮显示
buttonShow.value.isSaveShow = buttonState.isSaveShow;
// 编辑行 按钮显示
buttonShow.value.isEditShow = buttonState.isEditShow;
// 警戒订货 按钮显示
buttonShow.value.isAlertShow = buttonState.isAlertShow;
};
// 监听路由变化
watch(
() => route.query,
async (newQuery) => {
//console.log('路由参数发生变化:', newQuery);
if (newQuery.busNo) {
queryParams.value.searchKey = newQuery.busNo;
await getList();
// 设置选中状态
selectedOrder.value = orderList.value.find((item) => item.supplyBusNo === newQuery.busNo);
// 编辑按钮
handleEdit(selectedOrder.value);
// 清空路由参数
// router.replace({ query: {} });
}
},
{ immediate: true }
);
// 下拉列表初始化
init();
</script>
<style scoped lang="scss">
.medicine-container :deep(.el-row) {
margin-bottom: 10px;
}
.medicine-container :deep(.el-row:last-child) {
margin-bottom: 0;
}
// 订单列表容器
.order-list-container {
width: 100%;
padding: 0;
}
// 订单列表项样式
.order-item {
width: 100%;
cursor: pointer;
transition: all 0.3s ease;
border-radius: 6px;
overflow: hidden;
margin: 4px 0;
&:hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
.order-card {
border-color: #409eff;
}
}
&.is-active {
.order-card {
border-color: #409eff;
background: linear-gradient(135deg, #ecf5ff 0%, #f0f9ff 100%);
}
.order-number .number-text {
color: #409eff;
font-weight: 600;
}
}
}
// 订单卡片样式
.order-card {
border: 1px solid #e4e7ed;
border-radius: 6px;
transition: all 0.3s ease;
background: #fff;
overflow: hidden;
:deep(.el-card__body) {
padding: 12px;
}
}
// 订单头部样式
.order-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
padding-bottom: 8px;
border-bottom: 1px solid #f0f0f0;
}
.order-number {
display: flex;
align-items: center;
gap: 6px;
min-width: 0;
flex: 1;
.el-icon {
color: #409eff;
font-size: 14px;
flex-shrink: 0;
}
.number-text {
font-size: 13px;
font-weight: 500;
color: #303133;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.order-status {
flex-shrink: 0;
.el-tag {
border-radius: 10px;
font-weight: 500;
font-size: 11px;
padding: 2px 6px;
}
}
// 订单内容样式
.order-content {
display: flex;
flex-direction: column;
gap: 4px;
}
.info-item {
display: flex;
align-items: center;
gap: 4px;
padding: 4px 0;
min-width: 0;
.info-icon {
color: #909399;
font-size: 12px;
flex-shrink: 0;
}
.label {
color: #606266;
font-size: 12px;
font-weight: 500;
flex-shrink: 0;
}
.value {
color: #303133;
font-size: 12px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
min-width: 0;
flex: 1;
}
}
// 空状态样式
.empty-state {
display: flex;
justify-content: center;
align-items: center;
height: 200px;
color: #909399;
:deep(.el-empty__description) {
color: #909399;
font-size: 14px;
}
:deep(.el-button) {
margin-top: 16px;
}
}
// 响应式设计
@media (max-width: 768px) {
.order-header {
flex-direction: column;
align-items: flex-start;
gap: 6px;
}
.info-item {
padding: 2px 0;
}
.empty-state {
height: 150px;
}
}
</style>

View File

@@ -0,0 +1,83 @@
import request from '@/utils/request';
// 药库订货单初始化
export function getInit () {
return request ({
url: '/pharmacy-dispensary/profitLoss-order/init',
method: 'get',
});
}
// 订货单单据列表:显示所有单据 左边框
export function getOrderList (query) {
return request ({
url: '/pharmacy-dispensary/profitLoss-order/profitLoss-order-page',
method: 'get',
params: query,
});
}
// 根据供应商获取药品:对应添加/编辑时加下一行数据后,点击项目时调用的接口
export function getMedicineList (query) {
return request ({
url: '/pharmacy-dispensary/profitLoss-order/medication-info',
method: 'get',
params: query,
});
}
// 获取单据号:添加时,获取新单据号。编辑的逻辑是先删除后新增。
export function getBusNo () {
return request ({
url: '/pharmacy-dispensary/profitLoss-order/busNo-init',
method: 'get',
});
}
// 添加/编辑采购单:添加/编辑采购单
export function addOrEditOrder (data) {
return request ({
url: '/pharmacy-dispensary/profitLoss-order/addOrEdit-profitLossOrder',
method: 'PUT',
data,
});
}
// 删除单据
export function deleteOrder (data) {
return request ({
url: '/pharmacy-dispensary/profitLoss-order/delete-profitLossOrder?busNo=' +
data,
method: 'DELETE',
});
}
// 同意审批
export function agreeApproval (data) {
return request ({
url: '/pharmacy-dispensary/profitLoss-order/agree-approval?busNo=' + data,
method: 'PUT',
});
}
// 获取单据详情
export function getOrderDetail (query) {
return request ({
url: '/pharmacy-dispensary/profitLoss-order/profitLoss-order-detail-page',
method: 'GET',
params: query,
});
}
// 订货单单据列表
export function getPurchaseOrderList (query) {
return request ({
url: '/pharmacy-warehouse/purchase-order/purchase-order-page',
method: 'get',
params: query,
});
}
// 获取单据详情
export function getPurchaseOrderDetail (query) {
return request ({
url: '/pharmacy-warehouse/purchase-order/purchase-order-detail-page',
method: 'GET',
params: query,
});
}

View File

@@ -0,0 +1,88 @@
<template>
<div>
<el-table ref="medicineRef" height="400" :data="medicineList" @cell-click="clickRow">
<el-table-column label="项目编码" align="center" prop="busNo" width="150" />
<el-table-column label="项目名称" align="center" prop="name" width="180" />
<el-table-column label="进货价" align="center" prop="price" />
<el-table-column label="零售价" align="center" prop="retailPrice" />
<el-table-column label="包装单位" align="center" prop="unitCode_dictText" />
<el-table-column label="最小单位" align="center" prop="minUnitCode_dictText" />
<el-table-column label="规格" align="center" prop="totalVolume" />
<el-table-column label="规格库存" align="center" prop="specificationInventory" />
<el-table-column label="批次库存" align="center" prop="batchInventory" />
<el-table-column label="供应商" align="center" prop="supplierId_dictText" />
<el-table-column label="生产厂家" align="center" prop="manufacturerText" />
<el-table-column label="批准文号" align="center" prop="approvalNumber" />
</el-table>
</div>
</template>
<script setup>
import { getMedicineList } from './api';
import { watch } from 'vue';
import { throttle } from 'lodash-es';
const props = defineProps({
searchKey: {
type: String,
default: '',
},
locationId: {
type: String,
default: '',
},
});
// 选择药品
const emit = defineEmits(['selectRow']);
//
const queryParams = ref({
pageNum: 1,
pageSize: 50,
searchKey: props.searchKey,
});
// 药品列表
const medicineList = ref([]);
// 节流函数
const throttledGetList = throttle(
() => {
getList();
},
300,
{ leading: true, trailing: true }
);
// 获取药品列表
const getList = (query) => {
queryParams.value = {
...queryParams.value,
...query,
locationId: props.locationId,
}
getMedicineList(query || queryParams.value).then((res) => {
medicineList.value = res.data.records;
});
};
// 点击行
const clickRow = (row) => {
// console.log(row, 'row');
emit('selectRow', row);
};
// 监听搜索关键字
watch(
() => props,
(newValue) => {
queryParams.value.searchKey = newValue.searchKey;
throttledGetList();
},
{ immdiate: true, deep: true }
);
// 获取药品列表
getList();
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,343 @@
<template>
<div>
<el-dialog
title="订单列表"
v-model="localDialogVisible"
width="960px"
append-to-body
@close="resetAllData"
>
<el-table
:data="orderList"
ref="tableRef"
width="100%"
highlight-current-row
height="470px"
@row-dblclick="handleRowDBClick"
@row-click="handleRowClick"
>
<el-table-column
label="订单编号"
prop="supplyBusNo"
width="200"
align="center"
></el-table-column>
<el-table-column label="采购员" prop="applicantId_dictText" width="100" align="center" />
<el-table-column label="供应商" prop="supplierId_dictText" width="220" align="center" />
<el-table-column label="审核状态" prop="statusEnum_enumText" width="100" align="center">
<template #default="scope">
<el-tag v-if="scope.row.statusEnum_enumText === '同意'" type="success">
{{ scope.row.statusEnum_enumText }}
</el-tag>
<el-tag v-else type="danger">{{ scope.row.statusEnum_enumText }}</el-tag>
</template>
</el-table-column>
<el-table-column label="单据类型" prop="typeEnum_enumText" width="100" align="center" />
<el-table-column label="单据日期" prop="applyTime" width="200" align="center">
<template #default="scope">
{{ parseTime(scope.row.applyTime, '{yy}-{mm}-{dd} {hh}:{ii}:{ss}') }}
</template>
</el-table-column>
</el-table>
<el-row justify="end" style="margin-top: 10px">
<el-pagination
:current-page="queryParams.pageNo"
:page-size="queryParams.pageSize"
:page-sizes="[10, 50, 100, 200]"
layout="total, sizes, prev, pager, next, jumper"
:total="localTableDataTotal"
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
v-show="localTableDataTotal > 0"
/>
</el-row>
<template #footer>
<div class="dialog-footer">
<el-button @click="handleCancel">取消</el-button>
<el-button type="primary" @click="handleSubmit"> 确认 </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { getPurchaseOrderList, getPurchaseOrderDetail } from './api';
import { ref, watch, getCurrentInstance } from 'vue';
import { parseTime } from '@/utils/his';
// 调用父组件方法
const emit = defineEmits(['dialogSubmit', 'dialogCancel', 'updateTableData']);
// 获取当前实例
const { proxy } = getCurrentInstance();
// 属性
const props = defineProps({
// 对话框x显示
dialogVisible: {
type: Boolean,
default: false,
},
});
// 本地对话框显示
const localDialogVisible = ref(false);
// 监听属性
watch(
() => props.dialogVisible,
(newValue) => {
localDialogVisible.value = newValue;
}
);
// 获取当前行
const currentRow = ref({});
// 行点击 双击
const handleRowClick = (row) => {
// 设置当前行
currentRow.value = row;
};
// 行点击 双击
const handleRowDBClick = (row) => {
// 设置当前行
currentRow.value = row;
// 提交
handleSubmit();
};
// 订单列表
const orderList = ref([]);
// 订单列表总条数
const localTableDataTotal = ref(0);
// 当前locationId
const currentLocationId = ref(undefined);
// 查询参数
const queryParams = ref({
pageNo: 1,
pageSize: 10,
locationId: undefined,
});
// 分页每页条数
const handleSizeChange = (size) => {
queryParams.value.pageSize = size;
queryParams.value.pageNo = 1; // 切换每页条数时重置到第一页
// 重新获取数据
if (currentLocationId.value) {
getOrderList(currentLocationId.value);
}
};
// 分页当前页
const handleCurrentChange = (page) => {
queryParams.value.pageNo = page;
// 重新获取数据
if (currentLocationId.value) {
getOrderList(currentLocationId.value);
}
};
// 获取订货单列表
const getOrderList = async (locationId) => {
try {
// 保存当前locationId
currentLocationId.value = locationId;
// 构建请求参数
const requestParams = {
// 仓库ID
locationId: locationId,
// 页码
pageNo: queryParams.value.pageNo,
// 每页条数
pageSize: queryParams.value.pageSize,
// 订单状态 3 :审核通过
statusEnum: 3,
};
const res = await getPurchaseOrderList(requestParams);
if (res.data.records && res.data.records.length > 0) {
// 订货单列表
orderList.value = res.data.records || [];
// 订货单列表总条数
localTableDataTotal.value = res.data.total;
} else {
proxy.$message.error('获取订货单列表失败');
}
} catch (error) {
console.error('获取订货单列表失败:', error);
}
};
// 重置所有数据
const resetAllData = () => {
// 重置分页参数
queryParams.value.pageNo = 1;
queryParams.value.pageSize = 10;
currentLocationId.value = undefined;
orderList.value = [];
localTableDataTotal.value = 0;
};
// 提交数据
const handleSubmit = async () => {
// 取消按钮
handleCancel();
// 获取当前进货单的订单列表
await getCurrentOrderDetail();
// 传递数据给父组件
emit('updateTableData', {
currentOrderList: setCurrentOrderList.value,
currentOrderForm: setCurrentOrderForm.value,
});
};
// 设置当前进货单的订单列表
const setCurrentOrderList = ref([]);
// 设置当前进货单的订单表单
const setCurrentOrderForm = ref({});
// 获取当前进货单的订单列表
const getCurrentOrderDetail = async () => {
const res = await getPurchaseOrderDetail({ busNo: currentRow.value.supplyBusNo });
// 构建编辑后的表单数据
buildEditForm(res.data.records);
};
// 构建编辑后的表单数据
const buildEditForm = (data) => {
// 构建表格数据
if (data.length > 0) {
// 表单数据
setCurrentOrderForm.value = {
// 供应商
supplierId: data[0].supplierId,
// 供应商联系人
phone: data[0].phone,
// 采购员
practitionerId: data[0].applicantId,
};
// 表格数据
data.forEach((item) => {
// 表格编辑状态
item.isEditing = true;
// 表格查看状态
item.isViewing = false;
// 判断当前单位是否是最大单位
buildPrice(item);
// 构建单位列表
buildUnitList(item);
});
// 更新表格数据
setCurrentOrderList.value = data;
}
};
// 构建进货价和销售价
const buildPrice = (item) => {
// 判断当前单位是最大单位还是最小单位
const isMaxUnit = item.unitCode === item.maxUnitCode;
if (isMaxUnit) {
// 进货价
item.price = item.price;
item.priceMaxUnit = item.price;
item.priceMinUnit = item.price / parseInt(item.partPercent);
// 销售价
item.retailPrice = item.retailPrice;
item.retailPriceMaxUnit = item.retailPrice;
item.retailPriceMinUnit = (parseFloat(item.retailPrice) / parseInt(item.partPercent)).toFixed(
2
);
} else {
// 进货价
item.price = item.price;
item.priceMaxUnit = parseFloat((item.price * parseInt(item.partPercent)).toFixed(2));
item.priceMinUnit = item.price;
// 销售价
item.retailPrice = item.retailPrice;
item.retailPriceMaxUnit = parseFloat(
(item.retailPrice * parseInt(item.partPercent)).toFixed(2)
);
item.retailPriceMinUnit = item.retailPrice;
}
};
// 构建单位列表
const buildUnitList = (item) => {
// 表格单位列表
(item.unitList || []).forEach((unit) => {
// 判断当前单位是最大单位还是最小单位
const isMaxUnit = unit.value === item.maxUnitCode;
const isMinUnit = unit.value === item.minUnitCode;
// // 进货价(假)
unit.priceMask = item.price;
// 销售价(假)
unit.retailPriceMask = item.retailPrice;
// 进价金额(假)
unit.totalPriceMask = (parseFloat(item.price) * parseFloat(item.itemQuantity)).toFixed(2);
// 销售金额(假)
unit.totalRetailPriceMask = (
parseFloat(item.retailPrice) * parseFloat(item.itemQuantity)
).toFixed(2);
// 规格库存
unit.specificationInventoryOriginal = item.specificationInventory;
// 规格库存显示逻辑
if (isMaxUnit) {
// 最大单位:显示为 "X盒"
unit.specificationInventoryMax = Math.floor(
item.specificationInventory / parseInt(item.partPercent)
);
unit.specificationInventoryMaxUnit =
unit.specificationInventoryMax > 0 ? item.maxUnitCode_dictText : '';
unit.specificationInventoryMin = item.specificationInventory % parseInt(item.partPercent);
unit.specificationInventoryMinUnit =
unit.specificationInventoryMin > 0 ? item.minUnitCode_dictText : '';
// 批次库存
unit.batchInventoryMax = Math.floor(item.batchInventory / parseInt(item.partPercent));
unit.batchInventoryMaxUnit = unit.batchInventoryMax > 0 ? item.maxUnitCode_dictText : '';
unit.batchInventoryMin = item.batchInventory % parseInt(item.partPercent);
unit.batchInventoryMinUnit = unit.batchInventoryMin > 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 : '';
// 批次库存
unit.batchInventoryMax = item.batchInventory;
unit.batchInventoryMaxUnit = unit.batchInventoryMax > 0 ? item.minUnitCode_dictText : '';
unit.batchInventoryMin = 0;
unit.batchInventoryMinUnit = unit.batchInventoryMin > 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 : '';
// 批次库存
unit.batchInventoryMax = item.batchInventory;
unit.batchInventoryMaxUnit = unit.batchInventoryMax > 0 ? item.minUnitCode_dictText : '';
unit.batchInventoryMin = 0;
unit.batchInventoryMinUnit = unit.batchInventoryMin > 0 ? item.minUnitCode_dictText : '';
}
});
};
// 取消按钮
const handleCancel = () => {
emit('dialogCancel', {
dialogVisible: false,
});
};
defineOptions({
name: 'orderDialog',
});
defineExpose({
getOrderList,
});
</script>
<style>
</style>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,65 @@
import request from '@/utils/request';
// 药房请领单单初始化
export function getInit () {
return request ({
url: '/pharmacy-dispensary/requisition-order/init',
method: 'get',
});
}
// 请领单单据列表:显示所有单据 左边框
export function getOrderList (query) {
return request ({
url: '/pharmacy-dispensary/requisition-order/requisition-order-page',
method: 'get',
params: query,
});
}
// 根据供应商获取药品:对应添加/编辑时加下一行数据后,点击项目时调用的接口
export function getMedicineList (query) {
return request ({
url: '/pharmacy-dispensary/requisition-order/medication-info',
method: 'get',
params: query,
});
}
// 获取单据号:添加时,获取新单据号。编辑的逻辑是先删除后新增。
export function getBusNo () {
return request ({
url: '/pharmacy-dispensary/requisition-order/busNo-init',
method: 'get',
});
}
// 添加/编辑采购单:添加/编辑采购单
export function addOrEditOrder (data) {
return request ({
url: '/pharmacy-dispensary/requisition-order/addOrEdit-requisitionOrder',
method: 'PUT',
data,
});
}
// 删除单据
export function deleteOrder (data) {
return request ({
url: '/pharmacy-dispensary/requisition-order/delete-requisitionOrder?busNo=' +
data,
method: 'DELETE',
});
}
// 同意审批
export function agreeApproval (data) {
return request ({
url: '/pharmacy-dispensary/requisition-order/agree-approval?busNo=' + data,
method: 'PUT',
});
}
// 获取单据详情
export function getOrderDetail (query) {
return request ({
url: '/pharmacy-dispensary/requisition-order/requisition-order-detail-page',
method: 'GET',
params: query,
});
}

View File

@@ -0,0 +1,79 @@
<template>
<div>
<el-table ref="medicineRef" height="400" :data="medicineList" @cell-click="clickRow">
<el-table-column label="项目编码" align="center" prop="busNo" width="150" />
<el-table-column label="项目名称" align="center" prop="name" width="180" />
<el-table-column label="进货价" align="center" prop="price" />
<el-table-column label="零售价" align="center" prop="retailPrice" />
<el-table-column label="包装单位" align="center" prop="unitCode_dictText" />
<el-table-column label="最小单位" align="center" prop="minUnitCode_dictText" />
<el-table-column label="规格" align="center" prop="totalVolume" />
<el-table-column label="规格库存" align="center" prop="specificationInventory" />
<el-table-column label="生产厂家" align="center" prop="manufacturerText" />
<el-table-column label="批准文号" align="center" prop="approvalNumber" />
</el-table>
</div>
</template>
<script setup>
import { getMedicineList } from './api';
import { watch } from 'vue';
import { throttle } from 'lodash-es';
const props = defineProps({
searchKey: {
type: String,
default: '',
},
});
// 选择药品
const emit = defineEmits(['selectRow']);
//
const queryParams = ref({
pageNum: 1,
pageSize: 50,
searchKey: props.searchKey,
// 13 药品
typeEnum: 13,
});
// 药品列表
const medicineList = ref([]);
// 节流函数
const throttledGetList = throttle(
() => {
getList();
},
300,
{ leading: true, trailing: true }
);
// 获取药品列表
const getList = (query) => {
getMedicineList(query || queryParams.value).then((res) => {
medicineList.value = res.data.records;
});
};
// 点击行
const clickRow = (row) => {
// console.log(row, 'row');
emit('selectRow', row);
};
// 监听搜索关键字
watch(
() => props,
(newValue) => {
queryParams.value.searchKey = newValue.searchKey;
throttledGetList();
},
{ immdiate: true, deep: true }
);
// 获取药品列表
getList();
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,997 @@
<!-- 药库订货单 -->
<template>
<div class="medicine-container app-container">
<!-- 顶部按钮 -->
<el-row :gutter="20" :xs="24" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
icon="Plus"
plain
@click="handleAdd"
:disabled="isAddDisabled"
v-hasPermi="['pharmacy-warehouse:purchase-order:add']"
>
新增
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
icon="Delete"
plain
@click="handleDelete"
:disabled="isDeleteDisabled"
v-hasPermi="['pharmacy-warehouse:purchase-order:delete']"
>
删除
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
icon="Close"
plain
@click="handleCancel"
:disabled="isCancelDisabled"
v-hasPermi="['pharmacy-warehouse:purchase-order:cancel']"
>
取消
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
icon="Check"
plain
@click="handleAudit"
:disabled="isAuditDisabled"
v-hasPermi="['pharmacy-warehouse:purchase-order:audit']"
>
审核
</el-button>
</el-col>
</el-row>
<el-row :gutter="20" :xs="24">
<!-- 左侧搜索 -->
<el-col :span="4" style="border: 1px solid #ebeef5; height: calc(100vh - 200px)">
<el-row :gutter="10" style="margin-top: 10px">
<el-col :span="24">
<el-form ref="tableFormRef" :model="tableForm" style="width: 100%" :rules="rules">
<el-form-item label="库房:" label-width="100px">
<el-select
v-model="tableForm.locationId"
placeholder="请选择库房"
clearable
filterable
@change="handleLocationChange(tableForm.locationId)"
>
<el-option
v-for="item in cabinetListOptions"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-form>
</el-col>
</el-row>
<el-row :gutter="10">
<el-form
ref="queryParamsRef"
:model="queryParams"
style="width: 100%"
:rules="rules"
@submit.prevent
>
<el-form-item label="单据搜索" label-width="100px">
<el-input
v-model="queryParams.searchKey"
placeholder="请输入单据号"
@keyup.enter="getList"
clearable
>
<template #append>
<el-button icon="Search" @click="getList" />
</template>
</el-input>
</el-form-item>
</el-form>
</el-row>
<el-row :gutter="10" :xs="24">
<el-scrollbar height="calc(100vh - 350px)" style="width: 100%">
<div class="order-list-container">
<!-- 有数据时显示列表 -->
<template v-if="orderList.length > 0">
<div
v-for="item in orderList"
:key="item.supplyBusNo"
:class="['order-item', { 'is-active': selectedOrder === item }]"
@click="handleOrderClick(item)"
>
<el-card class="order-card" shadow="hover">
<div class="order-header">
<div class="order-number">
<el-icon><Document /></el-icon>
<span class="number-text">{{ item.supplyBusNo }}</span>
</div>
</div>
<div class="order-content">
<div class="info-item">
<el-icon class="info-icon"><User /></el-icon>
<span class="label">采购员</span>
<span class="value">{{ item.applicantId_dictText }}</span>
</div>
<div class="info-item">
<el-icon class="info-icon"><Shop /></el-icon>
<span class="label">供应商</span>
<span class="value">{{ item.supplierId_dictText }}</span>
</div>
<div class="info-item">
<el-icon class="info-icon"><User /></el-icon>
<span class="label">审核状态</span>
<el-tag type="success" v-if="item.statusEnum_enumText === '同意'">
{{ item.statusEnum_enumText }}
</el-tag>
<el-tag type="danger" v-else>
{{ item.statusEnum_enumText }}
</el-tag>
</div>
<div class="info-item">
<el-icon class="info-icon"><Files /></el-icon>
<span class="label">单据类型</span>
<span class="value">{{ item.typeEnum_enumText }}</span>
</div>
<div class="info-item">
<el-icon class="info-icon"><Calendar /></el-icon>
<span class="label">单据日期</span>
<span class="value">{{
parseTime(item.applyTime, '{y}-{m}-{d} {h}:{i}:{s}')
}}</span>
</div>
</div>
</el-card>
</div>
</template>
<!-- 空状态显示 -->
<div v-else class="empty-state">
<el-empty description="暂无单据" :image-size="80">
<el-button type="primary" @click="handleAdd"> 新增单据 </el-button>
</el-empty>
</div>
</div>
</el-scrollbar>
</el-row>
</el-col>
<!-- 右侧表格 -->
<el-col :span="20">
<el-row :gutter="10">
<el-col :span="24">
<orderTable
ref="orderTableRef"
:form="tableForm"
:table-data="tableData"
:audit-form="auditForm"
:table-data-total="tableDataTotal"
:is-add-or-edit-order="isAddOrEditOrder"
:supplier-option="supplierOption"
:supply-type-options="supplyTypeOptions"
:supply-status-options="supplyStatusOptions"
:supply-category-options="supplyCategoryOptions"
:practitioner-option="practitionerOption"
:button-show="buttonShow"
@update:query-params="handleQueryParamsUpdate"
@update:form="handleFormUpdate"
@clearForm="clearForm"
@getList="getList"
@updateButtonState="handleUpdateButtonState"
>
</orderTable>
</el-col>
</el-row>
</el-col>
</el-row>
</div>
</template>
<script setup>
import { ref, onMounted, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import orderTable from './components/orderTable.vue';
import {
getInit,
getOrderList,
deleteOrder,
agreeApproval,
getOrderDetail,
} from './components/api';
import useUserStore from '@/store/modules/user';
import { parseTime } from '@/utils/his';
const route = useRoute();
const router = useRouter();
// 获取 pinia 中用户信息
const userInfo = useUserStore();
// 左侧查询参数
const queryParams = ref({
searchKey: '',
});
// 获取当前实例
const { proxy } = getCurrentInstance();
// 右侧表格查询参数 + 分页参数 + 添加查询参数
const tableForm = ref({
locationId: undefined,
busNo: undefined,
applyTime: undefined,
applicantId: undefined,
reason: undefined,
categoryEnum: undefined,
supplierId: undefined,
pageNo: 1,
pageSize: 10,
});
// 右侧表格数据
const tableData = ref([]);
// 右侧审核表单
const auditForm = ref({
approvalTime: undefined,
statusEnum: undefined,
statusEnum_enumText: undefined,
approverId: undefined,
});
// 订单编辑还是新增
const isAddOrEditOrder = ref({
isAddOrder: false,
isEditOrder: false,
});
// 仓库列表 cabinetList
const cabinetListOptions = ref([]);
// 查询经手人列表 practitionerOption
const practitionerOption = ref([]);
// 查询供应商列表 supplierOption
const supplierOption = ref([]);
// 审批状态 supplyStatusOptions
const supplyStatusOptions = ref([]);
// 单据类型 supplyTypeOptions
const supplyTypeOptions = ref([]);
// 单据分类 supplyCategoryOptions
const supplyCategoryOptions = ref([]);
// 订货单单据列表 orderList
const orderList = ref([]);
// 订货单单据列表总条数
const tableDataTotal = ref(0);
// 选中的单据ID
const selectedOrder = ref(null);
// 是否禁用新增按钮
const isAddDisabled = ref(false);
// 是否禁用编辑按钮
const isEditDisabled = ref(true);
// 是否禁用取消按钮
const isCancelDisabled = ref(true);
// 是否禁用删除按钮
const isDeleteDisabled = ref(true);
// 是否禁用审核按钮
const isAuditDisabled = ref(true);
// 按钮显示 buttonShow
const buttonShow = ref({
isAddShow: false,
isDeleteShow: false,
isSaveShow: false,
isEditShow: false,
});
const rules = ref({
locationId: [{ required: true, message: '请选择库房', trigger: 'blur' }],
});
// 初始化 获取下拉列表
const init = async () => {
const res = await getInit();
// 仓库列表 cabinetListOptions
cabinetListOptions.value = res.data.cabinetListOptions;
// 查询经手人列表 practitionerList
practitionerOption.value = res.data.practitionerOption;
// 查询供应商列表 supplierOption
supplierOption.value = res.data.supplierOption;
// 审批状态 supplyStatusOptions
supplyStatusOptions.value = res.data.supplyStatusOptions;
// 单据类型 supplyTypeOptions
supplyTypeOptions.value = res.data.supplyTypeOptions;
// 单据分类
supplyCategoryOptions.value = res.data.supplyCategoryOptions;
};
// 获取订货单单据列表
const getList = async () => {
const res = await getOrderList(queryParams.value);
// 订货单单据列表 orderList
orderList.value = res.data.records;
};
// 新增按钮
const handleAdd = async () => {
// 清空当前表格数据 和 选中状态
resetFormAndTableData();
// 校验库房ID
if (!tableForm.value.locationId) {
proxy.$modal.msgWarning('新增单据前,请选择库房');
return;
}
// 右侧表单数据
tableForm.value = {
// 采购员
applicantId: userInfo.practitionerId,
// 单据日期
applyTime: parseTime(new Date(), '{y}-{m}-{d} {h}:{i}:{s}'),
// 库房ID
locationId: tableForm.value.locationId,
};
// 订单编辑还是新增
isAddOrEditOrder.value = {
isAddOrder: true,
isEditOrder: false,
};
// 延迟执行
nextTick(() => {
// 更新按钮状态为编辑模式
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: false,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: true,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: true,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: true,
});
});
};
// 清空当前表格数据
const resetFormAndTableData = () => {
// 清空右侧表格数据
tableData.value = [];
// 清空审核表单数据
auditForm.value = {};
// 清空右侧表格数据总条数
tableDataTotal.value = 0;
};
// 编辑按钮
const handleEdit = async (order) => {
// 清空当前表格数据 和 选中状态
resetFormAndTableData();
if (!selectedOrder.value) {
proxy.$modal.msgError('请选择要编辑的单据');
return;
}
const res = await getOrderDetail({
busNo: selectedOrder.value.supplyBusNo,
pageNo: tableForm.value.pageNo,
pageSize: tableForm.value.pageSize,
});
// 构建编辑后的表单数据
buildEditForm(res.data.records);
// 更新表格数据总条数
tableDataTotal.value = res.data.total;
// 根据订单状态更新按钮状态
const isApproved = order.statusEnum_enumText === '同意' || order.statusEnum === 3;
if (isApproved) {
// 设置编辑状态
isAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: false,
};
// 更新按钮状态为初始状态
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: true,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: false,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: false,
});
return;
}
// 设置编辑状态
isAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: true,
};
// 更新按钮状态
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: isApproved,
// 取消 按钮禁用
isCancelDisabled: false,
// 删除 按钮禁用
isDeleteDisabled: isApproved,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: !isApproved,
// 删除行 按钮显示
isDeleteShow: !isApproved,
// 保存行 按钮显示
isSaveShow: !isApproved,
// 编辑行 按钮显示
isEditShow: !isApproved,
// 警戒订货 按钮显示
isAlertShow: !isApproved,
});
};
// 构建单位列表
const buildUnitList = (item) => {
// 表格单位列表
(item.unitList || []).forEach((unit) => {
// 判断当前单位是最大单位还是最小单位
const isMaxUnit = unit.value === item.maxUnitCode;
const isMinUnit = unit.value === item.minUnitCode;
// 进货价(假)
if (isMaxUnit) {
unit.priceMask = item.price;
} else {
unit.priceMask = item.price / parseInt(item.partPercent);
}
// 销售价(假)
if (isMaxUnit) {
unit.retailPriceMask = item.retailPrice;
} else {
unit.retailPriceMask = item.retailPrice / parseInt(item.partPercent);
}
// 进价金额(假)
unit.totalPriceMask = (parseFloat(item.price) * parseFloat(item.itemQuantity)).toFixed(2);
// 销售金额(假)
unit.totalRetailPriceMask = (
parseFloat(item.retailPrice) * parseFloat(item.itemQuantity)
).toFixed(2);
// 规格库存
unit.specificationInventoryOriginal = item.specificationInventory;
// 规格库存显示逻辑
if (isMaxUnit) {
// 最大单位:显示为 "X盒"
unit.specificationInventoryMax = Math.floor(
item.specificationInventory / parseInt(item.partPercent)
);
unit.specificationInventoryMaxUnit =
unit.specificationInventoryMax > 0 ? item.maxUnitCode_dictText : '';
unit.specificationInventoryMin = item.specificationInventory % parseInt(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 buildEditForm = (data) => {
// 构建表格数据
if (data.length > 0) {
// 表单数据
tableForm.value = {
// 单据号
busNo: data[0].busNo,
// 单据日期
applyTime: data[0].applyTime,
// 供应商
supplierId: data[0].supplierId,
// 采购员
applicantId: data[0].applicantId,
// 单据类型
categoryEnum: data[0].categoryEnum,
// 摘要
reason: data[0].reason,
// 仓库
locationId: data[0].purposeLocationId,
};
// 表格数据
data.forEach((item) => {
// 表格编辑状态
item.isEditing = false;
// 表格查看状态
item.isViewing = true;
// 构建单位列表
buildUnitList(item);
});
// 更新表格数据
tableData.value = data;
// 审核表格数据
auditForm.value = {
// 审核时间
approvalTime: data[0].approvalTime,
// 审核状态
statusEnum: data[0].statusEnum,
// 审核状态文本
statusEnum_enumText: data[0].statusEnum_enumText,
// 审核人
approverId: data[0].approverId,
};
// 订单编辑还是新增
isAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: true,
};
}
};
// 取消按钮
const handleCancel = () => {
// 更新按钮状态为初始状态
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: true,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: false,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: false,
});
// 清空表单
clearForm();
};
// 清空表单
const clearForm = () => {
// 清空表单数据
tableForm.value = {};
tableData.value = [];
// 清空右侧表格数据
proxy.$refs.orderTableRef.resetAllData();
// 重置订单状态
isAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: false,
};
};
// 删除按钮
const handleDelete = async () => {
if (!selectedOrder.value) {
proxy.$modal.msgError('请选择要删除的单据');
return;
}
// 校验是否可以删除(已审批的单据不能删除)
if (selectedOrder.value.statusEnum_enumText === '同意' || selectedOrder.value.statusEnum === 3) {
proxy.$modal.msgError('已审批的单据不能删除');
return;
}
try {
await proxy.$modal.confirm('确认删除该采购单吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
});
// 删除单据
await deleteOrder(selectedOrder.value.supplyBusNo);
proxy.$modal.msgSuccess('删除成功');
// 编辑
handleEdit(selectedOrder.value);
// 清空右侧表格数据
clearForm();
// 重新获取列表 库房ID
await getList(tableForm.value.locationId);
// 清空选中状态
selectedOrder.value = null;
// 更新按钮状态为初始状态
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: true,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: false,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: false,
});
} catch (error) {
if (error !== 'cancel') {
proxy.$modal.msgError('删除失败');
console.error('删除失败:', error);
}
}
};
// 审核按钮
const handleAudit = async () => {
if (!selectedOrder.value) {
proxy.$modal.msgError('请选择要审核的单据');
return;
}
// 校验是否是已审批状态
if (selectedOrder.value.statusEnum_enumText === '同意' || selectedOrder.value.statusEnum === 3) {
proxy.$modal.msgError('该单据已审批,不能重复审批');
return;
}
try {
await proxy.$modal.confirm('确认同意该采购单吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
});
// 同意审批
await agreeApproval(selectedOrder.value.supplyBusNo);
proxy.$modal.msgSuccess('同意审批成功');
// 编辑
handleEdit(selectedOrder.value);
// 清空右侧表格数据
clearForm();
// 重新获取列表 库房ID
await getList(tableForm.value.locationId);
// 清空选中状态
selectedOrder.value = null;
// 更新按钮状态为初始状态
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: true,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: false,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: false,
});
isAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: false,
};
} catch (error) {
if (error !== 'cancel') {
proxy.$modal.msgError('同意审批失败');
console.error('同意审批失败:', error);
}
}
};
// 处理订单点击事件
const handleOrderClick = (order) => {
// 选中订单
selectedOrder.value = order;
// 编辑
handleEdit(order);
};
// 处理查询参数更新
const handleQueryParamsUpdate = (newParams) => {
// 更新右侧表格的分页参数
tableForm.value.pageNo = newParams.pageNo;
tableForm.value.pageSize = newParams.pageSize;
// 如果有选中的订单,重新获取订单详情
if (selectedOrder.value) {
handleEdit(selectedOrder.value);
}
};
//
// 处理库房变化
const handleLocationChange = (locationId) => {
queryParams.value.locationId = locationId;
// 重新获取列表
getList();
};
//
// 处理表单更新
const handleFormUpdate = (newForm) => {
tableForm.value = { ...tableForm.value, ...newForm };
};
// 处理按钮状态更新
const handleUpdateButtonState = (buttonState) => {
// 按钮禁用
// 审核 按钮禁用
isAuditDisabled.value = buttonState.isAuditDisabled;
// 取消 按钮禁用
isCancelDisabled.value = buttonState.isCancelDisabled;
// 删除 按钮禁用
isDeleteDisabled.value = buttonState.isDeleteDisabled;
// 添加 按钮禁用
isAddDisabled.value = buttonState.isAddDisabled;
// 编辑 按钮禁用
isEditDisabled.value = buttonState.isEditDisabled;
// 按钮显示
// 添加行 按钮显示
buttonShow.value.isAddShow = buttonState.isAddShow;
// 删除行 按钮显示
buttonShow.value.isDeleteShow = buttonState.isDeleteShow;
// 保存行 按钮显示
buttonShow.value.isSaveShow = buttonState.isSaveShow;
// 编辑行 按钮显示
buttonShow.value.isEditShow = buttonState.isEditShow;
// 警戒订货 按钮显示
buttonShow.value.isAlertShow = buttonState.isAlertShow;
};
// 监听路由变化
watch(
() => route.query,
async (newQuery) => {
//console.log('路由参数发生变化:', newQuery);
if (newQuery.busNo) {
queryParams.value.searchKey = newQuery.busNo;
await getList();
// 设置选中状态
selectedOrder.value = orderList.value.find((item) => item.supplyBusNo === newQuery.busNo);
// 编辑按钮
handleEdit(selectedOrder.value);
// 清空路由参数
// router.replace({ query: {} });
}
},
{ immediate: true }
);
// 下拉列表初始化
init();
</script>
<style scoped lang="scss">
.medicine-container :deep(.el-row) {
margin-bottom: 10px;
}
.medicine-container :deep(.el-row:last-child) {
margin-bottom: 0;
}
// 订单列表容器
.order-list-container {
width: 100%;
padding: 0;
}
// 订单列表项样式
.order-item {
width: 100%;
cursor: pointer;
transition: all 0.3s ease;
border-radius: 6px;
overflow: hidden;
margin: 4px 0;
&:hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
.order-card {
border-color: #409eff;
}
}
&.is-active {
.order-card {
border-color: #409eff;
background: linear-gradient(135deg, #ecf5ff 0%, #f0f9ff 100%);
}
.order-number .number-text {
color: #409eff;
font-weight: 600;
}
}
}
// 订单卡片样式
.order-card {
border: 1px solid #e4e7ed;
border-radius: 6px;
transition: all 0.3s ease;
background: #fff;
overflow: hidden;
:deep(.el-card__body) {
padding: 12px;
}
}
// 订单头部样式
.order-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
padding-bottom: 8px;
border-bottom: 1px solid #f0f0f0;
}
.order-number {
display: flex;
align-items: center;
gap: 6px;
min-width: 0;
flex: 1;
.el-icon {
color: #409eff;
font-size: 14px;
flex-shrink: 0;
}
.number-text {
font-size: 13px;
font-weight: 500;
color: #303133;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.order-status {
flex-shrink: 0;
.el-tag {
border-radius: 10px;
font-weight: 500;
font-size: 11px;
padding: 2px 6px;
}
}
// 订单内容样式
.order-content {
display: flex;
flex-direction: column;
gap: 4px;
}
.info-item {
display: flex;
align-items: center;
gap: 4px;
padding: 4px 0;
min-width: 0;
.info-icon {
color: #909399;
font-size: 12px;
flex-shrink: 0;
}
.label {
color: #606266;
font-size: 12px;
font-weight: 500;
flex-shrink: 0;
}
.value {
color: #303133;
font-size: 12px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
min-width: 0;
flex: 1;
}
}
// 空状态样式
.empty-state {
display: flex;
justify-content: center;
align-items: center;
height: 200px;
color: #909399;
:deep(.el-empty__description) {
color: #909399;
font-size: 14px;
}
:deep(.el-button) {
margin-top: 16px;
}
}
// 响应式设计
@media (max-width: 768px) {
.order-header {
flex-direction: column;
align-items: flex-start;
gap: 6px;
}
.info-item {
padding: 2px 0;
}
.empty-state {
height: 150px;
}
}
</style>

View File

@@ -0,0 +1,65 @@
import request from '@/utils/request';
// 药房请领单单初始化
export function getInit () {
return request ({
url: '/pharmacy-dispensary/returnToWarehouse-order/init',
method: 'get',
});
}
// 请领单单据列表:显示所有单据 左边框
export function getOrderList (query) {
return request ({
url: '/pharmacy-dispensary/returnToWarehouse-order/returnToWarehouse-order-page',
method: 'get',
params: query,
});
}
// 根据供应商获取药品:对应添加/编辑时加下一行数据后,点击项目时调用的接口
export function getMedicineList (query) {
return request ({
url: '/pharmacy-dispensary/returnToWarehouse-order/medication-info',
method: 'get',
params: query,
});
}
// 获取单据号:添加时,获取新单据号。编辑的逻辑是先删除后新增。
export function getBusNo () {
return request ({
url: '/pharmacy-dispensary/returnToWarehouse-order/busNo-init',
method: 'get',
});
}
// 添加/编辑采购单:添加/编辑采购单
export function addOrEditOrder (data) {
return request ({
url: '/pharmacy-dispensary/returnToWarehouse-order/addOrEdit-returnToDispensaryOrder',
method: 'PUT',
data,
});
}
// 删除单据
export function deleteOrder (data) {
return request ({
url: '/pharmacy-dispensary/returnToWarehouse-order/delete-returnToDispensaryOrder?busNo=' +
data,
method: 'DELETE',
});
}
// 同意审批
export function agreeApproval (data) {
return request ({
url: '/pharmacy-dispensary/returnToWarehouse-order/agree-approval?busNo=' + data,
method: 'PUT',
});
}
// 获取单据详情
export function getOrderDetail (query) {
return request ({
url: '/pharmacy-dispensary/returnToWarehouse-order/returnToWarehouse-order-detail-page',
method: 'GET',
params: query,
});
}

View File

@@ -0,0 +1,79 @@
<template>
<div>
<el-table ref="medicineRef" height="400" :data="medicineList" @cell-click="clickRow">
<el-table-column label="项目编码" align="center" prop="busNo" width="150" />
<el-table-column label="项目名称" align="center" prop="name" width="180" />
<el-table-column label="进货价" align="center" prop="price" />
<el-table-column label="零售价" align="center" prop="retailPrice" />
<el-table-column label="包装单位" align="center" prop="unitCode_dictText" />
<el-table-column label="最小单位" align="center" prop="minUnitCode_dictText" />
<el-table-column label="规格" align="center" prop="totalVolume" />
<el-table-column label="规格库存" align="center" prop="specificationInventory" />
<el-table-column label="生产厂家" align="center" prop="manufacturerText" />
<el-table-column label="批准文号" align="center" prop="approvalNumber" />
</el-table>
</div>
</template>
<script setup>
import { getMedicineList } from './api';
import { watch } from 'vue';
import { throttle } from 'lodash-es';
const props = defineProps({
searchKey: {
type: String,
default: '',
},
});
// 选择药品
const emit = defineEmits(['selectRow']);
//
const queryParams = ref({
pageNum: 1,
pageSize: 50,
searchKey: props.searchKey,
// 13 药品
typeEnum: 13,
});
// 药品列表
const medicineList = ref([]);
// 节流函数
const throttledGetList = throttle(
() => {
getList();
},
300,
{ leading: true, trailing: true }
);
// 获取药品列表
const getList = (query) => {
getMedicineList(query || queryParams.value).then((res) => {
medicineList.value = res.data.records;
});
};
// 点击行
const clickRow = (row) => {
// console.log(row, 'row');
emit('selectRow', row);
};
// 监听搜索关键字
watch(
() => props,
(newValue) => {
queryParams.value.searchKey = newValue.searchKey;
throttledGetList();
},
{ immdiate: true, deep: true }
);
// 获取药品列表
getList();
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,997 @@
<!-- 药库订货单 -->
<template>
<div class="medicine-container app-container">
<!-- 顶部按钮 -->
<el-row :gutter="20" :xs="24" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
icon="Plus"
plain
@click="handleAdd"
:disabled="isAddDisabled"
v-hasPermi="['pharmacy-warehouse:purchase-order:add']"
>
新增
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
icon="Delete"
plain
@click="handleDelete"
:disabled="isDeleteDisabled"
v-hasPermi="['pharmacy-warehouse:purchase-order:delete']"
>
删除
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
icon="Close"
plain
@click="handleCancel"
:disabled="isCancelDisabled"
v-hasPermi="['pharmacy-warehouse:purchase-order:cancel']"
>
取消
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
icon="Check"
plain
@click="handleAudit"
:disabled="isAuditDisabled"
v-hasPermi="['pharmacy-warehouse:purchase-order:audit']"
>
审核
</el-button>
</el-col>
</el-row>
<el-row :gutter="20" :xs="24">
<!-- 左侧搜索 -->
<el-col :span="4" style="border: 1px solid #ebeef5; height: calc(100vh - 200px)">
<el-row :gutter="10" style="margin-top: 10px">
<el-col :span="24">
<el-form ref="tableFormRef" :model="tableForm" style="width: 100%" :rules="rules">
<el-form-item label="库房:" label-width="100px">
<el-select
v-model="tableForm.locationId"
placeholder="请选择库房"
clearable
filterable
@change="handleLocationChange(tableForm.locationId)"
>
<el-option
v-for="item in cabinetListOptions"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-form>
</el-col>
</el-row>
<el-row :gutter="10">
<el-form
ref="queryParamsRef"
:model="queryParams"
style="width: 100%"
:rules="rules"
@submit.prevent
>
<el-form-item label="单据搜索" label-width="100px">
<el-input
v-model="queryParams.searchKey"
placeholder="请输入单据号"
@keyup.enter="getList"
clearable
>
<template #append>
<el-button icon="Search" @click="getList" />
</template>
</el-input>
</el-form-item>
</el-form>
</el-row>
<el-row :gutter="10" :xs="24">
<el-scrollbar height="calc(100vh - 350px)" style="width: 100%">
<div class="order-list-container">
<!-- 有数据时显示列表 -->
<template v-if="orderList.length > 0">
<div
v-for="item in orderList"
:key="item.supplyBusNo"
:class="['order-item', { 'is-active': selectedOrder === item }]"
@click="handleOrderClick(item)"
>
<el-card class="order-card" shadow="hover">
<div class="order-header">
<div class="order-number">
<el-icon><Document /></el-icon>
<span class="number-text">{{ item.supplyBusNo }}</span>
</div>
</div>
<div class="order-content">
<div class="info-item">
<el-icon class="info-icon"><User /></el-icon>
<span class="label">采购员</span>
<span class="value">{{ item.applicantId_dictText }}</span>
</div>
<div class="info-item">
<el-icon class="info-icon"><Shop /></el-icon>
<span class="label">供应商</span>
<span class="value">{{ item.supplierId_dictText }}</span>
</div>
<div class="info-item">
<el-icon class="info-icon"><User /></el-icon>
<span class="label">审核状态</span>
<el-tag type="success" v-if="item.statusEnum_enumText === '同意'">
{{ item.statusEnum_enumText }}
</el-tag>
<el-tag type="danger" v-else>
{{ item.statusEnum_enumText }}
</el-tag>
</div>
<div class="info-item">
<el-icon class="info-icon"><Files /></el-icon>
<span class="label">单据类型</span>
<span class="value">{{ item.typeEnum_enumText }}</span>
</div>
<div class="info-item">
<el-icon class="info-icon"><Calendar /></el-icon>
<span class="label">单据日期</span>
<span class="value">{{
parseTime(item.applyTime, '{y}-{m}-{d} {h}:{i}:{s}')
}}</span>
</div>
</div>
</el-card>
</div>
</template>
<!-- 空状态显示 -->
<div v-else class="empty-state">
<el-empty description="暂无单据" :image-size="80">
<el-button type="primary" @click="handleAdd"> 新增单据 </el-button>
</el-empty>
</div>
</div>
</el-scrollbar>
</el-row>
</el-col>
<!-- 右侧表格 -->
<el-col :span="20">
<el-row :gutter="10">
<el-col :span="24">
<orderTable
ref="orderTableRef"
:form="tableForm"
:table-data="tableData"
:audit-form="auditForm"
:table-data-total="tableDataTotal"
:is-add-or-edit-order="isAddOrEditOrder"
:supplier-option="supplierOption"
:supply-type-options="supplyTypeOptions"
:supply-status-options="supplyStatusOptions"
:supply-category-options="supplyCategoryOptions"
:practitioner-option="practitionerOption"
:button-show="buttonShow"
@update:query-params="handleQueryParamsUpdate"
@update:form="handleFormUpdate"
@clearForm="clearForm"
@getList="getList"
@updateButtonState="handleUpdateButtonState"
>
</orderTable>
</el-col>
</el-row>
</el-col>
</el-row>
</div>
</template>
<script setup>
import { ref, onMounted, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import orderTable from './components/orderTable.vue';
import {
getInit,
getOrderList,
deleteOrder,
agreeApproval,
getOrderDetail,
} from './components/api';
import useUserStore from '@/store/modules/user';
import { parseTime } from '@/utils/his';
const route = useRoute();
const router = useRouter();
// 获取 pinia 中用户信息
const userInfo = useUserStore();
// 左侧查询参数
const queryParams = ref({
searchKey: '',
});
// 获取当前实例
const { proxy } = getCurrentInstance();
// 右侧表格查询参数 + 分页参数 + 添加查询参数
const tableForm = ref({
locationId: undefined,
busNo: undefined,
applyTime: undefined,
applicantId: undefined,
reason: undefined,
categoryEnum: undefined,
supplierId: undefined,
pageNo: 1,
pageSize: 10,
});
// 右侧表格数据
const tableData = ref([]);
// 右侧审核表单
const auditForm = ref({
approvalTime: undefined,
statusEnum: undefined,
statusEnum_enumText: undefined,
approverId: undefined,
});
// 订单编辑还是新增
const isAddOrEditOrder = ref({
isAddOrder: false,
isEditOrder: false,
});
// 仓库列表 cabinetList
const cabinetListOptions = ref([]);
// 查询经手人列表 practitionerOption
const practitionerOption = ref([]);
// 查询供应商列表 supplierOption
const supplierOption = ref([]);
// 审批状态 supplyStatusOptions
const supplyStatusOptions = ref([]);
// 单据类型 supplyTypeOptions
const supplyTypeOptions = ref([]);
// 单据分类 supplyCategoryOptions
const supplyCategoryOptions = ref([]);
// 订货单单据列表 orderList
const orderList = ref([]);
// 订货单单据列表总条数
const tableDataTotal = ref(0);
// 选中的单据ID
const selectedOrder = ref(null);
// 是否禁用新增按钮
const isAddDisabled = ref(false);
// 是否禁用编辑按钮
const isEditDisabled = ref(true);
// 是否禁用取消按钮
const isCancelDisabled = ref(true);
// 是否禁用删除按钮
const isDeleteDisabled = ref(true);
// 是否禁用审核按钮
const isAuditDisabled = ref(true);
// 按钮显示 buttonShow
const buttonShow = ref({
isAddShow: false,
isDeleteShow: false,
isSaveShow: false,
isEditShow: false,
});
const rules = ref({
locationId: [{ required: true, message: '请选择库房', trigger: 'blur' }],
});
// 初始化 获取下拉列表
const init = async () => {
const res = await getInit();
// 仓库列表 cabinetListOptions
cabinetListOptions.value = res.data.cabinetListOptions;
// 查询经手人列表 practitionerList
practitionerOption.value = res.data.practitionerOption;
// 查询供应商列表 supplierOption
supplierOption.value = res.data.supplierOption;
// 审批状态 supplyStatusOptions
supplyStatusOptions.value = res.data.supplyStatusOptions;
// 单据类型 supplyTypeOptions
supplyTypeOptions.value = res.data.supplyTypeOptions;
// 单据分类
supplyCategoryOptions.value = res.data.supplyCategoryOptions;
};
// 获取订货单单据列表
const getList = async () => {
const res = await getOrderList(queryParams.value);
// 订货单单据列表 orderList
orderList.value = res.data.records;
};
// 新增按钮
const handleAdd = async () => {
// 清空当前表格数据 和 选中状态
resetFormAndTableData();
// 校验库房ID
if (!tableForm.value.locationId) {
proxy.$modal.msgWarning('新增单据前,请选择库房');
return;
}
// 右侧表单数据
tableForm.value = {
// 采购员
applicantId: userInfo.practitionerId,
// 单据日期
applyTime: parseTime(new Date(), '{y}-{m}-{d} {h}:{i}:{s}'),
// 库房ID
locationId: tableForm.value.locationId,
};
// 订单编辑还是新增
isAddOrEditOrder.value = {
isAddOrder: true,
isEditOrder: false,
};
// 延迟执行
nextTick(() => {
// 更新按钮状态为编辑模式
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: false,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: true,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: true,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: true,
});
});
};
// 清空当前表格数据
const resetFormAndTableData = () => {
// 清空右侧表格数据
tableData.value = [];
// 清空审核表单数据
auditForm.value = {};
// 清空右侧表格数据总条数
tableDataTotal.value = 0;
};
// 编辑按钮
const handleEdit = async (order) => {
// 清空当前表格数据 和 选中状态
resetFormAndTableData();
if (!selectedOrder.value) {
proxy.$modal.msgError('请选择要编辑的单据');
return;
}
const res = await getOrderDetail({
busNo: selectedOrder.value.supplyBusNo,
pageNo: tableForm.value.pageNo,
pageSize: tableForm.value.pageSize,
});
// 构建编辑后的表单数据
buildEditForm(res.data.records);
// 更新表格数据总条数
tableDataTotal.value = res.data.total;
// 根据订单状态更新按钮状态
const isApproved = order.statusEnum_enumText === '同意' || order.statusEnum === 3;
if (isApproved) {
// 设置编辑状态
isAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: false,
};
// 更新按钮状态为初始状态
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: true,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: false,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: false,
});
return;
}
// 设置编辑状态
isAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: true,
};
// 更新按钮状态
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: isApproved,
// 取消 按钮禁用
isCancelDisabled: false,
// 删除 按钮禁用
isDeleteDisabled: isApproved,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: !isApproved,
// 删除行 按钮显示
isDeleteShow: !isApproved,
// 保存行 按钮显示
isSaveShow: !isApproved,
// 编辑行 按钮显示
isEditShow: !isApproved,
// 警戒订货 按钮显示
isAlertShow: !isApproved,
});
};
// 构建单位列表
const buildUnitList = (item) => {
// 表格单位列表
(item.unitList || []).forEach((unit) => {
// 判断当前单位是最大单位还是最小单位
const isMaxUnit = unit.value === item.maxUnitCode;
const isMinUnit = unit.value === item.minUnitCode;
// 进货价(假)
if (isMaxUnit) {
unit.priceMask = item.price;
} else {
unit.priceMask = item.price / parseInt(item.partPercent);
}
// 销售价(假)
if (isMaxUnit) {
unit.retailPriceMask = item.retailPrice;
} else {
unit.retailPriceMask = item.retailPrice / parseInt(item.partPercent);
}
// 进价金额(假)
unit.totalPriceMask = (parseFloat(item.price) * parseFloat(item.itemQuantity)).toFixed(2);
// 销售金额(假)
unit.totalRetailPriceMask = (
parseFloat(item.retailPrice) * parseFloat(item.itemQuantity)
).toFixed(2);
// 规格库存
unit.specificationInventoryOriginal = item.specificationInventory;
// 规格库存显示逻辑
if (isMaxUnit) {
// 最大单位:显示为 "X盒"
unit.specificationInventoryMax = Math.floor(
item.specificationInventory / parseInt(item.partPercent)
);
unit.specificationInventoryMaxUnit =
unit.specificationInventoryMax > 0 ? item.maxUnitCode_dictText : '';
unit.specificationInventoryMin = item.specificationInventory % parseInt(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 buildEditForm = (data) => {
// 构建表格数据
if (data.length > 0) {
// 表单数据
tableForm.value = {
// 单据号
busNo: data[0].busNo,
// 单据日期
applyTime: data[0].applyTime,
// 供应商
supplierId: data[0].supplierId,
// 采购员
applicantId: data[0].applicantId,
// 单据类型
categoryEnum: data[0].categoryEnum,
// 摘要
reason: data[0].reason,
// 仓库
locationId: data[0].purposeLocationId,
};
// 表格数据
data.forEach((item) => {
// 表格编辑状态
item.isEditing = false;
// 表格查看状态
item.isViewing = true;
// 构建单位列表
buildUnitList(item);
});
// 更新表格数据
tableData.value = data;
// 审核表格数据
auditForm.value = {
// 审核时间
approvalTime: data[0].approvalTime,
// 审核状态
statusEnum: data[0].statusEnum,
// 审核状态文本
statusEnum_enumText: data[0].statusEnum_enumText,
// 审核人
approverId: data[0].approverId,
};
// 订单编辑还是新增
isAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: true,
};
}
};
// 取消按钮
const handleCancel = () => {
// 更新按钮状态为初始状态
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: true,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: false,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: false,
});
// 清空表单
clearForm();
};
// 清空表单
const clearForm = () => {
// 清空表单数据
tableForm.value = {};
tableData.value = [];
// 清空右侧表格数据
proxy.$refs.orderTableRef.resetAllData();
// 重置订单状态
isAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: false,
};
};
// 删除按钮
const handleDelete = async () => {
if (!selectedOrder.value) {
proxy.$modal.msgError('请选择要删除的单据');
return;
}
// 校验是否可以删除(已审批的单据不能删除)
if (selectedOrder.value.statusEnum_enumText === '同意' || selectedOrder.value.statusEnum === 3) {
proxy.$modal.msgError('已审批的单据不能删除');
return;
}
try {
await proxy.$modal.confirm('确认删除该采购单吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
});
// 删除单据
await deleteOrder(selectedOrder.value.supplyBusNo);
proxy.$modal.msgSuccess('删除成功');
// 编辑
handleEdit(selectedOrder.value);
// 清空右侧表格数据
clearForm();
// 重新获取列表 库房ID
await getList(tableForm.value.locationId);
// 清空选中状态
selectedOrder.value = null;
// 更新按钮状态为初始状态
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: true,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: false,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: false,
});
} catch (error) {
if (error !== 'cancel') {
proxy.$modal.msgError('删除失败');
console.error('删除失败:', error);
}
}
};
// 审核按钮
const handleAudit = async () => {
if (!selectedOrder.value) {
proxy.$modal.msgError('请选择要审核的单据');
return;
}
// 校验是否是已审批状态
if (selectedOrder.value.statusEnum_enumText === '同意' || selectedOrder.value.statusEnum === 3) {
proxy.$modal.msgError('该单据已审批,不能重复审批');
return;
}
try {
await proxy.$modal.confirm('确认同意该采购单吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
});
// 同意审批
await agreeApproval(selectedOrder.value.supplyBusNo);
proxy.$modal.msgSuccess('同意审批成功');
// 编辑
handleEdit(selectedOrder.value);
// 清空右侧表格数据
clearForm();
// 重新获取列表 库房ID
await getList(tableForm.value.locationId);
// 清空选中状态
selectedOrder.value = null;
// 更新按钮状态为初始状态
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: true,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: false,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: false,
});
isAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: false,
};
} catch (error) {
if (error !== 'cancel') {
proxy.$modal.msgError('同意审批失败');
console.error('同意审批失败:', error);
}
}
};
// 处理订单点击事件
const handleOrderClick = (order) => {
// 选中订单
selectedOrder.value = order;
// 编辑
handleEdit(order);
};
// 处理查询参数更新
const handleQueryParamsUpdate = (newParams) => {
// 更新右侧表格的分页参数
tableForm.value.pageNo = newParams.pageNo;
tableForm.value.pageSize = newParams.pageSize;
// 如果有选中的订单,重新获取订单详情
if (selectedOrder.value) {
handleEdit(selectedOrder.value);
}
};
//
// 处理库房变化
const handleLocationChange = (locationId) => {
queryParams.value.locationId = locationId;
// 重新获取列表
getList();
};
//
// 处理表单更新
const handleFormUpdate = (newForm) => {
tableForm.value = { ...tableForm.value, ...newForm };
};
// 处理按钮状态更新
const handleUpdateButtonState = (buttonState) => {
// 按钮禁用
// 审核 按钮禁用
isAuditDisabled.value = buttonState.isAuditDisabled;
// 取消 按钮禁用
isCancelDisabled.value = buttonState.isCancelDisabled;
// 删除 按钮禁用
isDeleteDisabled.value = buttonState.isDeleteDisabled;
// 添加 按钮禁用
isAddDisabled.value = buttonState.isAddDisabled;
// 编辑 按钮禁用
isEditDisabled.value = buttonState.isEditDisabled;
// 按钮显示
// 添加行 按钮显示
buttonShow.value.isAddShow = buttonState.isAddShow;
// 删除行 按钮显示
buttonShow.value.isDeleteShow = buttonState.isDeleteShow;
// 保存行 按钮显示
buttonShow.value.isSaveShow = buttonState.isSaveShow;
// 编辑行 按钮显示
buttonShow.value.isEditShow = buttonState.isEditShow;
// 警戒订货 按钮显示
buttonShow.value.isAlertShow = buttonState.isAlertShow;
};
// 监听路由变化
watch(
() => route.query,
async (newQuery) => {
//console.log('路由参数发生变化:', newQuery);
if (newQuery.busNo) {
queryParams.value.searchKey = newQuery.busNo;
await getList();
// 设置选中状态
selectedOrder.value = orderList.value.find((item) => item.supplyBusNo === newQuery.busNo);
// 编辑按钮
handleEdit(selectedOrder.value);
// 清空路由参数
// router.replace({ query: {} });
}
},
{ immediate: true }
);
// 下拉列表初始化
init();
</script>
<style scoped lang="scss">
.medicine-container :deep(.el-row) {
margin-bottom: 10px;
}
.medicine-container :deep(.el-row:last-child) {
margin-bottom: 0;
}
// 订单列表容器
.order-list-container {
width: 100%;
padding: 0;
}
// 订单列表项样式
.order-item {
width: 100%;
cursor: pointer;
transition: all 0.3s ease;
border-radius: 6px;
overflow: hidden;
margin: 4px 0;
&:hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
.order-card {
border-color: #409eff;
}
}
&.is-active {
.order-card {
border-color: #409eff;
background: linear-gradient(135deg, #ecf5ff 0%, #f0f9ff 100%);
}
.order-number .number-text {
color: #409eff;
font-weight: 600;
}
}
}
// 订单卡片样式
.order-card {
border: 1px solid #e4e7ed;
border-radius: 6px;
transition: all 0.3s ease;
background: #fff;
overflow: hidden;
:deep(.el-card__body) {
padding: 12px;
}
}
// 订单头部样式
.order-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
padding-bottom: 8px;
border-bottom: 1px solid #f0f0f0;
}
.order-number {
display: flex;
align-items: center;
gap: 6px;
min-width: 0;
flex: 1;
.el-icon {
color: #409eff;
font-size: 14px;
flex-shrink: 0;
}
.number-text {
font-size: 13px;
font-weight: 500;
color: #303133;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.order-status {
flex-shrink: 0;
.el-tag {
border-radius: 10px;
font-weight: 500;
font-size: 11px;
padding: 2px 6px;
}
}
// 订单内容样式
.order-content {
display: flex;
flex-direction: column;
gap: 4px;
}
.info-item {
display: flex;
align-items: center;
gap: 4px;
padding: 4px 0;
min-width: 0;
.info-icon {
color: #909399;
font-size: 12px;
flex-shrink: 0;
}
.label {
color: #606266;
font-size: 12px;
font-weight: 500;
flex-shrink: 0;
}
.value {
color: #303133;
font-size: 12px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
min-width: 0;
flex: 1;
}
}
// 空状态样式
.empty-state {
display: flex;
justify-content: center;
align-items: center;
height: 200px;
color: #909399;
:deep(.el-empty__description) {
color: #909399;
font-size: 14px;
}
:deep(.el-button) {
margin-top: 16px;
}
}
// 响应式设计
@media (max-width: 768px) {
.order-header {
flex-direction: column;
align-items: flex-start;
gap: 6px;
}
.info-item {
padding: 2px 0;
}
.empty-state {
height: 150px;
}
}
</style>

View File

@@ -0,0 +1,65 @@
import request from '@/utils/request';
// 药房入库单单初始化
export function getInit () {
return request ({
url: '/pharmacy-dispensary/stockIn-order/init',
method: 'get',
});
}
// 入库单单据列表:显示所有单据 左边框
export function getOrderList (query) {
return request ({
url: '/pharmacy-dispensary/stockIn-order/stockIn-order-page',
method: 'get',
params: query,
});
}
// 根据供应商获取药品:对应添加/编辑时加下一行数据后,点击项目时调用的接口
export function getMedicineList (query) {
return request ({
url: '/pharmacy-dispensary/stockIn-order/medication-info',
method: 'get',
params: query,
});
}
// 获取单据号:添加时,获取新单据号。编辑的逻辑是先删除后新增。
export function getBusNo () {
return request ({
url: '/pharmacy-dispensary/stockIn-order/busNo-init',
method: 'get',
});
}
// 添加/编辑采购单:添加/编辑采购单
export function addOrEditOrder (data) {
return request ({
url: '/pharmacy-dispensary/stockIn-order/addOrEdit-stockInOrder',
method: 'PUT',
data,
});
}
// 删除单据
export function deleteOrder (data) {
return request ({
url: '/pharmacy-dispensary/stockIn-order/delete-stockInOrder?busNo=' +
data,
method: 'DELETE',
});
}
// 同意审批
export function agreeApproval (data) {
return request ({
url: '/pharmacy-dispensary/stockIn-order/agree-approval?busNo=' + data,
method: 'PUT',
});
}
// 获取单据详情
export function getOrderDetail (query) {
return request ({
url: '/pharmacy-dispensary/stockIn-order/stockIn-order-detail-page',
method: 'GET',
params: query,
});
}

View File

@@ -0,0 +1,79 @@
<template>
<div>
<el-table ref="medicineRef" height="400" :data="medicineList" @cell-click="clickRow">
<el-table-column label="项目编码" align="center" prop="busNo" width="150" />
<el-table-column label="项目名称" align="center" prop="name" width="180" />
<el-table-column label="进货价" align="center" prop="price" />
<el-table-column label="零售价" align="center" prop="retailPrice" />
<el-table-column label="包装单位" align="center" prop="unitCode_dictText" />
<el-table-column label="最小单位" align="center" prop="minUnitCode_dictText" />
<el-table-column label="规格" align="center" prop="totalVolume" />
<el-table-column label="规格库存" align="center" prop="specificationInventory" />
<el-table-column label="生产厂家" align="center" prop="manufacturerText" />
<el-table-column label="批准文号" align="center" prop="approvalNumber" />
</el-table>
</div>
</template>
<script setup>
import { getMedicineList } from './api';
import { watch } from 'vue';
import { throttle } from 'lodash-es';
const props = defineProps({
searchKey: {
type: String,
default: '',
},
});
// 选择药品
const emit = defineEmits(['selectRow']);
//
const queryParams = ref({
pageNum: 1,
pageSize: 50,
searchKey: props.searchKey,
// 13 药品
typeEnum: 13,
});
// 药品列表
const medicineList = ref([]);
// 节流函数
const throttledGetList = throttle(
() => {
getList();
},
300,
{ leading: true, trailing: true }
);
// 获取药品列表
const getList = (query) => {
getMedicineList(query || queryParams.value).then((res) => {
medicineList.value = res.data.records;
});
};
// 点击行
const clickRow = (row) => {
// console.log(row, 'row');
emit('selectRow', row);
};
// 监听搜索关键字
watch(
() => props,
(newValue) => {
queryParams.value.searchKey = newValue.searchKey;
throttledGetList();
},
{ immdiate: true, deep: true }
);
// 获取药品列表
getList();
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,997 @@
<!-- 药库订货单 -->
<template>
<div class="medicine-container app-container">
<!-- 顶部按钮 -->
<el-row :gutter="20" :xs="24" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
icon="Plus"
plain
@click="handleAdd"
:disabled="isAddDisabled"
v-hasPermi="['pharmacy-warehouse:purchase-order:add']"
>
新增
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
icon="Delete"
plain
@click="handleDelete"
:disabled="isDeleteDisabled"
v-hasPermi="['pharmacy-warehouse:purchase-order:delete']"
>
删除
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
icon="Close"
plain
@click="handleCancel"
:disabled="isCancelDisabled"
v-hasPermi="['pharmacy-warehouse:purchase-order:cancel']"
>
取消
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
icon="Check"
plain
@click="handleAudit"
:disabled="isAuditDisabled"
v-hasPermi="['pharmacy-warehouse:purchase-order:audit']"
>
审核
</el-button>
</el-col>
</el-row>
<el-row :gutter="20" :xs="24">
<!-- 左侧搜索 -->
<el-col :span="4" style="border: 1px solid #ebeef5; height: calc(100vh - 200px)">
<el-row :gutter="10" style="margin-top: 10px">
<el-col :span="24">
<el-form ref="tableFormRef" :model="tableForm" style="width: 100%" :rules="rules">
<el-form-item label="库房:" label-width="100px">
<el-select
v-model="tableForm.locationId"
placeholder="请选择库房"
clearable
filterable
@change="handleLocationChange(tableForm.locationId)"
>
<el-option
v-for="item in cabinetListOptions"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-form>
</el-col>
</el-row>
<el-row :gutter="10">
<el-form
ref="queryParamsRef"
:model="queryParams"
style="width: 100%"
:rules="rules"
@submit.prevent
>
<el-form-item label="单据搜索" label-width="100px">
<el-input
v-model="queryParams.searchKey"
placeholder="请输入单据号"
@keyup.enter="getList"
clearable
>
<template #append>
<el-button icon="Search" @click="getList" />
</template>
</el-input>
</el-form-item>
</el-form>
</el-row>
<el-row :gutter="10" :xs="24">
<el-scrollbar height="calc(100vh - 350px)" style="width: 100%">
<div class="order-list-container">
<!-- 有数据时显示列表 -->
<template v-if="orderList.length > 0">
<div
v-for="item in orderList"
:key="item.supplyBusNo"
:class="['order-item', { 'is-active': selectedOrder === item }]"
@click="handleOrderClick(item)"
>
<el-card class="order-card" shadow="hover">
<div class="order-header">
<div class="order-number">
<el-icon><Document /></el-icon>
<span class="number-text">{{ item.supplyBusNo }}</span>
</div>
</div>
<div class="order-content">
<div class="info-item">
<el-icon class="info-icon"><User /></el-icon>
<span class="label">采购员</span>
<span class="value">{{ item.applicantId_dictText }}</span>
</div>
<div class="info-item">
<el-icon class="info-icon"><Shop /></el-icon>
<span class="label">供应商</span>
<span class="value">{{ item.supplierId_dictText }}</span>
</div>
<div class="info-item">
<el-icon class="info-icon"><User /></el-icon>
<span class="label">审核状态</span>
<el-tag type="success" v-if="item.statusEnum_enumText === '同意'">
{{ item.statusEnum_enumText }}
</el-tag>
<el-tag type="danger" v-else>
{{ item.statusEnum_enumText }}
</el-tag>
</div>
<div class="info-item">
<el-icon class="info-icon"><Files /></el-icon>
<span class="label">单据类型</span>
<span class="value">{{ item.typeEnum_enumText }}</span>
</div>
<div class="info-item">
<el-icon class="info-icon"><Calendar /></el-icon>
<span class="label">单据日期</span>
<span class="value">{{
parseTime(item.applyTime, '{y}-{m}-{d} {h}:{i}:{s}')
}}</span>
</div>
</div>
</el-card>
</div>
</template>
<!-- 空状态显示 -->
<div v-else class="empty-state">
<el-empty description="暂无单据" :image-size="80">
<el-button type="primary" @click="handleAdd"> 新增单据 </el-button>
</el-empty>
</div>
</div>
</el-scrollbar>
</el-row>
</el-col>
<!-- 右侧表格 -->
<el-col :span="20">
<el-row :gutter="10">
<el-col :span="24">
<orderTable
ref="orderTableRef"
:form="tableForm"
:table-data="tableData"
:audit-form="auditForm"
:table-data-total="tableDataTotal"
:is-add-or-edit-order="isAddOrEditOrder"
:supplier-option="supplierOption"
:supply-type-options="supplyTypeOptions"
:supply-status-options="supplyStatusOptions"
:supply-category-options="supplyCategoryOptions"
:practitioner-option="practitionerOption"
:button-show="buttonShow"
@update:query-params="handleQueryParamsUpdate"
@update:form="handleFormUpdate"
@clearForm="clearForm"
@getList="getList"
@updateButtonState="handleUpdateButtonState"
>
</orderTable>
</el-col>
</el-row>
</el-col>
</el-row>
</div>
</template>
<script setup>
import { ref, onMounted, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import orderTable from './components/orderTable.vue';
import {
getInit,
getOrderList,
deleteOrder,
agreeApproval,
getOrderDetail,
} from './components/api';
import useUserStore from '@/store/modules/user';
import { parseTime } from '@/utils/his';
const route = useRoute();
const router = useRouter();
// 获取 pinia 中用户信息
const userInfo = useUserStore();
// 左侧查询参数
const queryParams = ref({
searchKey: '',
});
// 获取当前实例
const { proxy } = getCurrentInstance();
// 右侧表格查询参数 + 分页参数 + 添加查询参数
const tableForm = ref({
locationId: undefined,
busNo: undefined,
applyTime: undefined,
applicantId: undefined,
reason: undefined,
categoryEnum: undefined,
supplierId: undefined,
pageNo: 1,
pageSize: 10,
});
// 右侧表格数据
const tableData = ref([]);
// 右侧审核表单
const auditForm = ref({
approvalTime: undefined,
statusEnum: undefined,
statusEnum_enumText: undefined,
approverId: undefined,
});
// 订单编辑还是新增
const isAddOrEditOrder = ref({
isAddOrder: false,
isEditOrder: false,
});
// 仓库列表 cabinetList
const cabinetListOptions = ref([]);
// 查询经手人列表 practitionerOption
const practitionerOption = ref([]);
// 查询供应商列表 supplierOption
const supplierOption = ref([]);
// 审批状态 supplyStatusOptions
const supplyStatusOptions = ref([]);
// 单据类型 supplyTypeOptions
const supplyTypeOptions = ref([]);
// 单据分类 supplyCategoryOptions
const supplyCategoryOptions = ref([]);
// 订货单单据列表 orderList
const orderList = ref([]);
// 订货单单据列表总条数
const tableDataTotal = ref(0);
// 选中的单据ID
const selectedOrder = ref(null);
// 是否禁用新增按钮
const isAddDisabled = ref(false);
// 是否禁用编辑按钮
const isEditDisabled = ref(true);
// 是否禁用取消按钮
const isCancelDisabled = ref(true);
// 是否禁用删除按钮
const isDeleteDisabled = ref(true);
// 是否禁用审核按钮
const isAuditDisabled = ref(true);
// 按钮显示 buttonShow
const buttonShow = ref({
isAddShow: false,
isDeleteShow: false,
isSaveShow: false,
isEditShow: false,
});
const rules = ref({
locationId: [{ required: true, message: '请选择库房', trigger: 'blur' }],
});
// 初始化 获取下拉列表
const init = async () => {
const res = await getInit();
// 仓库列表 cabinetListOptions
cabinetListOptions.value = res.data.cabinetListOptions;
// 查询经手人列表 practitionerList
practitionerOption.value = res.data.practitionerOption;
// 查询供应商列表 supplierOption
supplierOption.value = res.data.supplierOption;
// 审批状态 supplyStatusOptions
supplyStatusOptions.value = res.data.supplyStatusOptions;
// 单据类型 supplyTypeOptions
supplyTypeOptions.value = res.data.supplyTypeOptions;
// 单据分类
supplyCategoryOptions.value = res.data.supplyCategoryOptions;
};
// 获取订货单单据列表
const getList = async () => {
const res = await getOrderList(queryParams.value);
// 订货单单据列表 orderList
orderList.value = res.data.records;
};
// 新增按钮
const handleAdd = async () => {
// 清空当前表格数据 和 选中状态
resetFormAndTableData();
// 校验库房ID
if (!tableForm.value.locationId) {
proxy.$modal.msgWarning('新增单据前,请选择库房');
return;
}
// 右侧表单数据
tableForm.value = {
// 采购员
applicantId: userInfo.practitionerId,
// 单据日期
applyTime: parseTime(new Date(), '{y}-{m}-{d} {h}:{i}:{s}'),
// 库房ID
locationId: tableForm.value.locationId,
};
// 订单编辑还是新增
isAddOrEditOrder.value = {
isAddOrder: true,
isEditOrder: false,
};
// 延迟执行
nextTick(() => {
// 更新按钮状态为编辑模式
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: false,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: true,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: true,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: true,
});
});
};
// 清空当前表格数据
const resetFormAndTableData = () => {
// 清空右侧表格数据
tableData.value = [];
// 清空审核表单数据
auditForm.value = {};
// 清空右侧表格数据总条数
tableDataTotal.value = 0;
};
// 编辑按钮
const handleEdit = async (order) => {
// 清空当前表格数据 和 选中状态
resetFormAndTableData();
if (!selectedOrder.value) {
proxy.$modal.msgError('请选择要编辑的单据');
return;
}
const res = await getOrderDetail({
busNo: selectedOrder.value.supplyBusNo,
pageNo: tableForm.value.pageNo,
pageSize: tableForm.value.pageSize,
});
// 构建编辑后的表单数据
buildEditForm(res.data.records);
// 更新表格数据总条数
tableDataTotal.value = res.data.total;
// 根据订单状态更新按钮状态
const isApproved = order.statusEnum_enumText === '同意' || order.statusEnum === 3;
if (isApproved) {
// 设置编辑状态
isAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: false,
};
// 更新按钮状态为初始状态
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: true,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: false,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: false,
});
return;
}
// 设置编辑状态
isAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: true,
};
// 更新按钮状态
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: isApproved,
// 取消 按钮禁用
isCancelDisabled: false,
// 删除 按钮禁用
isDeleteDisabled: isApproved,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: !isApproved,
// 删除行 按钮显示
isDeleteShow: !isApproved,
// 保存行 按钮显示
isSaveShow: !isApproved,
// 编辑行 按钮显示
isEditShow: !isApproved,
// 警戒订货 按钮显示
isAlertShow: !isApproved,
});
};
// 构建单位列表
const buildUnitList = (item) => {
// 表格单位列表
(item.unitList || []).forEach((unit) => {
// 判断当前单位是最大单位还是最小单位
const isMaxUnit = unit.value === item.maxUnitCode;
const isMinUnit = unit.value === item.minUnitCode;
// 进货价(假)
if (isMaxUnit) {
unit.priceMask = item.price;
} else {
unit.priceMask = item.price / parseInt(item.partPercent);
}
// 销售价(假)
if (isMaxUnit) {
unit.retailPriceMask = item.retailPrice;
} else {
unit.retailPriceMask = item.retailPrice / parseInt(item.partPercent);
}
// 进价金额(假)
unit.totalPriceMask = (parseFloat(item.price) * parseFloat(item.itemQuantity)).toFixed(2);
// 销售金额(假)
unit.totalRetailPriceMask = (
parseFloat(item.retailPrice) * parseFloat(item.itemQuantity)
).toFixed(2);
// 规格库存
unit.specificationInventoryOriginal = item.specificationInventory;
// 规格库存显示逻辑
if (isMaxUnit) {
// 最大单位:显示为 "X盒"
unit.specificationInventoryMax = Math.floor(
item.specificationInventory / parseInt(item.partPercent)
);
unit.specificationInventoryMaxUnit =
unit.specificationInventoryMax > 0 ? item.maxUnitCode_dictText : '';
unit.specificationInventoryMin = item.specificationInventory % parseInt(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 buildEditForm = (data) => {
// 构建表格数据
if (data.length > 0) {
// 表单数据
tableForm.value = {
// 单据号
busNo: data[0].busNo,
// 单据日期
applyTime: data[0].applyTime,
// 供应商
supplierId: data[0].supplierId,
// 采购员
applicantId: data[0].applicantId,
// 单据类型
categoryEnum: data[0].categoryEnum,
// 摘要
reason: data[0].reason,
// 仓库
locationId: data[0].purposeLocationId,
};
// 表格数据
data.forEach((item) => {
// 表格编辑状态
item.isEditing = false;
// 表格查看状态
item.isViewing = true;
// 构建单位列表
buildUnitList(item);
});
// 更新表格数据
tableData.value = data;
// 审核表格数据
auditForm.value = {
// 审核时间
approvalTime: data[0].approvalTime,
// 审核状态
statusEnum: data[0].statusEnum,
// 审核状态文本
statusEnum_enumText: data[0].statusEnum_enumText,
// 审核人
approverId: data[0].approverId,
};
// 订单编辑还是新增
isAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: true,
};
}
};
// 取消按钮
const handleCancel = () => {
// 更新按钮状态为初始状态
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: true,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: false,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: false,
});
// 清空表单
clearForm();
};
// 清空表单
const clearForm = () => {
// 清空表单数据
tableForm.value = {};
tableData.value = [];
// 清空右侧表格数据
proxy.$refs.orderTableRef.resetAllData();
// 重置订单状态
isAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: false,
};
};
// 删除按钮
const handleDelete = async () => {
if (!selectedOrder.value) {
proxy.$modal.msgError('请选择要删除的单据');
return;
}
// 校验是否可以删除(已审批的单据不能删除)
if (selectedOrder.value.statusEnum_enumText === '同意' || selectedOrder.value.statusEnum === 3) {
proxy.$modal.msgError('已审批的单据不能删除');
return;
}
try {
await proxy.$modal.confirm('确认删除该采购单吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
});
// 删除单据
await deleteOrder(selectedOrder.value.supplyBusNo);
proxy.$modal.msgSuccess('删除成功');
// 编辑
handleEdit(selectedOrder.value);
// 清空右侧表格数据
clearForm();
// 重新获取列表 库房ID
await getList(tableForm.value.locationId);
// 清空选中状态
selectedOrder.value = null;
// 更新按钮状态为初始状态
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: true,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: false,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: false,
});
} catch (error) {
if (error !== 'cancel') {
proxy.$modal.msgError('删除失败');
console.error('删除失败:', error);
}
}
};
// 审核按钮
const handleAudit = async () => {
if (!selectedOrder.value) {
proxy.$modal.msgError('请选择要审核的单据');
return;
}
// 校验是否是已审批状态
if (selectedOrder.value.statusEnum_enumText === '同意' || selectedOrder.value.statusEnum === 3) {
proxy.$modal.msgError('该单据已审批,不能重复审批');
return;
}
try {
await proxy.$modal.confirm('确认同意该采购单吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
});
// 同意审批
await agreeApproval(selectedOrder.value.supplyBusNo);
proxy.$modal.msgSuccess('同意审批成功');
// 编辑
handleEdit(selectedOrder.value);
// 清空右侧表格数据
clearForm();
// 重新获取列表 库房ID
await getList(tableForm.value.locationId);
// 清空选中状态
selectedOrder.value = null;
// 更新按钮状态为初始状态
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: true,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: false,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: false,
});
isAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: false,
};
} catch (error) {
if (error !== 'cancel') {
proxy.$modal.msgError('同意审批失败');
console.error('同意审批失败:', error);
}
}
};
// 处理订单点击事件
const handleOrderClick = (order) => {
// 选中订单
selectedOrder.value = order;
// 编辑
handleEdit(order);
};
// 处理查询参数更新
const handleQueryParamsUpdate = (newParams) => {
// 更新右侧表格的分页参数
tableForm.value.pageNo = newParams.pageNo;
tableForm.value.pageSize = newParams.pageSize;
// 如果有选中的订单,重新获取订单详情
if (selectedOrder.value) {
handleEdit(selectedOrder.value);
}
};
//
// 处理库房变化
const handleLocationChange = (locationId) => {
queryParams.value.locationId = locationId;
// 重新获取列表
getList();
};
//
// 处理表单更新
const handleFormUpdate = (newForm) => {
tableForm.value = { ...tableForm.value, ...newForm };
};
// 处理按钮状态更新
const handleUpdateButtonState = (buttonState) => {
// 按钮禁用
// 审核 按钮禁用
isAuditDisabled.value = buttonState.isAuditDisabled;
// 取消 按钮禁用
isCancelDisabled.value = buttonState.isCancelDisabled;
// 删除 按钮禁用
isDeleteDisabled.value = buttonState.isDeleteDisabled;
// 添加 按钮禁用
isAddDisabled.value = buttonState.isAddDisabled;
// 编辑 按钮禁用
isEditDisabled.value = buttonState.isEditDisabled;
// 按钮显示
// 添加行 按钮显示
buttonShow.value.isAddShow = buttonState.isAddShow;
// 删除行 按钮显示
buttonShow.value.isDeleteShow = buttonState.isDeleteShow;
// 保存行 按钮显示
buttonShow.value.isSaveShow = buttonState.isSaveShow;
// 编辑行 按钮显示
buttonShow.value.isEditShow = buttonState.isEditShow;
// 警戒订货 按钮显示
buttonShow.value.isAlertShow = buttonState.isAlertShow;
};
// 监听路由变化
watch(
() => route.query,
async (newQuery) => {
//console.log('路由参数发生变化:', newQuery);
if (newQuery.busNo) {
queryParams.value.searchKey = newQuery.busNo;
await getList();
// 设置选中状态
selectedOrder.value = orderList.value.find((item) => item.supplyBusNo === newQuery.busNo);
// 编辑按钮
handleEdit(selectedOrder.value);
// 清空路由参数
// router.replace({ query: {} });
}
},
{ immediate: true }
);
// 下拉列表初始化
init();
</script>
<style scoped lang="scss">
.medicine-container :deep(.el-row) {
margin-bottom: 10px;
}
.medicine-container :deep(.el-row:last-child) {
margin-bottom: 0;
}
// 订单列表容器
.order-list-container {
width: 100%;
padding: 0;
}
// 订单列表项样式
.order-item {
width: 100%;
cursor: pointer;
transition: all 0.3s ease;
border-radius: 6px;
overflow: hidden;
margin: 4px 0;
&:hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
.order-card {
border-color: #409eff;
}
}
&.is-active {
.order-card {
border-color: #409eff;
background: linear-gradient(135deg, #ecf5ff 0%, #f0f9ff 100%);
}
.order-number .number-text {
color: #409eff;
font-weight: 600;
}
}
}
// 订单卡片样式
.order-card {
border: 1px solid #e4e7ed;
border-radius: 6px;
transition: all 0.3s ease;
background: #fff;
overflow: hidden;
:deep(.el-card__body) {
padding: 12px;
}
}
// 订单头部样式
.order-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
padding-bottom: 8px;
border-bottom: 1px solid #f0f0f0;
}
.order-number {
display: flex;
align-items: center;
gap: 6px;
min-width: 0;
flex: 1;
.el-icon {
color: #409eff;
font-size: 14px;
flex-shrink: 0;
}
.number-text {
font-size: 13px;
font-weight: 500;
color: #303133;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.order-status {
flex-shrink: 0;
.el-tag {
border-radius: 10px;
font-weight: 500;
font-size: 11px;
padding: 2px 6px;
}
}
// 订单内容样式
.order-content {
display: flex;
flex-direction: column;
gap: 4px;
}
.info-item {
display: flex;
align-items: center;
gap: 4px;
padding: 4px 0;
min-width: 0;
.info-icon {
color: #909399;
font-size: 12px;
flex-shrink: 0;
}
.label {
color: #606266;
font-size: 12px;
font-weight: 500;
flex-shrink: 0;
}
.value {
color: #303133;
font-size: 12px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
min-width: 0;
flex: 1;
}
}
// 空状态样式
.empty-state {
display: flex;
justify-content: center;
align-items: center;
height: 200px;
color: #909399;
:deep(.el-empty__description) {
color: #909399;
font-size: 14px;
}
:deep(.el-button) {
margin-top: 16px;
}
}
// 响应式设计
@media (max-width: 768px) {
.order-header {
flex-direction: column;
align-items: flex-start;
gap: 6px;
}
.info-item {
padding: 2px 0;
}
.empty-state {
height: 150px;
}
}
</style>

View File

@@ -0,0 +1,83 @@
import request from '@/utils/request';
// 药库订货单初始化
export function getInit () {
return request ({
url: '/pharmacy-dispensary/stocktaking-order/init',
method: 'get',
});
}
// 订货单单据列表:显示所有单据 左边框
export function getOrderList (query) {
return request ({
url: '/pharmacy-dispensary/stocktaking-order/stocktaking-order-page',
method: 'get',
params: query,
});
}
// 根据供应商获取药品:对应添加/编辑时加下一行数据后,点击项目时调用的接口
export function getMedicineList (query) {
return request ({
url: '/pharmacy-dispensary/stocktaking-order/medication-info',
method: 'get',
params: query,
});
}
// 获取单据号:添加时,获取新单据号。编辑的逻辑是先删除后新增。
export function getBusNo () {
return request ({
url: '/pharmacy-dispensary/stocktaking-order/busNo-init',
method: 'get',
});
}
// 添加/编辑采购单:添加/编辑采购单
export function addOrEditOrder (data) {
return request ({
url: '/pharmacy-dispensary/stocktaking-order/addOrEdit-stocktakingOrder',
method: 'PUT',
data,
});
}
// 删除单据
export function deleteOrder (data) {
return request ({
url: '/pharmacy-dispensary/stocktaking-order/delete-stocktakingOrder?busNo=' +
data,
method: 'DELETE',
});
}
// 同意审批
export function agreeApproval (data) {
return request ({
url: '/pharmacy-dispensary/stocktaking-order/agree-approval?busNo=' + data,
method: 'PUT',
});
}
// 获取单据详情
export function getOrderDetail (query) {
return request ({
url: '/pharmacy-dispensary/stocktaking-order/stocktaking-order-detail-page',
method: 'GET',
params: query,
});
}
// 订货单单据列表
export function getPurchaseOrderList (query) {
return request ({
url: '/pharmacy-warehouse/purchase-order/purchase-order-page',
method: 'get',
params: query,
});
}
// 获取单据详情
export function getPurchaseOrderDetail (query) {
return request ({
url: '/pharmacy-warehouse/purchase-order/purchase-order-detail-page',
method: 'GET',
params: query,
});
}

View File

@@ -0,0 +1,88 @@
<template>
<div>
<el-table ref="medicineRef" height="400" :data="medicineList" @cell-click="clickRow">
<el-table-column label="项目编码" align="center" prop="busNo" width="150" />
<el-table-column label="项目名称" align="center" prop="name" width="180" />
<el-table-column label="进货价" align="center" prop="price" />
<el-table-column label="零售价" align="center" prop="retailPrice" />
<el-table-column label="包装单位" align="center" prop="unitCode_dictText" />
<el-table-column label="最小单位" align="center" prop="minUnitCode_dictText" />
<el-table-column label="规格" align="center" prop="totalVolume" />
<el-table-column label="规格库存" align="center" prop="specificationInventory" />
<el-table-column label="批次库存" align="center" prop="batchInventory" />
<el-table-column label="供应商" align="center" prop="supplierId_dictText" />
<el-table-column label="生产厂家" align="center" prop="manufacturerText" />
<el-table-column label="批准文号" align="center" prop="approvalNumber" />
</el-table>
</div>
</template>
<script setup>
import { getMedicineList } from './api';
import { watch } from 'vue';
import { throttle } from 'lodash-es';
const props = defineProps({
searchKey: {
type: String,
default: '',
},
locationId: {
type: String,
default: '',
},
});
// 选择药品
const emit = defineEmits(['selectRow']);
//
const queryParams = ref({
pageNum: 1,
pageSize: 50,
searchKey: props.searchKey,
});
// 药品列表
const medicineList = ref([]);
// 节流函数
const throttledGetList = throttle(
() => {
getList();
},
300,
{ leading: true, trailing: true }
);
// 获取药品列表
const getList = (query) => {
queryParams.value = {
...queryParams.value,
...query,
locationId: props.locationId,
}
getMedicineList(query || queryParams.value).then((res) => {
medicineList.value = res.data.records;
});
};
// 点击行
const clickRow = (row) => {
// console.log(row, 'row');
emit('selectRow', row);
};
// 监听搜索关键字
watch(
() => props,
(newValue) => {
queryParams.value.searchKey = newValue.searchKey;
throttledGetList();
},
{ immdiate: true, deep: true }
);
// 获取药品列表
getList();
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,343 @@
<template>
<div>
<el-dialog
title="订单列表"
v-model="localDialogVisible"
width="960px"
append-to-body
@close="resetAllData"
>
<el-table
:data="orderList"
ref="tableRef"
width="100%"
highlight-current-row
height="470px"
@row-dblclick="handleRowDBClick"
@row-click="handleRowClick"
>
<el-table-column
label="订单编号"
prop="supplyBusNo"
width="200"
align="center"
></el-table-column>
<el-table-column label="采购员" prop="applicantId_dictText" width="100" align="center" />
<el-table-column label="供应商" prop="supplierId_dictText" width="220" align="center" />
<el-table-column label="审核状态" prop="statusEnum_enumText" width="100" align="center">
<template #default="scope">
<el-tag v-if="scope.row.statusEnum_enumText === '同意'" type="success">
{{ scope.row.statusEnum_enumText }}
</el-tag>
<el-tag v-else type="danger">{{ scope.row.statusEnum_enumText }}</el-tag>
</template>
</el-table-column>
<el-table-column label="单据类型" prop="typeEnum_enumText" width="100" align="center" />
<el-table-column label="单据日期" prop="applyTime" width="200" align="center">
<template #default="scope">
{{ parseTime(scope.row.applyTime, '{yy}-{mm}-{dd} {hh}:{ii}:{ss}') }}
</template>
</el-table-column>
</el-table>
<el-row justify="end" style="margin-top: 10px">
<el-pagination
:current-page="queryParams.pageNo"
:page-size="queryParams.pageSize"
:page-sizes="[10, 50, 100, 200]"
layout="total, sizes, prev, pager, next, jumper"
:total="localTableDataTotal"
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
v-show="localTableDataTotal > 0"
/>
</el-row>
<template #footer>
<div class="dialog-footer">
<el-button @click="handleCancel">取消</el-button>
<el-button type="primary" @click="handleSubmit"> 确认 </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { getPurchaseOrderList, getPurchaseOrderDetail } from './api';
import { ref, watch, getCurrentInstance } from 'vue';
import { parseTime } from '@/utils/his';
// 调用父组件方法
const emit = defineEmits(['dialogSubmit', 'dialogCancel', 'updateTableData']);
// 获取当前实例
const { proxy } = getCurrentInstance();
// 属性
const props = defineProps({
// 对话框x显示
dialogVisible: {
type: Boolean,
default: false,
},
});
// 本地对话框显示
const localDialogVisible = ref(false);
// 监听属性
watch(
() => props.dialogVisible,
(newValue) => {
localDialogVisible.value = newValue;
}
);
// 获取当前行
const currentRow = ref({});
// 行点击 双击
const handleRowClick = (row) => {
// 设置当前行
currentRow.value = row;
};
// 行点击 双击
const handleRowDBClick = (row) => {
// 设置当前行
currentRow.value = row;
// 提交
handleSubmit();
};
// 订单列表
const orderList = ref([]);
// 订单列表总条数
const localTableDataTotal = ref(0);
// 当前locationId
const currentLocationId = ref(undefined);
// 查询参数
const queryParams = ref({
pageNo: 1,
pageSize: 10,
locationId: undefined,
});
// 分页每页条数
const handleSizeChange = (size) => {
queryParams.value.pageSize = size;
queryParams.value.pageNo = 1; // 切换每页条数时重置到第一页
// 重新获取数据
if (currentLocationId.value) {
getOrderList(currentLocationId.value);
}
};
// 分页当前页
const handleCurrentChange = (page) => {
queryParams.value.pageNo = page;
// 重新获取数据
if (currentLocationId.value) {
getOrderList(currentLocationId.value);
}
};
// 获取订货单列表
const getOrderList = async (locationId) => {
try {
// 保存当前locationId
currentLocationId.value = locationId;
// 构建请求参数
const requestParams = {
// 仓库ID
locationId: locationId,
// 页码
pageNo: queryParams.value.pageNo,
// 每页条数
pageSize: queryParams.value.pageSize,
// 订单状态 3 :审核通过
statusEnum: 3,
};
const res = await getPurchaseOrderList(requestParams);
if (res.data.records && res.data.records.length > 0) {
// 订货单列表
orderList.value = res.data.records || [];
// 订货单列表总条数
localTableDataTotal.value = res.data.total;
} else {
proxy.$message.error('获取订货单列表失败');
}
} catch (error) {
console.error('获取订货单列表失败:', error);
}
};
// 重置所有数据
const resetAllData = () => {
// 重置分页参数
queryParams.value.pageNo = 1;
queryParams.value.pageSize = 10;
currentLocationId.value = undefined;
orderList.value = [];
localTableDataTotal.value = 0;
};
// 提交数据
const handleSubmit = async () => {
// 取消按钮
handleCancel();
// 获取当前进货单的订单列表
await getCurrentOrderDetail();
// 传递数据给父组件
emit('updateTableData', {
currentOrderList: setCurrentOrderList.value,
currentOrderForm: setCurrentOrderForm.value,
});
};
// 设置当前进货单的订单列表
const setCurrentOrderList = ref([]);
// 设置当前进货单的订单表单
const setCurrentOrderForm = ref({});
// 获取当前进货单的订单列表
const getCurrentOrderDetail = async () => {
const res = await getPurchaseOrderDetail({ busNo: currentRow.value.supplyBusNo });
// 构建编辑后的表单数据
buildEditForm(res.data.records);
};
// 构建编辑后的表单数据
const buildEditForm = (data) => {
// 构建表格数据
if (data.length > 0) {
// 表单数据
setCurrentOrderForm.value = {
// 供应商
supplierId: data[0].supplierId,
// 供应商联系人
phone: data[0].phone,
// 采购员
practitionerId: data[0].applicantId,
};
// 表格数据
data.forEach((item) => {
// 表格编辑状态
item.isEditing = true;
// 表格查看状态
item.isViewing = false;
// 判断当前单位是否是最大单位
buildPrice(item);
// 构建单位列表
buildUnitList(item);
});
// 更新表格数据
setCurrentOrderList.value = data;
}
};
// 构建进货价和销售价
const buildPrice = (item) => {
// 判断当前单位是最大单位还是最小单位
const isMaxUnit = item.unitCode === item.maxUnitCode;
if (isMaxUnit) {
// 进货价
item.price = item.price;
item.priceMaxUnit = item.price;
item.priceMinUnit = item.price / parseInt(item.partPercent);
// 销售价
item.retailPrice = item.retailPrice;
item.retailPriceMaxUnit = item.retailPrice;
item.retailPriceMinUnit = (parseFloat(item.retailPrice) / parseInt(item.partPercent)).toFixed(
2
);
} else {
// 进货价
item.price = item.price;
item.priceMaxUnit = parseFloat((item.price * parseInt(item.partPercent)).toFixed(2));
item.priceMinUnit = item.price;
// 销售价
item.retailPrice = item.retailPrice;
item.retailPriceMaxUnit = parseFloat(
(item.retailPrice * parseInt(item.partPercent)).toFixed(2)
);
item.retailPriceMinUnit = item.retailPrice;
}
};
// 构建单位列表
const buildUnitList = (item) => {
// 表格单位列表
(item.unitList || []).forEach((unit) => {
// 判断当前单位是最大单位还是最小单位
const isMaxUnit = unit.value === item.maxUnitCode;
const isMinUnit = unit.value === item.minUnitCode;
// // 进货价(假)
unit.priceMask = item.price;
// 销售价(假)
unit.retailPriceMask = item.retailPrice;
// 进价金额(假)
unit.totalPriceMask = (parseFloat(item.price) * parseFloat(item.itemQuantity)).toFixed(2);
// 销售金额(假)
unit.totalRetailPriceMask = (
parseFloat(item.retailPrice) * parseFloat(item.itemQuantity)
).toFixed(2);
// 规格库存
unit.specificationInventoryOriginal = item.specificationInventory;
// 规格库存显示逻辑
if (isMaxUnit) {
// 最大单位:显示为 "X盒"
unit.specificationInventoryMax = Math.floor(
item.specificationInventory / parseInt(item.partPercent)
);
unit.specificationInventoryMaxUnit =
unit.specificationInventoryMax > 0 ? item.maxUnitCode_dictText : '';
unit.specificationInventoryMin = item.specificationInventory % parseInt(item.partPercent);
unit.specificationInventoryMinUnit =
unit.specificationInventoryMin > 0 ? item.minUnitCode_dictText : '';
// 批次库存
unit.batchInventoryMax = Math.floor(item.batchInventory / parseInt(item.partPercent));
unit.batchInventoryMaxUnit = unit.batchInventoryMax > 0 ? item.maxUnitCode_dictText : '';
unit.batchInventoryMin = item.batchInventory % parseInt(item.partPercent);
unit.batchInventoryMinUnit = unit.batchInventoryMin > 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 : '';
// 批次库存
unit.batchInventoryMax = item.batchInventory;
unit.batchInventoryMaxUnit = unit.batchInventoryMax > 0 ? item.minUnitCode_dictText : '';
unit.batchInventoryMin = 0;
unit.batchInventoryMinUnit = unit.batchInventoryMin > 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 : '';
// 批次库存
unit.batchInventoryMax = item.batchInventory;
unit.batchInventoryMaxUnit = unit.batchInventoryMax > 0 ? item.minUnitCode_dictText : '';
unit.batchInventoryMin = 0;
unit.batchInventoryMinUnit = unit.batchInventoryMin > 0 ? item.minUnitCode_dictText : '';
}
});
};
// 取消按钮
const handleCancel = () => {
emit('dialogCancel', {
dialogVisible: false,
});
};
defineOptions({
name: 'orderDialog',
});
defineExpose({
getOrderList,
});
</script>
<style>
</style>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,65 @@
import request from '@/utils/request';
// 药房请领单单初始化
export function getInit () {
return request ({
url: '/pharmacy-dispensary/transferIn-order/init',
method: 'get',
});
}
// 请领单单据列表:显示所有单据 左边框
export function getOrderList (query) {
return request ({
url: '/pharmacy-dispensary/transferIn-order/transferIn-order-page',
method: 'get',
params: query,
});
}
// 根据供应商获取药品:对应添加/编辑时加下一行数据后,点击项目时调用的接口
export function getMedicineList (query) {
return request ({
url: '/pharmacy-dispensary/transferIn-order/medication-info',
method: 'get',
params: query,
});
}
// 获取单据号:添加时,获取新单据号。编辑的逻辑是先删除后新增。
export function getBusNo () {
return request ({
url: '/pharmacy-dispensary/transferIn-order/busNo-init',
method: 'get',
});
}
// 添加/编辑采购单:添加/编辑采购单
export function addOrEditOrder (data) {
return request ({
url: '/pharmacy-dispensary/transferIn-order/addOrEdit-transferInOrder',
method: 'PUT',
data,
});
}
// 删除单据
export function deleteOrder (data) {
return request ({
url: '/pharmacy-dispensary/transferIn-order/delete-transferInOrder?busNo=' +
data,
method: 'DELETE',
});
}
// 同意审批
export function agreeApproval (data) {
return request ({
url: '/pharmacy-dispensary/transferIn-order/agree-approval?busNo=' + data,
method: 'PUT',
});
}
// 获取单据详情
export function getOrderDetail (query) {
return request ({
url: '/pharmacy-dispensary/transferIn-order/transferIn-order-detail-page',
method: 'GET',
params: query,
});
}

View File

@@ -0,0 +1,79 @@
<template>
<div>
<el-table ref="medicineRef" height="400" :data="medicineList" @cell-click="clickRow">
<el-table-column label="项目编码" align="center" prop="busNo" width="150" />
<el-table-column label="项目名称" align="center" prop="name" width="180" />
<el-table-column label="进货价" align="center" prop="price" />
<el-table-column label="零售价" align="center" prop="retailPrice" />
<el-table-column label="包装单位" align="center" prop="unitCode_dictText" />
<el-table-column label="最小单位" align="center" prop="minUnitCode_dictText" />
<el-table-column label="规格" align="center" prop="totalVolume" />
<el-table-column label="规格库存" align="center" prop="specificationInventory" />
<el-table-column label="生产厂家" align="center" prop="manufacturerText" />
<el-table-column label="批准文号" align="center" prop="approvalNumber" />
</el-table>
</div>
</template>
<script setup>
import { getMedicineList } from './api';
import { watch } from 'vue';
import { throttle } from 'lodash-es';
const props = defineProps({
searchKey: {
type: String,
default: '',
},
});
// 选择药品
const emit = defineEmits(['selectRow']);
//
const queryParams = ref({
pageNum: 1,
pageSize: 50,
searchKey: props.searchKey,
// 13 药品
typeEnum: 13,
});
// 药品列表
const medicineList = ref([]);
// 节流函数
const throttledGetList = throttle(
() => {
getList();
},
300,
{ leading: true, trailing: true }
);
// 获取药品列表
const getList = (query) => {
getMedicineList(query || queryParams.value).then((res) => {
medicineList.value = res.data.records;
});
};
// 点击行
const clickRow = (row) => {
// console.log(row, 'row');
emit('selectRow', row);
};
// 监听搜索关键字
watch(
() => props,
(newValue) => {
queryParams.value.searchKey = newValue.searchKey;
throttledGetList();
},
{ immdiate: true, deep: true }
);
// 获取药品列表
getList();
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,997 @@
<!-- 药库订货单 -->
<template>
<div class="medicine-container app-container">
<!-- 顶部按钮 -->
<el-row :gutter="20" :xs="24" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
icon="Plus"
plain
@click="handleAdd"
:disabled="isAddDisabled"
v-hasPermi="['pharmacy-warehouse:purchase-order:add']"
>
新增
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
icon="Delete"
plain
@click="handleDelete"
:disabled="isDeleteDisabled"
v-hasPermi="['pharmacy-warehouse:purchase-order:delete']"
>
删除
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
icon="Close"
plain
@click="handleCancel"
:disabled="isCancelDisabled"
v-hasPermi="['pharmacy-warehouse:purchase-order:cancel']"
>
取消
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
icon="Check"
plain
@click="handleAudit"
:disabled="isAuditDisabled"
v-hasPermi="['pharmacy-warehouse:purchase-order:audit']"
>
审核
</el-button>
</el-col>
</el-row>
<el-row :gutter="20" :xs="24">
<!-- 左侧搜索 -->
<el-col :span="4" style="border: 1px solid #ebeef5; height: calc(100vh - 200px)">
<el-row :gutter="10" style="margin-top: 10px">
<el-col :span="24">
<el-form ref="tableFormRef" :model="tableForm" style="width: 100%" :rules="rules">
<el-form-item label="库房:" label-width="100px">
<el-select
v-model="tableForm.locationId"
placeholder="请选择库房"
clearable
filterable
@change="handleLocationChange(tableForm.locationId)"
>
<el-option
v-for="item in cabinetListOptions"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-form>
</el-col>
</el-row>
<el-row :gutter="10">
<el-form
ref="queryParamsRef"
:model="queryParams"
style="width: 100%"
:rules="rules"
@submit.prevent
>
<el-form-item label="单据搜索" label-width="100px">
<el-input
v-model="queryParams.searchKey"
placeholder="请输入单据号"
@keyup.enter="getList"
clearable
>
<template #append>
<el-button icon="Search" @click="getList" />
</template>
</el-input>
</el-form-item>
</el-form>
</el-row>
<el-row :gutter="10" :xs="24">
<el-scrollbar height="calc(100vh - 350px)" style="width: 100%">
<div class="order-list-container">
<!-- 有数据时显示列表 -->
<template v-if="orderList.length > 0">
<div
v-for="item in orderList"
:key="item.supplyBusNo"
:class="['order-item', { 'is-active': selectedOrder === item }]"
@click="handleOrderClick(item)"
>
<el-card class="order-card" shadow="hover">
<div class="order-header">
<div class="order-number">
<el-icon><Document /></el-icon>
<span class="number-text">{{ item.supplyBusNo }}</span>
</div>
</div>
<div class="order-content">
<div class="info-item">
<el-icon class="info-icon"><User /></el-icon>
<span class="label">采购员</span>
<span class="value">{{ item.applicantId_dictText }}</span>
</div>
<div class="info-item">
<el-icon class="info-icon"><Shop /></el-icon>
<span class="label">供应商</span>
<span class="value">{{ item.supplierId_dictText }}</span>
</div>
<div class="info-item">
<el-icon class="info-icon"><User /></el-icon>
<span class="label">审核状态</span>
<el-tag type="success" v-if="item.statusEnum_enumText === '同意'">
{{ item.statusEnum_enumText }}
</el-tag>
<el-tag type="danger" v-else>
{{ item.statusEnum_enumText }}
</el-tag>
</div>
<div class="info-item">
<el-icon class="info-icon"><Files /></el-icon>
<span class="label">单据类型</span>
<span class="value">{{ item.typeEnum_enumText }}</span>
</div>
<div class="info-item">
<el-icon class="info-icon"><Calendar /></el-icon>
<span class="label">单据日期</span>
<span class="value">{{
parseTime(item.applyTime, '{y}-{m}-{d} {h}:{i}:{s}')
}}</span>
</div>
</div>
</el-card>
</div>
</template>
<!-- 空状态显示 -->
<div v-else class="empty-state">
<el-empty description="暂无单据" :image-size="80">
<el-button type="primary" @click="handleAdd"> 新增单据 </el-button>
</el-empty>
</div>
</div>
</el-scrollbar>
</el-row>
</el-col>
<!-- 右侧表格 -->
<el-col :span="20">
<el-row :gutter="10">
<el-col :span="24">
<orderTable
ref="orderTableRef"
:form="tableForm"
:table-data="tableData"
:audit-form="auditForm"
:table-data-total="tableDataTotal"
:is-add-or-edit-order="isAddOrEditOrder"
:supplier-option="supplierOption"
:supply-type-options="supplyTypeOptions"
:supply-status-options="supplyStatusOptions"
:supply-category-options="supplyCategoryOptions"
:practitioner-option="practitionerOption"
:button-show="buttonShow"
@update:query-params="handleQueryParamsUpdate"
@update:form="handleFormUpdate"
@clearForm="clearForm"
@getList="getList"
@updateButtonState="handleUpdateButtonState"
>
</orderTable>
</el-col>
</el-row>
</el-col>
</el-row>
</div>
</template>
<script setup>
import { ref, onMounted, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import orderTable from './components/orderTable.vue';
import {
getInit,
getOrderList,
deleteOrder,
agreeApproval,
getOrderDetail,
} from './components/api';
import useUserStore from '@/store/modules/user';
import { parseTime } from '@/utils/his';
const route = useRoute();
const router = useRouter();
// 获取 pinia 中用户信息
const userInfo = useUserStore();
// 左侧查询参数
const queryParams = ref({
searchKey: '',
});
// 获取当前实例
const { proxy } = getCurrentInstance();
// 右侧表格查询参数 + 分页参数 + 添加查询参数
const tableForm = ref({
locationId: undefined,
busNo: undefined,
applyTime: undefined,
applicantId: undefined,
reason: undefined,
categoryEnum: undefined,
supplierId: undefined,
pageNo: 1,
pageSize: 10,
});
// 右侧表格数据
const tableData = ref([]);
// 右侧审核表单
const auditForm = ref({
approvalTime: undefined,
statusEnum: undefined,
statusEnum_enumText: undefined,
approverId: undefined,
});
// 订单编辑还是新增
const isAddOrEditOrder = ref({
isAddOrder: false,
isEditOrder: false,
});
// 仓库列表 cabinetList
const cabinetListOptions = ref([]);
// 查询经手人列表 practitionerOption
const practitionerOption = ref([]);
// 查询供应商列表 supplierOption
const supplierOption = ref([]);
// 审批状态 supplyStatusOptions
const supplyStatusOptions = ref([]);
// 单据类型 supplyTypeOptions
const supplyTypeOptions = ref([]);
// 单据分类 supplyCategoryOptions
const supplyCategoryOptions = ref([]);
// 订货单单据列表 orderList
const orderList = ref([]);
// 订货单单据列表总条数
const tableDataTotal = ref(0);
// 选中的单据ID
const selectedOrder = ref(null);
// 是否禁用新增按钮
const isAddDisabled = ref(false);
// 是否禁用编辑按钮
const isEditDisabled = ref(true);
// 是否禁用取消按钮
const isCancelDisabled = ref(true);
// 是否禁用删除按钮
const isDeleteDisabled = ref(true);
// 是否禁用审核按钮
const isAuditDisabled = ref(true);
// 按钮显示 buttonShow
const buttonShow = ref({
isAddShow: false,
isDeleteShow: false,
isSaveShow: false,
isEditShow: false,
});
const rules = ref({
locationId: [{ required: true, message: '请选择库房', trigger: 'blur' }],
});
// 初始化 获取下拉列表
const init = async () => {
const res = await getInit();
// 仓库列表 cabinetListOptions
cabinetListOptions.value = res.data.cabinetListOptions;
// 查询经手人列表 practitionerList
practitionerOption.value = res.data.practitionerOption;
// 查询供应商列表 supplierOption
supplierOption.value = res.data.supplierOption;
// 审批状态 supplyStatusOptions
supplyStatusOptions.value = res.data.supplyStatusOptions;
// 单据类型 supplyTypeOptions
supplyTypeOptions.value = res.data.supplyTypeOptions;
// 单据分类
supplyCategoryOptions.value = res.data.supplyCategoryOptions;
};
// 获取订货单单据列表
const getList = async () => {
const res = await getOrderList(queryParams.value);
// 订货单单据列表 orderList
orderList.value = res.data.records;
};
// 新增按钮
const handleAdd = async () => {
// 清空当前表格数据 和 选中状态
resetFormAndTableData();
// 校验库房ID
if (!tableForm.value.locationId) {
proxy.$modal.msgWarning('新增单据前,请选择库房');
return;
}
// 右侧表单数据
tableForm.value = {
// 采购员
applicantId: userInfo.practitionerId,
// 单据日期
applyTime: parseTime(new Date(), '{y}-{m}-{d} {h}:{i}:{s}'),
// 库房ID
locationId: tableForm.value.locationId,
};
// 订单编辑还是新增
isAddOrEditOrder.value = {
isAddOrder: true,
isEditOrder: false,
};
// 延迟执行
nextTick(() => {
// 更新按钮状态为编辑模式
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: false,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: true,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: true,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: true,
});
});
};
// 清空当前表格数据
const resetFormAndTableData = () => {
// 清空右侧表格数据
tableData.value = [];
// 清空审核表单数据
auditForm.value = {};
// 清空右侧表格数据总条数
tableDataTotal.value = 0;
};
// 编辑按钮
const handleEdit = async (order) => {
// 清空当前表格数据 和 选中状态
resetFormAndTableData();
if (!selectedOrder.value) {
proxy.$modal.msgError('请选择要编辑的单据');
return;
}
const res = await getOrderDetail({
busNo: selectedOrder.value.supplyBusNo,
pageNo: tableForm.value.pageNo,
pageSize: tableForm.value.pageSize,
});
// 构建编辑后的表单数据
buildEditForm(res.data.records);
// 更新表格数据总条数
tableDataTotal.value = res.data.total;
// 根据订单状态更新按钮状态
const isApproved = order.statusEnum_enumText === '同意' || order.statusEnum === 3;
if (isApproved) {
// 设置编辑状态
isAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: false,
};
// 更新按钮状态为初始状态
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: true,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: false,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: false,
});
return;
}
// 设置编辑状态
isAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: true,
};
// 更新按钮状态
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: isApproved,
// 取消 按钮禁用
isCancelDisabled: false,
// 删除 按钮禁用
isDeleteDisabled: isApproved,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: !isApproved,
// 删除行 按钮显示
isDeleteShow: !isApproved,
// 保存行 按钮显示
isSaveShow: !isApproved,
// 编辑行 按钮显示
isEditShow: !isApproved,
// 警戒订货 按钮显示
isAlertShow: !isApproved,
});
};
// 构建单位列表
const buildUnitList = (item) => {
// 表格单位列表
(item.unitList || []).forEach((unit) => {
// 判断当前单位是最大单位还是最小单位
const isMaxUnit = unit.value === item.maxUnitCode;
const isMinUnit = unit.value === item.minUnitCode;
// 进货价(假)
if (isMaxUnit) {
unit.priceMask = item.price;
} else {
unit.priceMask = item.price / parseInt(item.partPercent);
}
// 销售价(假)
if (isMaxUnit) {
unit.retailPriceMask = item.retailPrice;
} else {
unit.retailPriceMask = item.retailPrice / parseInt(item.partPercent);
}
// 进价金额(假)
unit.totalPriceMask = (parseFloat(item.price) * parseFloat(item.itemQuantity)).toFixed(2);
// 销售金额(假)
unit.totalRetailPriceMask = (
parseFloat(item.retailPrice) * parseFloat(item.itemQuantity)
).toFixed(2);
// 规格库存
unit.specificationInventoryOriginal = item.specificationInventory;
// 规格库存显示逻辑
if (isMaxUnit) {
// 最大单位:显示为 "X盒"
unit.specificationInventoryMax = Math.floor(
item.specificationInventory / parseInt(item.partPercent)
);
unit.specificationInventoryMaxUnit =
unit.specificationInventoryMax > 0 ? item.maxUnitCode_dictText : '';
unit.specificationInventoryMin = item.specificationInventory % parseInt(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 buildEditForm = (data) => {
// 构建表格数据
if (data.length > 0) {
// 表单数据
tableForm.value = {
// 单据号
busNo: data[0].busNo,
// 单据日期
applyTime: data[0].applyTime,
// 供应商
supplierId: data[0].supplierId,
// 采购员
applicantId: data[0].applicantId,
// 单据类型
categoryEnum: data[0].categoryEnum,
// 摘要
reason: data[0].reason,
// 仓库
locationId: data[0].purposeLocationId,
};
// 表格数据
data.forEach((item) => {
// 表格编辑状态
item.isEditing = false;
// 表格查看状态
item.isViewing = true;
// 构建单位列表
buildUnitList(item);
});
// 更新表格数据
tableData.value = data;
// 审核表格数据
auditForm.value = {
// 审核时间
approvalTime: data[0].approvalTime,
// 审核状态
statusEnum: data[0].statusEnum,
// 审核状态文本
statusEnum_enumText: data[0].statusEnum_enumText,
// 审核人
approverId: data[0].approverId,
};
// 订单编辑还是新增
isAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: true,
};
}
};
// 取消按钮
const handleCancel = () => {
// 更新按钮状态为初始状态
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: true,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: false,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: false,
});
// 清空表单
clearForm();
};
// 清空表单
const clearForm = () => {
// 清空表单数据
tableForm.value = {};
tableData.value = [];
// 清空右侧表格数据
proxy.$refs.orderTableRef.resetAllData();
// 重置订单状态
isAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: false,
};
};
// 删除按钮
const handleDelete = async () => {
if (!selectedOrder.value) {
proxy.$modal.msgError('请选择要删除的单据');
return;
}
// 校验是否可以删除(已审批的单据不能删除)
if (selectedOrder.value.statusEnum_enumText === '同意' || selectedOrder.value.statusEnum === 3) {
proxy.$modal.msgError('已审批的单据不能删除');
return;
}
try {
await proxy.$modal.confirm('确认删除该采购单吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
});
// 删除单据
await deleteOrder(selectedOrder.value.supplyBusNo);
proxy.$modal.msgSuccess('删除成功');
// 编辑
handleEdit(selectedOrder.value);
// 清空右侧表格数据
clearForm();
// 重新获取列表 库房ID
await getList(tableForm.value.locationId);
// 清空选中状态
selectedOrder.value = null;
// 更新按钮状态为初始状态
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: true,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: false,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: false,
});
} catch (error) {
if (error !== 'cancel') {
proxy.$modal.msgError('删除失败');
console.error('删除失败:', error);
}
}
};
// 审核按钮
const handleAudit = async () => {
if (!selectedOrder.value) {
proxy.$modal.msgError('请选择要审核的单据');
return;
}
// 校验是否是已审批状态
if (selectedOrder.value.statusEnum_enumText === '同意' || selectedOrder.value.statusEnum === 3) {
proxy.$modal.msgError('该单据已审批,不能重复审批');
return;
}
try {
await proxy.$modal.confirm('确认同意该采购单吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
});
// 同意审批
await agreeApproval(selectedOrder.value.supplyBusNo);
proxy.$modal.msgSuccess('同意审批成功');
// 编辑
handleEdit(selectedOrder.value);
// 清空右侧表格数据
clearForm();
// 重新获取列表 库房ID
await getList(tableForm.value.locationId);
// 清空选中状态
selectedOrder.value = null;
// 更新按钮状态为初始状态
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: true,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: false,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: false,
});
isAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: false,
};
} catch (error) {
if (error !== 'cancel') {
proxy.$modal.msgError('同意审批失败');
console.error('同意审批失败:', error);
}
}
};
// 处理订单点击事件
const handleOrderClick = (order) => {
// 选中订单
selectedOrder.value = order;
// 编辑
handleEdit(order);
};
// 处理查询参数更新
const handleQueryParamsUpdate = (newParams) => {
// 更新右侧表格的分页参数
tableForm.value.pageNo = newParams.pageNo;
tableForm.value.pageSize = newParams.pageSize;
// 如果有选中的订单,重新获取订单详情
if (selectedOrder.value) {
handleEdit(selectedOrder.value);
}
};
//
// 处理库房变化
const handleLocationChange = (locationId) => {
queryParams.value.locationId = locationId;
// 重新获取列表
getList();
};
//
// 处理表单更新
const handleFormUpdate = (newForm) => {
tableForm.value = { ...tableForm.value, ...newForm };
};
// 处理按钮状态更新
const handleUpdateButtonState = (buttonState) => {
// 按钮禁用
// 审核 按钮禁用
isAuditDisabled.value = buttonState.isAuditDisabled;
// 取消 按钮禁用
isCancelDisabled.value = buttonState.isCancelDisabled;
// 删除 按钮禁用
isDeleteDisabled.value = buttonState.isDeleteDisabled;
// 添加 按钮禁用
isAddDisabled.value = buttonState.isAddDisabled;
// 编辑 按钮禁用
isEditDisabled.value = buttonState.isEditDisabled;
// 按钮显示
// 添加行 按钮显示
buttonShow.value.isAddShow = buttonState.isAddShow;
// 删除行 按钮显示
buttonShow.value.isDeleteShow = buttonState.isDeleteShow;
// 保存行 按钮显示
buttonShow.value.isSaveShow = buttonState.isSaveShow;
// 编辑行 按钮显示
buttonShow.value.isEditShow = buttonState.isEditShow;
// 警戒订货 按钮显示
buttonShow.value.isAlertShow = buttonState.isAlertShow;
};
// 监听路由变化
watch(
() => route.query,
async (newQuery) => {
//console.log('路由参数发生变化:', newQuery);
if (newQuery.busNo) {
queryParams.value.searchKey = newQuery.busNo;
await getList();
// 设置选中状态
selectedOrder.value = orderList.value.find((item) => item.supplyBusNo === newQuery.busNo);
// 编辑按钮
handleEdit(selectedOrder.value);
// 清空路由参数
// router.replace({ query: {} });
}
},
{ immediate: true }
);
// 下拉列表初始化
init();
</script>
<style scoped lang="scss">
.medicine-container :deep(.el-row) {
margin-bottom: 10px;
}
.medicine-container :deep(.el-row:last-child) {
margin-bottom: 0;
}
// 订单列表容器
.order-list-container {
width: 100%;
padding: 0;
}
// 订单列表项样式
.order-item {
width: 100%;
cursor: pointer;
transition: all 0.3s ease;
border-radius: 6px;
overflow: hidden;
margin: 4px 0;
&:hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
.order-card {
border-color: #409eff;
}
}
&.is-active {
.order-card {
border-color: #409eff;
background: linear-gradient(135deg, #ecf5ff 0%, #f0f9ff 100%);
}
.order-number .number-text {
color: #409eff;
font-weight: 600;
}
}
}
// 订单卡片样式
.order-card {
border: 1px solid #e4e7ed;
border-radius: 6px;
transition: all 0.3s ease;
background: #fff;
overflow: hidden;
:deep(.el-card__body) {
padding: 12px;
}
}
// 订单头部样式
.order-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
padding-bottom: 8px;
border-bottom: 1px solid #f0f0f0;
}
.order-number {
display: flex;
align-items: center;
gap: 6px;
min-width: 0;
flex: 1;
.el-icon {
color: #409eff;
font-size: 14px;
flex-shrink: 0;
}
.number-text {
font-size: 13px;
font-weight: 500;
color: #303133;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.order-status {
flex-shrink: 0;
.el-tag {
border-radius: 10px;
font-weight: 500;
font-size: 11px;
padding: 2px 6px;
}
}
// 订单内容样式
.order-content {
display: flex;
flex-direction: column;
gap: 4px;
}
.info-item {
display: flex;
align-items: center;
gap: 4px;
padding: 4px 0;
min-width: 0;
.info-icon {
color: #909399;
font-size: 12px;
flex-shrink: 0;
}
.label {
color: #606266;
font-size: 12px;
font-weight: 500;
flex-shrink: 0;
}
.value {
color: #303133;
font-size: 12px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
min-width: 0;
flex: 1;
}
}
// 空状态样式
.empty-state {
display: flex;
justify-content: center;
align-items: center;
height: 200px;
color: #909399;
:deep(.el-empty__description) {
color: #909399;
font-size: 14px;
}
:deep(.el-button) {
margin-top: 16px;
}
}
// 响应式设计
@media (max-width: 768px) {
.order-header {
flex-direction: column;
align-items: flex-start;
gap: 6px;
}
.info-item {
padding: 2px 0;
}
.empty-state {
height: 150px;
}
}
</style>

View File

@@ -0,0 +1,65 @@
import request from '@/utils/request';
// 药房请领单单初始化
export function getInit () {
return request ({
url: '/pharmacy-dispensary/transferOut-order/init',
method: 'get',
});
}
// 请领单单据列表:显示所有单据 左边框
export function getOrderList (query) {
return request ({
url: '/pharmacy-dispensary/transferOut-order/transferOut-order-page',
method: 'get',
params: query,
});
}
// 根据供应商获取药品:对应添加/编辑时加下一行数据后,点击项目时调用的接口
export function getMedicineList (query) {
return request ({
url: '/pharmacy-dispensary/transferOut-order/medication-info',
method: 'get',
params: query,
});
}
// 获取单据号:添加时,获取新单据号。编辑的逻辑是先删除后新增。
export function getBusNo () {
return request ({
url: '/pharmacy-dispensary/transferOut-order/busNo-init',
method: 'get',
});
}
// 添加/编辑采购单:添加/编辑采购单
export function addOrEditOrder (data) {
return request ({
url: '/pharmacy-dispensary/transferOut-order/addOrEdit-transferOutOrder',
method: 'PUT',
data,
});
}
// 删除单据
export function deleteOrder (data) {
return request ({
url: '/pharmacy-dispensary/transferOut-order/delete-transferOutOrder?busNo=' +
data,
method: 'DELETE',
});
}
// 同意审批
export function agreeApproval (data) {
return request ({
url: '/pharmacy-dispensary/transferOut-order/agree-approval?busNo=' + data,
method: 'PUT',
});
}
// 获取单据详情
export function getOrderDetail (query) {
return request ({
url: '/pharmacy-dispensary/transferOut-order/transferOut-order-detail-page',
method: 'GET',
params: query,
});
}

View File

@@ -0,0 +1,79 @@
<template>
<div>
<el-table ref="medicineRef" height="400" :data="medicineList" @cell-click="clickRow">
<el-table-column label="项目编码" align="center" prop="busNo" width="150" />
<el-table-column label="项目名称" align="center" prop="name" width="180" />
<el-table-column label="进货价" align="center" prop="price" />
<el-table-column label="零售价" align="center" prop="retailPrice" />
<el-table-column label="包装单位" align="center" prop="unitCode_dictText" />
<el-table-column label="最小单位" align="center" prop="minUnitCode_dictText" />
<el-table-column label="规格" align="center" prop="totalVolume" />
<el-table-column label="规格库存" align="center" prop="specificationInventory" />
<el-table-column label="生产厂家" align="center" prop="manufacturerText" />
<el-table-column label="批准文号" align="center" prop="approvalNumber" />
</el-table>
</div>
</template>
<script setup>
import { getMedicineList } from './api';
import { watch } from 'vue';
import { throttle } from 'lodash-es';
const props = defineProps({
searchKey: {
type: String,
default: '',
},
});
// 选择药品
const emit = defineEmits(['selectRow']);
//
const queryParams = ref({
pageNum: 1,
pageSize: 50,
searchKey: props.searchKey,
// 13 药品
typeEnum: 13,
});
// 药品列表
const medicineList = ref([]);
// 节流函数
const throttledGetList = throttle(
() => {
getList();
},
300,
{ leading: true, trailing: true }
);
// 获取药品列表
const getList = (query) => {
getMedicineList(query || queryParams.value).then((res) => {
medicineList.value = res.data.records;
});
};
// 点击行
const clickRow = (row) => {
// console.log(row, 'row');
emit('selectRow', row);
};
// 监听搜索关键字
watch(
() => props,
(newValue) => {
queryParams.value.searchKey = newValue.searchKey;
throttledGetList();
},
{ immdiate: true, deep: true }
);
// 获取药品列表
getList();
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,997 @@
<!-- 药库订货单 -->
<template>
<div class="medicine-container app-container">
<!-- 顶部按钮 -->
<el-row :gutter="20" :xs="24" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
icon="Plus"
plain
@click="handleAdd"
:disabled="isAddDisabled"
v-hasPermi="['pharmacy-warehouse:purchase-order:add']"
>
新增
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
icon="Delete"
plain
@click="handleDelete"
:disabled="isDeleteDisabled"
v-hasPermi="['pharmacy-warehouse:purchase-order:delete']"
>
删除
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
icon="Close"
plain
@click="handleCancel"
:disabled="isCancelDisabled"
v-hasPermi="['pharmacy-warehouse:purchase-order:cancel']"
>
取消
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
icon="Check"
plain
@click="handleAudit"
:disabled="isAuditDisabled"
v-hasPermi="['pharmacy-warehouse:purchase-order:audit']"
>
审核
</el-button>
</el-col>
</el-row>
<el-row :gutter="20" :xs="24">
<!-- 左侧搜索 -->
<el-col :span="4" style="border: 1px solid #ebeef5; height: calc(100vh - 200px)">
<el-row :gutter="10" style="margin-top: 10px">
<el-col :span="24">
<el-form ref="tableFormRef" :model="tableForm" style="width: 100%" :rules="rules">
<el-form-item label="库房:" label-width="100px">
<el-select
v-model="tableForm.locationId"
placeholder="请选择库房"
clearable
filterable
@change="handleLocationChange(tableForm.locationId)"
>
<el-option
v-for="item in cabinetListOptions"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-form>
</el-col>
</el-row>
<el-row :gutter="10">
<el-form
ref="queryParamsRef"
:model="queryParams"
style="width: 100%"
:rules="rules"
@submit.prevent
>
<el-form-item label="单据搜索" label-width="100px">
<el-input
v-model="queryParams.searchKey"
placeholder="请输入单据号"
@keyup.enter="getList"
clearable
>
<template #append>
<el-button icon="Search" @click="getList" />
</template>
</el-input>
</el-form-item>
</el-form>
</el-row>
<el-row :gutter="10" :xs="24">
<el-scrollbar height="calc(100vh - 350px)" style="width: 100%">
<div class="order-list-container">
<!-- 有数据时显示列表 -->
<template v-if="orderList.length > 0">
<div
v-for="item in orderList"
:key="item.supplyBusNo"
:class="['order-item', { 'is-active': selectedOrder === item }]"
@click="handleOrderClick(item)"
>
<el-card class="order-card" shadow="hover">
<div class="order-header">
<div class="order-number">
<el-icon><Document /></el-icon>
<span class="number-text">{{ item.supplyBusNo }}</span>
</div>
</div>
<div class="order-content">
<div class="info-item">
<el-icon class="info-icon"><User /></el-icon>
<span class="label">采购员</span>
<span class="value">{{ item.applicantId_dictText }}</span>
</div>
<div class="info-item">
<el-icon class="info-icon"><Shop /></el-icon>
<span class="label">供应商</span>
<span class="value">{{ item.supplierId_dictText }}</span>
</div>
<div class="info-item">
<el-icon class="info-icon"><User /></el-icon>
<span class="label">审核状态</span>
<el-tag type="success" v-if="item.statusEnum_enumText === '同意'">
{{ item.statusEnum_enumText }}
</el-tag>
<el-tag type="danger" v-else>
{{ item.statusEnum_enumText }}
</el-tag>
</div>
<div class="info-item">
<el-icon class="info-icon"><Files /></el-icon>
<span class="label">单据类型</span>
<span class="value">{{ item.typeEnum_enumText }}</span>
</div>
<div class="info-item">
<el-icon class="info-icon"><Calendar /></el-icon>
<span class="label">单据日期</span>
<span class="value">{{
parseTime(item.applyTime, '{y}-{m}-{d} {h}:{i}:{s}')
}}</span>
</div>
</div>
</el-card>
</div>
</template>
<!-- 空状态显示 -->
<div v-else class="empty-state">
<el-empty description="暂无单据" :image-size="80">
<el-button type="primary" @click="handleAdd"> 新增单据 </el-button>
</el-empty>
</div>
</div>
</el-scrollbar>
</el-row>
</el-col>
<!-- 右侧表格 -->
<el-col :span="20">
<el-row :gutter="10">
<el-col :span="24">
<orderTable
ref="orderTableRef"
:form="tableForm"
:table-data="tableData"
:audit-form="auditForm"
:table-data-total="tableDataTotal"
:is-add-or-edit-order="isAddOrEditOrder"
:supplier-option="supplierOption"
:supply-type-options="supplyTypeOptions"
:supply-status-options="supplyStatusOptions"
:supply-category-options="supplyCategoryOptions"
:practitioner-option="practitionerOption"
:button-show="buttonShow"
@update:query-params="handleQueryParamsUpdate"
@update:form="handleFormUpdate"
@clearForm="clearForm"
@getList="getList"
@updateButtonState="handleUpdateButtonState"
>
</orderTable>
</el-col>
</el-row>
</el-col>
</el-row>
</div>
</template>
<script setup>
import { ref, onMounted, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import orderTable from './components/orderTable.vue';
import {
getInit,
getOrderList,
deleteOrder,
agreeApproval,
getOrderDetail,
} from './components/api';
import useUserStore from '@/store/modules/user';
import { parseTime } from '@/utils/his';
const route = useRoute();
const router = useRouter();
// 获取 pinia 中用户信息
const userInfo = useUserStore();
// 左侧查询参数
const queryParams = ref({
searchKey: '',
});
// 获取当前实例
const { proxy } = getCurrentInstance();
// 右侧表格查询参数 + 分页参数 + 添加查询参数
const tableForm = ref({
locationId: undefined,
busNo: undefined,
applyTime: undefined,
applicantId: undefined,
reason: undefined,
categoryEnum: undefined,
supplierId: undefined,
pageNo: 1,
pageSize: 10,
});
// 右侧表格数据
const tableData = ref([]);
// 右侧审核表单
const auditForm = ref({
approvalTime: undefined,
statusEnum: undefined,
statusEnum_enumText: undefined,
approverId: undefined,
});
// 订单编辑还是新增
const isAddOrEditOrder = ref({
isAddOrder: false,
isEditOrder: false,
});
// 仓库列表 cabinetList
const cabinetListOptions = ref([]);
// 查询经手人列表 practitionerOption
const practitionerOption = ref([]);
// 查询供应商列表 supplierOption
const supplierOption = ref([]);
// 审批状态 supplyStatusOptions
const supplyStatusOptions = ref([]);
// 单据类型 supplyTypeOptions
const supplyTypeOptions = ref([]);
// 单据分类 supplyCategoryOptions
const supplyCategoryOptions = ref([]);
// 订货单单据列表 orderList
const orderList = ref([]);
// 订货单单据列表总条数
const tableDataTotal = ref(0);
// 选中的单据ID
const selectedOrder = ref(null);
// 是否禁用新增按钮
const isAddDisabled = ref(false);
// 是否禁用编辑按钮
const isEditDisabled = ref(true);
// 是否禁用取消按钮
const isCancelDisabled = ref(true);
// 是否禁用删除按钮
const isDeleteDisabled = ref(true);
// 是否禁用审核按钮
const isAuditDisabled = ref(true);
// 按钮显示 buttonShow
const buttonShow = ref({
isAddShow: false,
isDeleteShow: false,
isSaveShow: false,
isEditShow: false,
});
const rules = ref({
locationId: [{ required: true, message: '请选择库房', trigger: 'blur' }],
});
// 初始化 获取下拉列表
const init = async () => {
const res = await getInit();
// 仓库列表 cabinetListOptions
cabinetListOptions.value = res.data.cabinetListOptions;
// 查询经手人列表 practitionerList
practitionerOption.value = res.data.practitionerOption;
// 查询供应商列表 supplierOption
supplierOption.value = res.data.supplierOption;
// 审批状态 supplyStatusOptions
supplyStatusOptions.value = res.data.supplyStatusOptions;
// 单据类型 supplyTypeOptions
supplyTypeOptions.value = res.data.supplyTypeOptions;
// 单据分类
supplyCategoryOptions.value = res.data.supplyCategoryOptions;
};
// 获取订货单单据列表
const getList = async () => {
const res = await getOrderList(queryParams.value);
// 订货单单据列表 orderList
orderList.value = res.data.records;
};
// 新增按钮
const handleAdd = async () => {
// 清空当前表格数据 和 选中状态
resetFormAndTableData();
// 校验库房ID
if (!tableForm.value.locationId) {
proxy.$modal.msgWarning('新增单据前,请选择库房');
return;
}
// 右侧表单数据
tableForm.value = {
// 采购员
applicantId: userInfo.practitionerId,
// 单据日期
applyTime: parseTime(new Date(), '{y}-{m}-{d} {h}:{i}:{s}'),
// 库房ID
locationId: tableForm.value.locationId,
};
// 订单编辑还是新增
isAddOrEditOrder.value = {
isAddOrder: true,
isEditOrder: false,
};
// 延迟执行
nextTick(() => {
// 更新按钮状态为编辑模式
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: false,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: true,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: true,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: true,
});
});
};
// 清空当前表格数据
const resetFormAndTableData = () => {
// 清空右侧表格数据
tableData.value = [];
// 清空审核表单数据
auditForm.value = {};
// 清空右侧表格数据总条数
tableDataTotal.value = 0;
};
// 编辑按钮
const handleEdit = async (order) => {
// 清空当前表格数据 和 选中状态
resetFormAndTableData();
if (!selectedOrder.value) {
proxy.$modal.msgError('请选择要编辑的单据');
return;
}
const res = await getOrderDetail({
busNo: selectedOrder.value.supplyBusNo,
pageNo: tableForm.value.pageNo,
pageSize: tableForm.value.pageSize,
});
// 构建编辑后的表单数据
buildEditForm(res.data.records);
// 更新表格数据总条数
tableDataTotal.value = res.data.total;
// 根据订单状态更新按钮状态
const isApproved = order.statusEnum_enumText === '同意' || order.statusEnum === 3;
if (isApproved) {
// 设置编辑状态
isAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: false,
};
// 更新按钮状态为初始状态
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: true,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: false,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: false,
});
return;
}
// 设置编辑状态
isAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: true,
};
// 更新按钮状态
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: isApproved,
// 取消 按钮禁用
isCancelDisabled: false,
// 删除 按钮禁用
isDeleteDisabled: isApproved,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: !isApproved,
// 删除行 按钮显示
isDeleteShow: !isApproved,
// 保存行 按钮显示
isSaveShow: !isApproved,
// 编辑行 按钮显示
isEditShow: !isApproved,
// 警戒订货 按钮显示
isAlertShow: !isApproved,
});
};
// 构建单位列表
const buildUnitList = (item) => {
// 表格单位列表
(item.unitList || []).forEach((unit) => {
// 判断当前单位是最大单位还是最小单位
const isMaxUnit = unit.value === item.maxUnitCode;
const isMinUnit = unit.value === item.minUnitCode;
// 进货价(假)
if (isMaxUnit) {
unit.priceMask = item.price;
} else {
unit.priceMask = item.price / parseInt(item.partPercent);
}
// 销售价(假)
if (isMaxUnit) {
unit.retailPriceMask = item.retailPrice;
} else {
unit.retailPriceMask = item.retailPrice / parseInt(item.partPercent);
}
// 进价金额(假)
unit.totalPriceMask = (parseFloat(item.price) * parseFloat(item.itemQuantity)).toFixed(2);
// 销售金额(假)
unit.totalRetailPriceMask = (
parseFloat(item.retailPrice) * parseFloat(item.itemQuantity)
).toFixed(2);
// 规格库存
unit.specificationInventoryOriginal = item.specificationInventory;
// 规格库存显示逻辑
if (isMaxUnit) {
// 最大单位:显示为 "X盒"
unit.specificationInventoryMax = Math.floor(
item.specificationInventory / parseInt(item.partPercent)
);
unit.specificationInventoryMaxUnit =
unit.specificationInventoryMax > 0 ? item.maxUnitCode_dictText : '';
unit.specificationInventoryMin = item.specificationInventory % parseInt(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 buildEditForm = (data) => {
// 构建表格数据
if (data.length > 0) {
// 表单数据
tableForm.value = {
// 单据号
busNo: data[0].busNo,
// 单据日期
applyTime: data[0].applyTime,
// 供应商
supplierId: data[0].supplierId,
// 采购员
applicantId: data[0].applicantId,
// 单据类型
categoryEnum: data[0].categoryEnum,
// 摘要
reason: data[0].reason,
// 仓库
locationId: data[0].purposeLocationId,
};
// 表格数据
data.forEach((item) => {
// 表格编辑状态
item.isEditing = false;
// 表格查看状态
item.isViewing = true;
// 构建单位列表
buildUnitList(item);
});
// 更新表格数据
tableData.value = data;
// 审核表格数据
auditForm.value = {
// 审核时间
approvalTime: data[0].approvalTime,
// 审核状态
statusEnum: data[0].statusEnum,
// 审核状态文本
statusEnum_enumText: data[0].statusEnum_enumText,
// 审核人
approverId: data[0].approverId,
};
// 订单编辑还是新增
isAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: true,
};
}
};
// 取消按钮
const handleCancel = () => {
// 更新按钮状态为初始状态
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: true,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: false,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: false,
});
// 清空表单
clearForm();
};
// 清空表单
const clearForm = () => {
// 清空表单数据
tableForm.value = {};
tableData.value = [];
// 清空右侧表格数据
proxy.$refs.orderTableRef.resetAllData();
// 重置订单状态
isAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: false,
};
};
// 删除按钮
const handleDelete = async () => {
if (!selectedOrder.value) {
proxy.$modal.msgError('请选择要删除的单据');
return;
}
// 校验是否可以删除(已审批的单据不能删除)
if (selectedOrder.value.statusEnum_enumText === '同意' || selectedOrder.value.statusEnum === 3) {
proxy.$modal.msgError('已审批的单据不能删除');
return;
}
try {
await proxy.$modal.confirm('确认删除该采购单吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
});
// 删除单据
await deleteOrder(selectedOrder.value.supplyBusNo);
proxy.$modal.msgSuccess('删除成功');
// 编辑
handleEdit(selectedOrder.value);
// 清空右侧表格数据
clearForm();
// 重新获取列表 库房ID
await getList(tableForm.value.locationId);
// 清空选中状态
selectedOrder.value = null;
// 更新按钮状态为初始状态
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: true,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: false,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: false,
});
} catch (error) {
if (error !== 'cancel') {
proxy.$modal.msgError('删除失败');
console.error('删除失败:', error);
}
}
};
// 审核按钮
const handleAudit = async () => {
if (!selectedOrder.value) {
proxy.$modal.msgError('请选择要审核的单据');
return;
}
// 校验是否是已审批状态
if (selectedOrder.value.statusEnum_enumText === '同意' || selectedOrder.value.statusEnum === 3) {
proxy.$modal.msgError('该单据已审批,不能重复审批');
return;
}
try {
await proxy.$modal.confirm('确认同意该采购单吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
});
// 同意审批
await agreeApproval(selectedOrder.value.supplyBusNo);
proxy.$modal.msgSuccess('同意审批成功');
// 编辑
handleEdit(selectedOrder.value);
// 清空右侧表格数据
clearForm();
// 重新获取列表 库房ID
await getList(tableForm.value.locationId);
// 清空选中状态
selectedOrder.value = null;
// 更新按钮状态为初始状态
handleUpdateButtonState({
// 审核 按钮禁用
isAuditDisabled: true,
// 取消 按钮禁用
isCancelDisabled: true,
// 删除 按钮禁用
isDeleteDisabled: true,
// 添加 按钮禁用
isAddDisabled: false,
// 编辑 按钮禁用
isEditDisabled: true,
// 添加行 按钮显示
isAddShow: false,
// 删除行 按钮显示
isDeleteShow: false,
// 保存行 按钮显示
isSaveShow: false,
// 编辑行 按钮显示
isEditShow: false,
// 警戒订货 按钮显示
isAlertShow: false,
});
isAddOrEditOrder.value = {
isAddOrder: false,
isEditOrder: false,
};
} catch (error) {
if (error !== 'cancel') {
proxy.$modal.msgError('同意审批失败');
console.error('同意审批失败:', error);
}
}
};
// 处理订单点击事件
const handleOrderClick = (order) => {
// 选中订单
selectedOrder.value = order;
// 编辑
handleEdit(order);
};
// 处理查询参数更新
const handleQueryParamsUpdate = (newParams) => {
// 更新右侧表格的分页参数
tableForm.value.pageNo = newParams.pageNo;
tableForm.value.pageSize = newParams.pageSize;
// 如果有选中的订单,重新获取订单详情
if (selectedOrder.value) {
handleEdit(selectedOrder.value);
}
};
//
// 处理库房变化
const handleLocationChange = (locationId) => {
queryParams.value.locationId = locationId;
// 重新获取列表
getList();
};
//
// 处理表单更新
const handleFormUpdate = (newForm) => {
tableForm.value = { ...tableForm.value, ...newForm };
};
// 处理按钮状态更新
const handleUpdateButtonState = (buttonState) => {
// 按钮禁用
// 审核 按钮禁用
isAuditDisabled.value = buttonState.isAuditDisabled;
// 取消 按钮禁用
isCancelDisabled.value = buttonState.isCancelDisabled;
// 删除 按钮禁用
isDeleteDisabled.value = buttonState.isDeleteDisabled;
// 添加 按钮禁用
isAddDisabled.value = buttonState.isAddDisabled;
// 编辑 按钮禁用
isEditDisabled.value = buttonState.isEditDisabled;
// 按钮显示
// 添加行 按钮显示
buttonShow.value.isAddShow = buttonState.isAddShow;
// 删除行 按钮显示
buttonShow.value.isDeleteShow = buttonState.isDeleteShow;
// 保存行 按钮显示
buttonShow.value.isSaveShow = buttonState.isSaveShow;
// 编辑行 按钮显示
buttonShow.value.isEditShow = buttonState.isEditShow;
// 警戒订货 按钮显示
buttonShow.value.isAlertShow = buttonState.isAlertShow;
};
// 监听路由变化
watch(
() => route.query,
async (newQuery) => {
//console.log('路由参数发生变化:', newQuery);
if (newQuery.busNo) {
queryParams.value.searchKey = newQuery.busNo;
await getList();
// 设置选中状态
selectedOrder.value = orderList.value.find((item) => item.supplyBusNo === newQuery.busNo);
// 编辑按钮
handleEdit(selectedOrder.value);
// 清空路由参数
// router.replace({ query: {} });
}
},
{ immediate: true }
);
// 下拉列表初始化
init();
</script>
<style scoped lang="scss">
.medicine-container :deep(.el-row) {
margin-bottom: 10px;
}
.medicine-container :deep(.el-row:last-child) {
margin-bottom: 0;
}
// 订单列表容器
.order-list-container {
width: 100%;
padding: 0;
}
// 订单列表项样式
.order-item {
width: 100%;
cursor: pointer;
transition: all 0.3s ease;
border-radius: 6px;
overflow: hidden;
margin: 4px 0;
&:hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
.order-card {
border-color: #409eff;
}
}
&.is-active {
.order-card {
border-color: #409eff;
background: linear-gradient(135deg, #ecf5ff 0%, #f0f9ff 100%);
}
.order-number .number-text {
color: #409eff;
font-weight: 600;
}
}
}
// 订单卡片样式
.order-card {
border: 1px solid #e4e7ed;
border-radius: 6px;
transition: all 0.3s ease;
background: #fff;
overflow: hidden;
:deep(.el-card__body) {
padding: 12px;
}
}
// 订单头部样式
.order-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
padding-bottom: 8px;
border-bottom: 1px solid #f0f0f0;
}
.order-number {
display: flex;
align-items: center;
gap: 6px;
min-width: 0;
flex: 1;
.el-icon {
color: #409eff;
font-size: 14px;
flex-shrink: 0;
}
.number-text {
font-size: 13px;
font-weight: 500;
color: #303133;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.order-status {
flex-shrink: 0;
.el-tag {
border-radius: 10px;
font-weight: 500;
font-size: 11px;
padding: 2px 6px;
}
}
// 订单内容样式
.order-content {
display: flex;
flex-direction: column;
gap: 4px;
}
.info-item {
display: flex;
align-items: center;
gap: 4px;
padding: 4px 0;
min-width: 0;
.info-icon {
color: #909399;
font-size: 12px;
flex-shrink: 0;
}
.label {
color: #606266;
font-size: 12px;
font-weight: 500;
flex-shrink: 0;
}
.value {
color: #303133;
font-size: 12px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
min-width: 0;
flex: 1;
}
}
// 空状态样式
.empty-state {
display: flex;
justify-content: center;
align-items: center;
height: 200px;
color: #909399;
:deep(.el-empty__description) {
color: #909399;
font-size: 14px;
}
:deep(.el-button) {
margin-top: 16px;
}
}
// 响应式设计
@media (max-width: 768px) {
.order-header {
flex-direction: column;
align-items: flex-start;
gap: 6px;
}
.info-item {
padding: 2px 0;
}
.empty-state {
height: 150px;
}
}
</style>

View File

@@ -1,11 +1,19 @@
import request from '@/utils/request'
import request from '@/utils/request';
export function listPatient(query) {
return request({
url: '/pharmacy-manage/western-medicine-dispense/encounter-list',
method: 'get',
params: query
})
params: query,
});
}
export function devicePatientList(query) {
return request({
url: '/pharmacy-manage/device-dispense/encounter-list',
method: 'get',
params: query,
});
}
export function devicePatientList(query) {
@@ -20,47 +28,46 @@ export function listInit(query) {
return request({
url: '/pharmacy-manage/western-medicine-dispense/init',
method: 'get',
params: query
})
params: query,
});
}
export function listWesternmedicine(query) {
return request({
url: '/pharmacy-manage/western-medicine-dispense/medicine-order',
method: 'get',
params: query
})
params: query,
});
}
export function updateMedicion(prescriptionList) {
return request({
url: '/pharmacy-manage/western-medicine-dispense/medicine-dispense',
method: 'put',
data: prescriptionList
})
}
return request({
url: '/pharmacy-manage/western-medicine-dispense/medicine-dispense',
method: 'put',
data: prescriptionList,
});
}
export function prepareMedicion(data) {
return request({
url: '/pharmacy-manage/western-medicine-dispense/prepare',
method: 'put',
data: data
})
}
return request({
url: '/pharmacy-manage/western-medicine-dispense/prepare',
method: 'put',
data: data,
});
}
export function backMedicion(data) {
return request({
url: '/pharmacy-manage/western-medicine-dispense/medicine-cancel',
method: 'put',
data: data
})
data: data,
});
}
//扫码枪返回追溯码筛选
export function itemTraceNo(params) {
return request({
url: '/app-common/item-trace-no?traceNoList=' + params,
method: 'get',
})
});
}
/**
@@ -70,8 +77,8 @@ export function getReportRegisterInit(query) {
return request({
url: '/pharmacy-manage/device-dispense/device-order',
method: 'get',
params: query
})
params: query,
});
}
/**
@@ -81,8 +88,8 @@ export function deviceDispense(params) {
return request({
url: '/pharmacy-manage/device-dispense/device-dispense',
method: 'put',
data: params
})
data: params,
});
}
/**
@@ -92,6 +99,27 @@ export function deviceInvalid(data) {
return request({
url: '/pharmacy-manage/device-dispense/device-cancel',
method: 'put',
data: data
})
data: data,
});
}
/**
* 跨批次发药匹配批号
*/
export function medicineMatch(data) {
return request({
url: '/pharmacy-manage/western-medicine-dispense/medicine-match',
method: 'get',
params: data,
});
}
/**
* 根据doctorId查询医生签名
*/
export function getDoctorSignature(query) {
return request({
url: '/app-common/practitioner-signature',
method: 'get',
params: query,
});
}

View File

@@ -33,7 +33,11 @@
"top": 22.5,
"height": 12,
"width": 88.5,
<<<<<<< HEAD
"title": "长春大学医院",
=======
"title": "长春市朝阳区中医院医院",
>>>>>>> v1.3
"coordinateSync": false,
"widthHeightSync": false,
"fontSize": 13.5,
@@ -331,4 +335,8 @@
]
}
]
}
<<<<<<< HEAD
}
=======
}
>>>>>>> v1.3

View File

@@ -37,7 +37,11 @@
"top": 16.5,
"height": 22.5,
"width": 120,
<<<<<<< HEAD
"title": "长春大学医院",
=======
"title": "长春市朝阳区中医院医院",
>>>>>>> v1.3
"coordinateSync": false,
"widthHeightSync": false,
"fontFamily": "Microsoft YaHei",
@@ -636,4 +640,4 @@
]
}
]
}
}

View File

@@ -10,9 +10,9 @@
label-position="right"
style="min-width: 500px"
>
<el-form-item label="患者信息" prop="condition">
<el-form-item label="患者信息" prop="searchKey">
<el-input
v-model="queryParams.condition"
v-model="queryParams.searchKey"
placeholder="请输入姓名/证件号"
clearable
style="width: 160px"
@@ -84,6 +84,7 @@
align="center"
/>
<el-table-column prop="age" label="年龄" width="80" align="center" />
<el-table-column prop="phone" label="电话" width="80" align="center" />
<el-table-column prop="receptionTime" label="就诊日期" align="center">
<template #default="scope">
{{ scope.row.receptionTime ? formatDate(scope.row.receptionTime) : "-" }}
@@ -228,12 +229,15 @@
:data="medicineInfoList"
border
style="width: 100%; height: 65vh; margin-top: 10px"
:row-style="rowStyle"
:span-method="spanMethod"
:cell-class-name="cellClassName"
@select="handleSelectionChange"
@cell-dblclick="handleCellDbClick"
v-loading="loading"
ref="tableRef"
>
<el-table-column type="selection" width="55" align="center" fixed="left" />
<<<<<<< HEAD
<el-table-column
prop="prescriptionNo"
label="处方号"
@@ -247,17 +251,80 @@
width="100"
align="center"
>
=======
<el-table-column prop="prescriptionNo" label="处方号" width="120" align="center" />
<el-table-column prop="conditionName" label="诊断" width="120" align="center" />
<el-table-column prop="medTypeCode_dictText" label="处方类型" width="120" align="center" />
<el-table-column prop="itemName" label="项目名称" width="160" align="center" />
<el-table-column prop="merchandiseName" label="商品名称" width="160" align="center" />
<el-table-column prop="quantity" label="发药数量" width="130" align="center">
<template #default="scope">
<span v-if="!scope.row.isEdit" style="color: red">
{{ scope.row.quantity }}{{ scope.row.unitCode_dictText }}
</span>
<div class="lot-number-container" v-if="scope.row.isEdit">
<el-input-number
v-model="scope.row.quantity"
controls-position="right"
:controls="false"
>
<template #suffix>
<span>{{ scope.row.unitCode_dictText }}</span>
</template>
</el-input-number>
<el-icon
v-if="scope.row.isEdit"
class="editable-icon confirm-icon"
@click="
() => {
handleQuantity(scope.row);
}
"
>
<Select />
</el-icon>
</div>
</template>
</el-table-column>
<el-table-column prop="lotNumber" label="批次号" width="160" align="center">
<template #default="scope">
<span v-if="!scope.row.isEdit">{{ scope.row.lotNumber }}</span>
<div class="lot-number-container" v-if="scope.row.isEdit">
<el-select
v-model="scope.row.lotNumber"
@change="
(value) => {
scope.row.lotNumber = value;
}
"
>
<el-option
v-for="item in scope.row.inventoryDetailList"
:key="item.inventoryId"
:label="formatLotNumberLabel(scope.row, item)"
:value="item.inventoryLotNumber"
@click="validInventory(scope.row, item)"
/>
</el-select>
<el-icon
v-if="getAdjustPriceSwitchState && scope.row.isEdit"
class="editable-icon confirm-icon"
@click="handleQuantity(scope.row)"
>
<Select />
</el-icon>
</div>
</template>
</el-table-column>
<el-table-column prop="statusEnum_enumText" label="发药状态" width="100" align="center">
>>>>>>> v1.3
<template #default="scope">
<el-tag :type="tagType(scope.row.statusEnum)">
{{ scope.row.statusEnum_enumText }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="quantity" label="发药数量" width="100" align="center">
<template #default="scope">
{{ scope.row.quantity }}{{ scope.row.unitCode_dictText }}
</template>
</el-table-column>
<el-table-column prop="dispensePerDuration" label="天数" width="80" align="center" />
<!-- <el-table-column prop="flag" label="组合" width="60" align="center" /> -->
<!-- <el-table-column prop="quantity" label="发药数量" width="100" align="center" /> -->
<el-table-column prop="totalVolume" label="规格" width="100" align="center" />
@@ -295,7 +362,6 @@
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="lotNumber" label="批次号" width="120" align="center" />
<el-table-column
prop="totalPrice"
label="金额"
@@ -312,9 +378,9 @@
align="center"
/>
<el-table-column prop="doctorName" label="开单医生" width="100" align="center" />
<el-table-column prop="conditionName" label="诊断" width="120" align="center" />
<!-- <el-table-column prop="dose" label="剂量" width="100" align="center" /> -->
<el-table-column prop="rateCode" label="频次" width="100" align="center" />
<<<<<<< HEAD
<el-table-column
prop="methodCode_dictText"
label="用法"
@@ -327,6 +393,9 @@
width="80"
align="center"
/>
=======
<el-table-column prop="methodCode_dictText" label="用法" width="100" align="center" />
>>>>>>> v1.3
<el-table-column
label="操作"
align="center"
@@ -338,7 +407,7 @@
<el-button
link
type="primary"
:disabled="scope.row.statusEnum != 2"
:disabled="!(scope.row.statusEnum == 2 || scope.row.statusEnum == 14)"
icon="SuccessFilled"
@click="handleBatch(scope.row)"
>
@@ -404,8 +473,13 @@
</template>
<script setup name="westernmedicine">
<<<<<<< HEAD
import { ref, computed, onMounted, onBeforeMount } from "vue";
import { ElMessage } from "element-plus";
=======
import { ref, computed, onMounted, onBeforeMount, nextTick } from 'vue';
import { ElMessage } from 'element-plus';
>>>>>>> v1.3
import {
listWesternmedicine,
listPatient,
@@ -418,6 +492,7 @@ import {
deviceDispense,
deviceInvalid,
devicePatientList,
<<<<<<< HEAD
} from "./components/api";
import { advicePrint } from "@/api/public";
import { formatDate, formatDateStr } from "@/utils/index";
@@ -426,14 +501,33 @@ import TraceNoDialog from "@/components/OpenHis/TraceNoDialog/index.vue";
// 使用window.hiprint不再从vue-plugin-hiprint导入
import templateJson from "./components/templateJson.json";
import disposalTemplate from "./components/disposalTemplate.json";
=======
medicineMatch,
getDoctorSignature,
} from './components/api';
import { advicePrint, getAdjustPriceSwitchState, lotNumberMatch } from '@/api/public';
import { formatDate, formatDateStr } from '@/utils/index';
import { debounce } from 'lodash-es';
import TraceNoDialog from '@/components/OpenHis/TraceNoDialog/index.vue';
import { hiprint } from 'vue-plugin-hiprint';
// import templateJson from './components/templateJson.json';
import templateJson from '@/components/Print/Pharmacy.json';
import chineseMedicineTemplateJson from '@/components/Print/ChineseMedicinePrescription.json';
import disposalTemplate from './components/disposalTemplate.json';
import { formatInventory } from '../../../utils/his';
>>>>>>> v1.3
const { proxy } = getCurrentInstance();
const showSearch = ref(true);
const total = ref(0);
const markers = ref([]);
const patientList = ref([]);
const medicineInfoList = ref([]);
const departmentList = ref([]);
const dateRange = ref([]);
const dateRange = ref([
proxy.formatDateStr(new Date().setMonth(new Date().getMonth() - 1), 'YYYY-MM-DD'),
proxy.formatDateStr(new Date(), 'YYYY-MM-DD'),
]);
const personInfo = ref([]);
const dispenseStatusOptions = ref([]);
const preparerDoctorOptions = ref([]);
@@ -453,14 +547,19 @@ const traceNoTemp = ref("");
const tcmFlag = ref("0");
const openTraceNo = ref(false);
const isManualSelection = ref(false);
const couldSave = ref(true);
const groups = ref({});
const openTraceNoDialog = ref(false);
<<<<<<< HEAD
const ypName = ref("");
=======
const loading = ref(false);
const adjustPriceSwitchState = ref(false);
const ypName = ref('');
>>>>>>> v1.3
const medicineTotalPrice = ref(0);
const projectTypeCode = ref("2");
const selectedRow = ref(null);
const { proxy } = getCurrentInstance();
const medCategoryCode = ref([
{
label: "西药中成药",
@@ -478,6 +577,7 @@ const data = reactive({
pageNo: 1,
pageSize: 10,
condition: null,
searchKey: '',
departmentId: null,
statusEnum: 3,
classEnum: 2,
@@ -487,7 +587,6 @@ const { queryParams } = toRefs(data);
// 在组件挂载后调用 getList
onMounted(() => {
setDefaultDateRange();
getList();
});
function handleScan() {
@@ -520,6 +619,7 @@ function submit(value) {
}
});
}
<<<<<<< HEAD
// 设置默认日期范围为当天
function setDefaultDateRange() {
const today = new Date();
@@ -540,17 +640,30 @@ function getList() {
if (projectTypeCode.value == 2) {
listPatient(queryParams.value).then((response) => {
console.log("Full response1:", response);
=======
function getList() {
queryParams.value.receptionTimeSTime = dateRange.value[0] + ' 00:00:00';
queryParams.value.receptionTimeETime = dateRange.value[1] + ' 23:59:59';
if (projectTypeCode.value == 2) {
listPatient(queryParams.value).then((response) => {
>>>>>>> v1.3
patientList.value = response.data.records;
total.value = response.data.total;
});
} else if (projectTypeCode.value == 3) {
<<<<<<< HEAD
debugger;
devicePatientList(queryParams.value).then((response) => {
console.log("Full response1:", response);
=======
devicePatientList(queryParams.value).then((response) => {
>>>>>>> v1.3
patientList.value = response.data.records;
total.value = response.data.total;
});
} else {
<<<<<<< HEAD
Promise.all([
listPatient(queryParams.value),
devicePatientList(queryParams.value),
@@ -575,13 +688,38 @@ function getList() {
{ value: null, label: "全部" },
...response.data.departmentOptions,
];
=======
Promise.all([listPatient(queryParams.value), devicePatientList(queryParams.value)]).then(
([patientRes, deviceRes]) => {
// 合并两个接口的数据
const patientRecords = patientRes.data.records || [];
const deviceRecords = deviceRes.data.records || [];
const combinedRecords = [...patientRecords, ...deviceRecords];
// 根据 encounterId 去重
const uniqueRecords = combinedRecords.filter(
(item, index, self) =>
index === self.findIndex((record) => record.encounterId === item.encounterId)
);
patientList.value = uniqueRecords;
// 合并总数量(如果需要精确数量,可能需要后端支持)
total.value = uniqueRecords.length;
}
);
}
listInit().then((response) => {
departmentList.value = [{ value: null, label: '全部' }, ...response.data.departmentOptions];
>>>>>>> v1.3
backReason.value = response.data.notPerformedReasonOptions;
dispenseStatusOptions.value = response.data.dispenseStatusOptions;
preparerDoctorOptions.value = response.data.preparerDoctorOptions;
preparerDoctor.value = preparerDoctorOptions.value[0].value;
});
}
<<<<<<< HEAD
//打印中西药处方
=======
>>>>>>> v1.3
async function printPrescription() {
const selectedRows = tableRef.value.getSelectionRows();
if (selectedRows.length === 0) {
@@ -601,6 +739,7 @@ async function printPrescription() {
groupedRows[prescriptionNo].push(row);
});
<<<<<<< HEAD
console.log("按处方号分组的结果:", groupedRows);
// 如果您需要将分组后的数据转换为数组形式
@@ -1136,6 +1275,109 @@ function confirmPrinter(printData) {
showPrinterDialog.value = false;
window.currentPrintData = null;
}
=======
// 获取所有唯一的doctorId
const uniqueDoctorIds = [...new Set(selectedRows.map((row) => row.doctorId).filter((id) => id))];
console.log('uniqueDoctorIds:', uniqueDoctorIds);
// 获取所有选择数据医生的签名信息
const doctorSignatures = {};
for (const doctorId of uniqueDoctorIds[0]) {
const signatureResult = await getDoctorSignature({ practitionerId: doctorId });
doctorSignatures[doctorId] = signatureResult?.data || '';
}
let requestIds = selectedRows.map((item) => item.requestId).join(',');
const result = [];
advicePrint({
requestIds: requestIds,
isPrescription: projectTypeCode.value == '3' ? undefined : '1',
}).then((res) => {
if (projectTypeCode.value == '3') {
const result = res.data;
const printElements = disposalTemplate;
var hiprintTemplate = new hiprint.PrintTemplate({ template: printElements }); // 定义模板
hiprintTemplate.print2(result, {
height: 210,
width: 148,
});
} else {
// 将adviceItemList中的chineseHerbsDoseQuantity字段合并到selectedRows中
if (res.data.adviceItemList && res.data.adviceItemList.length > 0) {
selectedRows.forEach((row) => {
// 查找匹配的adviceItem
const matchingItem = res.data.adviceItemList.find(
(item) =>
item.itemName === row.itemName &&
item.quantity === row.quantity &&
item.prescriptionNo === row.prescriptionNo
);
// 如果找到匹配项添加chineseHerbsDoseQuantity字段
if (matchingItem && matchingItem.chineseHerbsDoseQuantity !== undefined) {
row.chineseHerbsDoseQuantity = matchingItem.chineseHerbsDoseQuantity;
}
});
}
const groupedRows = {};
selectedRows.forEach((row) => {
const prescriptionNo = row.prescriptionNo;
if (!groupedRows[prescriptionNo]) {
groupedRows[prescriptionNo] = [];
}
row.contractName = res.data.contractName;
groupedRows[prescriptionNo].push(row);
});
// 转换为数组形式
const groupedArray = Object.values(groupedRows);
groupedArray.forEach((item, index) => {
const total = item.reduce((sum, item) => {
return sum + (item.totalPrice || 0);
}, 0);
// 获取该处方对应的医生签名使用处方中第一个项目的doctorId
const prescriptionDoctorId = item[0]?.doctorId;
const doctorSignature = prescriptionDoctorId
? doctorSignatures[prescriptionDoctorId] || ''
: '';
result.push({
...res.data,
medTotalAmount: '¥' + total.toFixed(2) + '元',
prescriptionList: item,
// 医生签名图片 - 确保使用处方对应的医生签名
doctorSignature: doctorSignature,
});
});
// 从patientList.value中根据encounterNo查询idCard
result.forEach((item) => {
const encounterNo = item.encounterNo;
const patient = patientList.value.find((p) => p.encounterNo === encounterNo);
if (patient) {
item.idCard = patient.idCard;
}
});
console.log('药房result', result);
// 根据药品分类选择对应的打印模板
const printElements = tcmFlag.value === '1' ? chineseMedicineTemplateJson : templateJson;
var hiprintTemplate = new hiprint.PrintTemplate({ template: printElements }); // 定义模板
hiprintTemplate.print2(result, {
height: 210,
width: 148,
});
// 发送任务到打印机成功
hiprintTemplate.on('printSuccess', function (e) {
console.log('打印成功');
});
// 发送任务到打印机失败
hiprintTemplate.on('printError', function (e) {
console.log('打印失败');
});
}
});
>>>>>>> v1.3
}
// 取消打印机选择
@@ -1145,7 +1387,6 @@ function cancelPrinter() {
}
/** 重置按钮操作 */
function resetQuery() {
setDefaultDateRange();
medicineInfoList.value = [];
personInfo.value = [];
proxy.resetForm("queryRef");
@@ -1162,6 +1403,36 @@ function handleQuery() {
}
queryParams.value.pageNo = 1;
getList();
<<<<<<< HEAD
=======
}
function formatLotNumberLabel(row, item) {
if (row.unitCode == item.maxUnitCode) {
return (
item.inventoryLotNumber +
' 剩余:' +
formatInventory(
item.inventoryQuantity,
item.partPercent,
item.maxUnitCode_dictText,
item.inventoryUnitCode_dictText
) +
' 有效期至:' +
proxy.formatDateStr(item.expirationDate, 'YYYY-MM-DD')
);
} else {
return (
item.inventoryLotNumber +
' ' +
item.inventoryQuantity +
' ' +
item.inventoryUnitCode_dictText +
' 有效期至:' +
proxy.formatDateStr(item.expirationDate, 'YYYY-MM-DD')
);
}
>>>>>>> v1.3
}
function countGroupRows(data) {
@@ -1177,6 +1448,7 @@ function countGroupRows(data) {
return groupCounts;
}
function getRowMarkers(groupCounts, data) {
<<<<<<< HEAD
const markers = new Array(data.length).fill("");
// ✅ 兼容 Map 和普通对象
@@ -1186,6 +1458,10 @@ function getRowMarkers(groupCounts, data) {
: Object.entries(groupCounts);
entries.forEach(([prescriptionNo, groupInfo]) => {
=======
const markers = new Array(data.length).fill('');
groupCounts.forEach((groupInfo, prescriptionNo) => {
>>>>>>> v1.3
const { count, indices } = groupInfo;
if (count === 1) {
@@ -1212,8 +1488,7 @@ function getRowMarkers(groupCounts, data) {
function spanMethod({ row, column, rowIndex, columnIndex }) {
// 定义需要合并的列范围前6列包括selection列
const columnsToMerge = [1, 16]; // 假设selection列是第0列其他列依次是1, 2, 3, 4, 5
console.log(row);
const columnsToMerge = [1, 2, 3, 17]; // 假设selection列是第0列其他列依次是1, 2, 3, 4, 5
// 检查当前列是否在需要合并的列范围内
if (row.prescriptionNo) {
if (columnsToMerge.includes(columnIndex)) {
@@ -1241,6 +1516,26 @@ function spanMethod({ row, column, rowIndex, columnIndex }) {
return [1, 1];
}
// 单元格类名设置
const cellClassName = ({ row, column, rowIndex, columnIndex }) => {
if (columnIndex === 1) {
// 要合并的行数
const sameDeptRows = medicineInfoList.value.filter(
(item) => item.prescriptionNo === row.prescriptionNo
);
// 找到当前行在列表中第一次出现的索引
const firstIndex = medicineInfoList.value.findIndex(
(item) => item.prescriptionNo === row.prescriptionNo
);
// 如果是合并的单元格,添加特殊类名
if (rowIndex === firstIndex && sameDeptRows.length > 1) {
return 'merged-cell colored-cell';
}
}
return '';
};
function handleSelectionChange(selectedRows, currentRow) {
medicineInfoList.value
.filter((item) => {
@@ -1251,6 +1546,15 @@ function handleSelectionChange(selectedRows, currentRow) {
});
}
function handleCellDbClick(row, column, cellValue, event) {
if (
adjustPriceSwitchState.value &&
(column.property == 'lotNumber' || column.property == 'quantity')
) {
row.isEdit = true;
}
}
function formatPrice(row, column, cellValue) {
if (cellValue === null || cellValue === undefined) {
return "0.00 元"; // 如果值为空返回0.00
@@ -1260,7 +1564,11 @@ function formatPrice(row, column, cellValue) {
function tagType(statusEnum) {
if (statusEnum == 2 || statusEnum == 2) {
<<<<<<< HEAD
return "default";
=======
return 'primary';
>>>>>>> v1.3
} else if (statusEnum == 4) {
return "success";
} else if (statusEnum == 5 || statusEnum == 6 || statusEnum == 7) {
@@ -1271,11 +1579,30 @@ function tagType(statusEnum) {
}
function handleCurrentChange(row) {
loading.value = true;
currentRow.value = row; // 更新当前选中行的数据
<<<<<<< HEAD
console.log("当前选中行的数据:", currentRow.value);
=======
>>>>>>> v1.3
currentRow.value.statusEnum = undefined;
currentRow.value.dispenseStatus = queryParams.value.statusEnum;
getMedicineList(row.encounterId);
getAdjustPriceSwitchState().then((res) => {
adjustPriceSwitchState.value = res.data;
if (adjustPriceSwitchState.value) {
lotNumberMatch({ encounterIdList: row.encounterId })
.then((res) => {
if (res.code == 200) {
getMedicineList(row.encounterId);
}
})
.catch(() => {
loading.value = false;
});
} else {
getMedicineList(row.encounterId);
}
});
}
function getMedicineList(encounterId) {
@@ -1313,10 +1640,15 @@ function getMedicineList(encounterId) {
// 处理合并后的数据
processMedicineListData();
loading.value = false;
})
.catch((error) => {
<<<<<<< HEAD
console.error("获取数据失败:", error);
proxy.$modal.msgError("获取数据失败");
=======
proxy.$modal.msgError('获取数据失败');
>>>>>>> v1.3
});
} else if (projectTypeCode.value == 2) {
// 只调用listWesternmedicine接口
@@ -1327,7 +1659,10 @@ function getMedicineList(encounterId) {
statusEnum: queryParams.value.statusEnum,
tcmFlag: tcmFlag.value,
}).then((response) => {
<<<<<<< HEAD
console.log("121212", response);
=======
>>>>>>> v1.3
// personInfo.value = response.data.prescriptionPatientInfoDto;
medicineInfoList.value = Array.isArray(response.data.records)
? response.data.records
@@ -1335,6 +1670,7 @@ function getMedicineList(encounterId) {
// 处理数据
processMedicineListData();
loading.value = false;
});
} else if (projectTypeCode.value == 3) {
// 只调用getReportRegisterInit接口
@@ -1349,6 +1685,7 @@ function getMedicineList(encounterId) {
// 处理数据
processMedicineListData();
loading.value = false;
});
}
}
@@ -1396,7 +1733,6 @@ function processMedicineListData() {
}
function submitMedicine(saveList) {
console.log(saveList);
if (projectTypeCode.value == 1) {
// 根据itemTable分类数据
const deviceList = saveList.filter(
@@ -1421,10 +1757,27 @@ function submitMedicine(saveList) {
);
}
let preparationList = medicineList.filter((item) => {
return item.statusEnum == 2;
}); // 待配药列表
let preparedList = medicineList.filter((item) => {
return item.statusEnum == 14;
}); // 已配药列表
// 如果有药品数据调用prepareMedicion接口
if (medicineList.length > 0) {
if (preparationList.length > 0) {
promises.push(
prepareMedicion(medicineList).then((res) => {
prepareMedicion(preparationList).then((res) => {
if (res.code != 200) {
throw new Error('药品发药失败');
}
return res;
})
);
}
if (preparedList.length > 0) {
promises.push(
updateMedicion(preparedList).then((res) => {
if (res.code != 200) {
throw new Error("药品发药失败");
}
@@ -1437,8 +1790,8 @@ function submitMedicine(saveList) {
Promise.all(promises)
.then(() => {
// 所有发药都成功后,调用更新接口
if (medicineList.length > 0) {
return updateMedicion(medicineList);
if (preparationList.length > 0) {
return updateMedicion(preparationList);
}
})
.then((response) => {
@@ -1447,6 +1800,7 @@ function submitMedicine(saveList) {
getMedicineList(currentRow.value.encounterId);
})
.catch((error) => {
<<<<<<< HEAD
console.error("发药失败:", error);
proxy.$modal.msgError("发药失败: " + error.message);
});
@@ -1459,6 +1813,32 @@ function submitMedicine(saveList) {
});
}
});
=======
proxy.$modal.msgError('发药失败: ' + error.message);
});
} else if (projectTypeCode.value == 2) {
let preparationList = saveList.filter((item) => {
return item.statusEnum == 2;
}); // 待配药列表
let preparedList = saveList.filter((item) => {
return item.statusEnum == 14;
}); // 已配药列表
if (preparedList.length > 0) {
updateMedicion(preparedList).then((response) => {
proxy.$modal.msgSuccess('发药成功');
getMedicineList(currentRow.value.encounterId);
});
} else {
prepareMedicion(preparationList).then((res) => {
if (res.code == 200) {
updateMedicion(preparationList).then((response) => {
proxy.$modal.msgSuccess('发药成功');
getMedicineList(currentRow.value.encounterId);
});
}
});
}
>>>>>>> v1.3
} else {
deviceDispense(saveList).then((res) => {
if (res.code == 200) {
@@ -1468,6 +1848,43 @@ function submitMedicine(saveList) {
});
}
}
// 校验当前批次库存是否充足
function validInventory(row, item) {
// 统一成小单位数量
let quantity = row.quantity;
if (row.unitCode == item.maxUnitCode) {
quantity = quantity * item.partPercent;
}
if (quantity > item.inventoryQuantity) {
proxy.$modal.msgError('当前批次库存不足');
return;
}
}
// 校验输入发药数量是否大于总数量
function handleQuantity(row) {
// 遍历全部药品列表, 计算出与当前行requestId相同的发药数量总数
let totalQuantity = 0;
medicineInfoList.value.forEach((item) => {
if (item.requestId == row.requestId) {
totalQuantity += item.quantity;
}
});
if (totalQuantity > row.requestQuantity) {
couldSave.value = false;
proxy.$modal.msgError('发药数量不能大于总数量');
} else if (totalQuantity < row.requestQuantity) {
couldSave.value = false;
proxy.$modal.msgError('发药数量不能小于总数量');
} else {
couldSave.value = true;
}
if (couldSave.value) {
row.isEdit = false;
}
}
const throttledGetList = debounce(handelTraceNo, 500);
const traceNoInput = debounce(handleTraceNoInput, 500);
@@ -1506,8 +1923,6 @@ function handelTraceNo(value) {
traceNoTemp.value = "";
// let saveValue = value.substring(inputValue.length + 5, value.length);
// inputValue = value;
// console.log(value);
// console.log(saveValue);
// traceNoList.value.push(saveValue);
// traceNo.value = value + '[' + (traceNoList.value.length + 1) + ']' + ' ';
}
@@ -1517,7 +1932,7 @@ function handleBatch(row) {
if (row) {
saveList = medicineInfoList.value
.filter((item) => {
return item.dispenseId === row.dispenseId;
return item.prescriptionNo === row.prescriptionNo;
})
.map((item) => {
return {
@@ -1527,6 +1942,9 @@ function handleBatch(row) {
prescriptionNo: item.prescriptionNo,
preparerId: preparerDoctor.value,
itemTable: item.itemTable,
statusEnum: item.statusEnum,
quantity: item.quantity,
lotNumber: item.lotNumber,
};
});
} else {
@@ -1539,12 +1957,16 @@ function handleBatch(row) {
prescriptionNo: item.prescriptionNo,
preparerId: preparerDoctor.value,
itemTable: item.itemTable,
statusEnum: item.statusEnum,
quantity: item.quantity,
lotNumber: item.lotNumber,
};
});
} else {
proxy.$modal.msgWarning('未选择要发药的项目,请重新选择,发药失败');
return;
}
}
console.log(saveList);
submitMedicine(saveList);
}
@@ -1614,6 +2036,26 @@ function validate() {
width: 74%;
}
/* 表格文字颜色改为纯黑色 */
:deep(.el-table) {
td,
th {
color: #000000 !important;
}
.el-table__cell {
color: #000000 !important;
}
tbody tr td {
color: #000000 !important;
}
thead tr th {
color: #000000 !important;
}
}
:deep(.el-table tbody tr:hover > td) {
background-color: inherit !important;
}
@@ -1624,4 +2066,57 @@ function validate() {
::v-deep.el-textarea .el-textarea__inner {
resize: none !important;
}
/* 添加图标悬停样式 */
.editable-icon {
transition: color 0.3s ease;
}
.editable-icon:hover {
color: #409eff; /* Element Plus 主题色,可根据需要调整 */
cursor: pointer;
}
/* 批次号容器样式 */
.lot-number-container {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
}
/* 确认图标样式 */
.confirm-icon {
transition: color 0.3s ease;
margin-left: 5px;
}
.confirm-icon:hover {
color: #409eff;
cursor: pointer;
}
/* 合并单元格基础样式 */
:deep(.merged-cell) {
text-align: center;
font-weight: bold;
}
/* 变色样式 */
:deep(.colored-cell) {
background-color: #e6f7ff !important; /* 浅蓝色 */
border-left: 3px solid #1890ff !important;
}
::v-deep .el-table--border::after,
::v-deep .el-table--group::after,
::v-deep .el-table::before {
background-color: #dddde0;
}
::v-deep .el-table td,
::v-deep .el-table th.is-leaf {
border-color: #dddde0;
}
::v-deep .el-table--border th,
::v-deep .el-table--border th.gutter:last-of-type {
border-color: #dddde0;
}
</style>