feat: Spring Boot 3.5.14 全量升级 + 组件升级
核心升级: - Spring Boot 2.7.18 → 3.5.14 - MyBatis Plus 3.5.5 → 3.5.16 (spring-boot3-starter) - Springdoc 1.8.0 → 2.8.6 (OpenAPI 3) - Flowable 6.8.0 → 7.1.0 - Druid 1.2.x → 1.2.28 (boot3-starter) - kotlin-reflect 1.9.10 → 1.9.25 迁移适配: - javax → jakarta 命名空间 (620+ 文件) - Swagger 注解迁移到 OpenAPI 3 (@Tag/@Schema/@Operation/@Parameter) - Spring Security 6.2 适配 (antMatchers→requestMatchers, EnableMethodSecurity) - Druid 包名迁移 (boot→boot3) - Redis 配置路径迁移 (spring.redis→spring.data.redis) - Flyway 适配 (flyway-database-postgresql) - Flowable 7.x 适配 (MULE_TASK_IMAGE 移除) 修复: - spring-boot-maven-plugin 2.5.15→3.5.14 (SPI服务发现失效) - mybatis-plus-boot-starter 3.5.5→3.5.16 (kotlin-reflect+fastjson2冲突) - Flowable database-schema-update 启用自动建表 验证: 23/23 测试通过, 1374 API端点正常
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
// 获取库房对账列表
|
||||
export function getStoreReconciliationList (query) {
|
||||
return request ({
|
||||
url: '/inventory-manage/dynamic/dynamic-inventory',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 获取库房列表// 药房药库列表
|
||||
export function getPharmacyCabinetList () {
|
||||
return request ({
|
||||
url: '/app-common/pharmacy-cabinet-list',
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
// 查询备份单号
|
||||
export function getBackupList () {
|
||||
return request ({
|
||||
url: '/app-common/backup-list',
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,510 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form
|
||||
ref="queryForm"
|
||||
:model="queryParams"
|
||||
label-width="120px"
|
||||
:inline="true"
|
||||
>
|
||||
<el-form-item
|
||||
label="药品名称/编码/拼音/五笔码"
|
||||
prop="searchKey"
|
||||
label-width="200px"
|
||||
>
|
||||
<el-input
|
||||
v-model="queryParams.searchKey"
|
||||
placeholder="请输入"
|
||||
clearable
|
||||
style="width: 350px"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="期初备份单据号"
|
||||
prop="startBusNo"
|
||||
>
|
||||
<el-select
|
||||
v-model="queryParams.startBusNo"
|
||||
filterable
|
||||
clearable
|
||||
placeholder="请选择"
|
||||
@change="handleQuery"
|
||||
>
|
||||
<el-option
|
||||
v-for="(item, index) in backUpOptions"
|
||||
:key="index"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="期末备份单据号"
|
||||
prop="endBusNo"
|
||||
>
|
||||
<el-select
|
||||
v-model="queryParams.endBusNo"
|
||||
filterable
|
||||
clearable
|
||||
placeholder="请选择"
|
||||
@change="handleQuery"
|
||||
>
|
||||
<el-option
|
||||
v-for="(item, index) in backUpOptions"
|
||||
:key="index"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="库房"
|
||||
prop="locationId"
|
||||
>
|
||||
<el-select
|
||||
v-model="queryParams.locationId"
|
||||
placeholder="请选择库房"
|
||||
filterable
|
||||
clearable
|
||||
@change="handleQuery"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in locationOptions"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="是否发生过业务"
|
||||
prop="isBus"
|
||||
>
|
||||
<el-select
|
||||
v-model="queryParams.isBus"
|
||||
filterable
|
||||
clearable
|
||||
@change="handleQuery"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in [
|
||||
{ id: 1, name: '已发生业务' },
|
||||
{ id: 0, name: '未发生业务' },
|
||||
]"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="是否账平"
|
||||
prop="isBalance"
|
||||
>
|
||||
<el-select
|
||||
v-model="queryParams.isBalance"
|
||||
filterable
|
||||
clearable
|
||||
@change="handleQuery"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in [
|
||||
{ id: 1, name: '已平账' },
|
||||
{ id: 0, name: '未平账' },
|
||||
]"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleQuery"
|
||||
>
|
||||
查询
|
||||
</el-button>
|
||||
<el-button @click="resetQuery">
|
||||
重置
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="tableData"
|
||||
border
|
||||
stripe
|
||||
element-loading-text="数据加载中..."
|
||||
:header-cell-style="{ backgroundColor: '#f5f7fa', color: '#303133' }"
|
||||
empty-text="暂无数据"
|
||||
>
|
||||
<el-table-column
|
||||
type="expand"
|
||||
width="48"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-row
|
||||
:gutter="10"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-form
|
||||
label-width="100px"
|
||||
:inline="true"
|
||||
>
|
||||
<el-form-item
|
||||
label="发药单据数"
|
||||
:class="computedClass(row)"
|
||||
>
|
||||
{{ row.dispenseOrderCount }}
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="退药单据数"
|
||||
:class="computedClass(row)"
|
||||
>
|
||||
{{ row.returnOrderCount }}
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="采购单据数"
|
||||
:class="computedClass(row)"
|
||||
>
|
||||
{{ row.purchaseOrderCount }}
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="退库单据数"
|
||||
:class="computedClass(row)"
|
||||
>
|
||||
{{ row.purchaseReturnOrderCount }}
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="调拨进单据数"
|
||||
:class="computedClass(row)"
|
||||
>
|
||||
{{ row.transferInOrderCount }}
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="调拨出单据数"
|
||||
:class="computedClass(row)"
|
||||
>
|
||||
{{ row.transferOutOrderCount }}
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="报损单据数"
|
||||
:class="computedClass(row)"
|
||||
>
|
||||
{{ row.lossOrderCount }}
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="盘点单据数"
|
||||
:class="computedClass(row)"
|
||||
>
|
||||
{{ row.stocktakeOrderCount }}
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="领用单据数"
|
||||
:class="computedClass(row)"
|
||||
>
|
||||
{{ row.issueOrderCount }}
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="退领单据数"
|
||||
:class="computedClass(row)"
|
||||
>
|
||||
{{ row.returnIssueOrderCount }}
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-row>
|
||||
<el-row
|
||||
:gutter="40"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-col
|
||||
:span="16"
|
||||
class="formula-wrapper"
|
||||
>
|
||||
<div class="formula">
|
||||
<template
|
||||
v-for="segment in balanceSegments"
|
||||
:key="segment.label"
|
||||
>
|
||||
<span
|
||||
v-if="segment.operator"
|
||||
class="formula-operator"
|
||||
>
|
||||
{{ segment.operator }}
|
||||
</span>
|
||||
<span class="formula-label">{{ segment.label }}</span>
|
||||
<span>(</span>
|
||||
<span :class="computedClass(row)">
|
||||
{{ formatInventoryUnit(row[segment.field], row) }}
|
||||
</span>
|
||||
<span>)</span>
|
||||
</template>
|
||||
<span class="formula-operator">=</span>
|
||||
<span class="formula-label">推算期末数</span>
|
||||
<span>(</span>
|
||||
<span :class="computedClass(row)">{{ computedEndNum(row) }}</span>
|
||||
<span>)</span>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col
|
||||
:span="4"
|
||||
class="formula-wrapper"
|
||||
>
|
||||
<span>期末数量</span>
|
||||
<span>(</span>
|
||||
<span :class="computedClass(row)">
|
||||
{{ formatInventoryUnit(row.endCount, row) }}
|
||||
</span>
|
||||
<span>)</span>
|
||||
<span class="formula-operator">-</span>
|
||||
<span>推测期末数量</span>
|
||||
<span>(</span>
|
||||
<span :class="computedClass(row)">{{ computedEndNum(row) }}</span>
|
||||
<span>)</span>
|
||||
<span class="formula-operator">=</span>
|
||||
<span>盈亏数量</span>
|
||||
<span>(</span>
|
||||
<span :class="computedClass(row)">
|
||||
{{ formatInventoryUnit(row.profitLossDiff, row) }}</span>
|
||||
<span>)</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="itemName"
|
||||
label="药品名称"
|
||||
align="center"
|
||||
width="200"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="itemNo"
|
||||
label="项目编号"
|
||||
align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="unitCode_dictText"
|
||||
label="单位"
|
||||
align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="minUnitCode_dictText"
|
||||
label="最小单位"
|
||||
align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="totalVolume"
|
||||
label="规格"
|
||||
align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="categoryCode_dictText"
|
||||
label="药品分类"
|
||||
align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="manufacturerText"
|
||||
label="生产厂家"
|
||||
align="center"
|
||||
width="300"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="partPercent"
|
||||
label="拆零比"
|
||||
align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="isBalance"
|
||||
label="是否账平"
|
||||
align="center"
|
||||
width="100"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-tag
|
||||
v-if="scope.row.isBalance == 1"
|
||||
type="success"
|
||||
>
|
||||
已平账
|
||||
</el-tag>
|
||||
<el-tag
|
||||
v-else-if="scope.row.isBalance == 0"
|
||||
type="danger"
|
||||
>
|
||||
未平账
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
:total="total"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="storeReconciliation">
|
||||
import {onMounted, reactive, ref, watch} from 'vue';
|
||||
import {ElMessage} from 'element-plus';
|
||||
import {getBackupList, getPharmacyCabinetList, getStoreReconciliationList,} from './components/api.js';
|
||||
import {formatInventory} from '@/utils/his.js';
|
||||
|
||||
const loading = ref(false);
|
||||
const total = ref(0);
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
searchKey: '',
|
||||
startBusNo: '',
|
||||
endBusNo: '',
|
||||
locationId: '',
|
||||
isBus: 1,
|
||||
isBalance: 0,
|
||||
});
|
||||
// 获取库存单位
|
||||
function formatInventoryUnit(num, row) {
|
||||
return formatInventory(num, row.partPercent, row.unitCode_dictText, row.minUnitCode_dictText);
|
||||
}
|
||||
// 推算期末数
|
||||
function computedEndNum(row) {
|
||||
if (!row) return '';
|
||||
|
||||
const {
|
||||
startCount = 0,
|
||||
dispenseCount = 0,
|
||||
returnCount = 0,
|
||||
purchaseCount = 0,
|
||||
purchaseReturnCount = 0,
|
||||
transferInCount = 0,
|
||||
transferOutCount = 0,
|
||||
lossCount = 0,
|
||||
stocktakeCount = 0,
|
||||
issueCount = 0,
|
||||
returnIssueCount = 0,
|
||||
} = row;
|
||||
|
||||
const endCount =
|
||||
Number(startCount || 0) -
|
||||
Number(dispenseCount || 0) +
|
||||
Number(returnCount || 0) +
|
||||
Number(purchaseCount || 0) -
|
||||
Number(purchaseReturnCount || 0) +
|
||||
Number(transferInCount || 0) -
|
||||
Number(transferOutCount || 0) -
|
||||
Number(lossCount || 0) +
|
||||
Number(stocktakeCount || 0) -
|
||||
Number(issueCount || 0) +
|
||||
Number(returnIssueCount || 0);
|
||||
|
||||
return formatInventoryUnit(endCount, row);
|
||||
}
|
||||
function computedClass(row) {
|
||||
if (row.isBalance == 1) {
|
||||
return 'label-green';
|
||||
}
|
||||
if (row.isBalance == 0) {
|
||||
return 'label-red';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
// function
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1;
|
||||
getList();
|
||||
};
|
||||
|
||||
const resetQuery = () => {
|
||||
queryParams.locationId = '';
|
||||
queryParams.startBusNo = '';
|
||||
queryParams.endBusNo = '';
|
||||
queryParams.isBus = 1;
|
||||
queryParams.isBalance = 0;
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
const tableData = ref([]);
|
||||
const getList = async () => {
|
||||
const response = await getStoreReconciliationList(queryParams);
|
||||
tableData.value = response?.data?.records || [];
|
||||
total.value = response?.data?.total || 0;
|
||||
};
|
||||
const locationOptions = ref([]);
|
||||
const getLocationList = async () => {
|
||||
try {
|
||||
const response = await getPharmacyCabinetList();
|
||||
locationOptions.value = response?.data || [];
|
||||
queryParams.locationId = response?.data[0].id;
|
||||
} catch (error) {
|
||||
ElMessage.error('获取库房列表失败,请稍后重试');
|
||||
}
|
||||
};
|
||||
const backUpOptions = ref([]);
|
||||
const getBackupOptionsList = async () => {
|
||||
try {
|
||||
const response = await getBackupList();
|
||||
backUpOptions.value = response?.data || [];
|
||||
queryParams.startBusNo = response?.data[backUpOptions.value.length - 1];
|
||||
} catch (error) {
|
||||
ElMessage.error('获取备份单号失败,请稍后重试');
|
||||
}
|
||||
};
|
||||
const balanceSegments = [
|
||||
{ label: '期初数', field: 'startCount', operator: null },
|
||||
{ label: '发药数', field: 'dispenseCount', operator: '-' },
|
||||
{ label: '退药数', field: 'returnCount', operator: '+' },
|
||||
{ label: '入库数', field: 'purchaseCount', operator: '+' },
|
||||
{ label: '退库数', field: 'purchaseReturnCount', operator: '-' },
|
||||
{ label: '调拨进数', field: 'transferInCount', operator: '+' },
|
||||
{ label: '调拨出数', field: 'transferOutCount', operator: '-' },
|
||||
{ label: '报损数', field: 'lossCount', operator: '-' },
|
||||
{ label: '盘点数', field: 'stocktakeCount', operator: '+' },
|
||||
{ label: '领用数', field: 'issueCount', operator: '-' },
|
||||
{ label: '领用退数', field: 'returnIssueCount', operator: '+' },
|
||||
];
|
||||
watch(
|
||||
[() => queryParams.locationId, () => queryParams.startBusNo],
|
||||
([newLocationId, newStartBusNo]) => {
|
||||
if (newLocationId && newStartBusNo) {
|
||||
getList();
|
||||
}
|
||||
}
|
||||
);
|
||||
onMounted(() => {
|
||||
getBackupOptionsList();
|
||||
getLocationList();
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.label-red {
|
||||
color: #f56c6c;
|
||||
}
|
||||
.label-green {
|
||||
color: #67c23a;
|
||||
}
|
||||
.formula-wrapper {
|
||||
margin-top: 8px;
|
||||
margin-left: 12px;
|
||||
}
|
||||
.formula-wrapper span {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.formula {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-size: 14px;
|
||||
line-height: 28px;
|
||||
}
|
||||
.formula-label {
|
||||
font-weight: 500;
|
||||
}
|
||||
.formula-operator {
|
||||
padding: 0 2px;
|
||||
color: #909399;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user