根因: - Bug #请修复 Bug #591 存在的问题 修复: - ### 变更摘要 - 全链路数据流分析**:录取(弹窗输入)→ 保存(API传入)→ 查询(Mapper返回)→ 修改(Service记录)→ 删除/停止(状态变更)→ 关联(列表展示) - ### 后端变更(4个文件) - 1. `AdviceBatchOpParam.java`** — 停嘱参数添加 `stopTime` 字段 - 新增 `@JsonFormat Date stopTime`,支持前端传入停嘱时间 - 2. `RequestBaseDto.java`** — 查询DTO添加 `stopUserName`、`stopTime` 字段 - 新增 `String stopUserName`(停嘱医生姓名) - 新增 `Date stopTime`(停嘱时间) - 3. `AdviceManageAppServiceImpl.java`** — 停嘱Service增强 - 优先使用前端传入的 `stopTime`,兜底用当前时间 - 通过 `SecurityUtils.getNickName()` 获取当前操作用户昵称,记录到 `updateBy` - 药品和诊疗两个更新入口均已同步修改 - 4. `AdviceManageAppMapper.xml`** — 三个UNION ALL子查询添加字段 - 药品子查询:`T1.effective_dose_end AS stop_time` + `T1.update_by AS stop_user_name` - 耗材子查询:`NULL AS stop_time` + `'' AS stop_user_name` - 诊疗子查询:`T1.occurrence_end_time AS stop_time` + `T1.update_by AS stop_user_name` - ### 前端变更(1个文件) - `order/index.vue`**: - 1. **停嘱时间弹窗** — 点击「停嘱」后弹出 `el-dialog`,内含 `el-date-picker`(datetime类型,默认当前时间),确定后才调用API - 2. **表格列** — 在「皮试」列后面、「诊断」列前面新增两列: - 「停嘱医生」`prop="stopUserName"`,宽度120px - 「停嘱时间」`prop="stopTime"`,宽度170px - 3. **`handleStopAdvice`** — 保留原有校验(未保存/未签发/已停止检查),校验通过后弹出时间选择弹窗而非直接调API - 4. **`confirmStopAdvice`** — 新增确认函数,将 `stopTime` 拼入请求参数后调用 `stopAdvice` API - ### 验证结果 - ✅ 前端 Lint 检查通过(仅1个预存的 `vue/no-dupe-keys` 警告) - ✅ 后端 Maven 编译通过(BUILD SUCCESS)
386 lines
11 KiB
Vue
Executable File
386 lines
11 KiB
Vue
Executable File
<template>
|
|
<div>
|
|
<el-dialog
|
|
v-model="localDialogVisible"
|
|
title="订单列表"
|
|
width="960px"
|
|
append-to-body
|
|
@close="resetAllData"
|
|
>
|
|
<el-table
|
|
ref="tableRef"
|
|
:data="orderList"
|
|
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
|
|
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
|
|
v-show="localTableDataTotal > 0"
|
|
: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"
|
|
/>
|
|
</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 {getPurchaseOrderDetail, getPurchaseOrderList} from './api';
|
|
import {getCurrentInstance, ref, watch} 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> |