Files
his/backup/vxetable-migration-20260602/medicationmanagement/pharmacyReconciliation/index.vue
华佗 1d21661a78 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端点正常
2026-06-04 22:39:49 +08:00

526 lines
13 KiB
Vue
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="app-container">
<!-- 顶部查询条件 -->
<div class="table-header">
<el-select
v-model="searchParams.locationId"
class="table-header-search"
placeholder="请选择库房"
>
<el-option
v-for="item in locationOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-date-picker
v-model="searchParams.startTime"
type="date"
placeholder="选择开始时间"
value-format="YYYY-MM-DD"
style="margin-right: 15px"
/>
<el-date-picker
v-model="searchParams.endTime"
class="table-header-search"
type="date"
placeholder="选择结束时间"
value-format="YYYY-MM-DD"
/>
<el-button
class="table-header-button"
type="primary"
@click="handleSearch"
>
查询
</el-button>
<el-button
class="table-header-button"
@click="resetForm"
>
重置
</el-button>
</div>
<!-- 数据表格 -->
<div class="table-container">
<el-table
v-loading="loading"
:data="reconciliationData"
style="width: 100%"
border
>
<el-table-column
prop="locationId_dictText"
label="库房"
min-width="150"
show-overflow-tooltip
/>
<el-table-column
prop="initialAmount"
label="期初金额"
min-width="160"
align="right"
/>
<el-table-column
prop="finalAmount"
label="期末金额"
min-width="160"
align="right"
>
<template #default="scope">
<div
style="color: dodgerblue;cursor: pointer;"
@click="skipToPage(scope, 1)"
>
{{ scope.row.finalAmount }}
</div>
</template>
</el-table-column>
<el-table-column
prop="expectFinalAmount"
label="预期期末金额"
min-width="160"
align="right"
/>
<el-table-column
prop="offsetAmount"
label="偏移量"
min-width="100"
align="right"
/>
<el-table-column
prop="purchaseInAmount"
label="采购入库金额"
min-width="120"
align="right"
>
<template #default="scope">
<div
style="color: dodgerblue;cursor: pointer;"
@click="skipToPage(scope, 2)"
>
{{ scope.row.purchaseInAmount }}
</div>
</template>
</el-table-column>
<el-table-column
prop="purchaseInNumber"
label="采购入库单据数"
min-width="120"
align="right"
/>
<el-table-column
prop="purchaseReturnAmount"
label="采购出库金额"
min-width="120"
align="right"
>
<template #default="scope">
<div
style="color: dodgerblue;cursor: pointer;"
@click="skipToPage(scope, 3)"
>
{{ scope.row.purchaseReturnAmount }}
</div>
</template>
</el-table-column>
<el-table-column
prop="purchaseReturnNumber"
label="采购出库单据数"
min-width="120"
align="right"
/>
<el-table-column
prop="applyOutAmount"
label="领用出库金额"
min-width="120"
align="right"
>
<template #default="scope">
<div
style="color: dodgerblue;cursor: pointer;"
@click="skipToPage(scope, 4)"
>
{{ scope.row.applyOutAmount }}
</div>
</template>
</el-table-column>
<el-table-column
prop="applyOutNumber"
label="领用出库单据数"
min-width="120"
align="right"
/>
<el-table-column
prop="applyReturnAmount"
label="领用退货金额"
min-width="120"
align="right"
>
<template #default="scope">
<div
style="color: dodgerblue;cursor: pointer;"
@click="skipToPage(scope, 5)"
>
{{ scope.row.applyReturnAmount }}
</div>
</template>
</el-table-column>
<el-table-column
prop="applyReturnNumber"
label="领用退货单据数"
min-width="120"
align="right"
/>
<el-table-column
prop="transferInAmount"
label="调拨入库金额"
min-width="120"
align="right"
>
<template #default="scope">
<div
style="color: dodgerblue;cursor: pointer;"
@click="skipToPage(scope, 6)"
>
{{ scope.row.transferInAmount }}
</div>
</template>
</el-table-column>
<el-table-column
prop="transferInNumber"
label="调拨入库单据数"
min-width="120"
align="right"
/>
<el-table-column
prop="transferOutAmount"
label="调拨出库金额"
min-width="120"
align="right"
>
<template #default="scope">
<div
style="color: dodgerblue;cursor: pointer;"
@click="skipToPage(scope, 10)"
>
{{ scope.row.transferOutAmount }}
</div>
</template>
</el-table-column>
<el-table-column
prop="transferOutNumber"
label="调拨出库单据数"
min-width="120"
align="right"
/>
<el-table-column
prop="checkProfitLossAmount"
label="盘点盈亏金额"
min-width="120"
align="right"
>
<template #default="scope">
<div
style="color: dodgerblue;cursor: pointer;"
@click="skipToPage(scope, 7)"
>
{{ scope.row.checkProfitLossAmount }}
</div>
</template>
</el-table-column>
<el-table-column
prop="checkProfitLossNumber"
label="盘点盈亏单据数"
min-width="120"
align="right"
/>
<el-table-column
prop="lossAmount"
label="报损金额"
min-width="100"
align="right"
>
<template #default="scope">
<div
style="color: dodgerblue;cursor: pointer;"
@click="skipToPage(scope, 8)"
>
{{ scope.row.lossAmount }}
</div>
</template>
</el-table-column>
<el-table-column
prop="lossNumber"
label="报损单据数"
min-width="100"
align="right"
/>
<el-table-column
prop="drugIssueAmount"
label="药品发放金额"
min-width="120"
align="right"
>
<template #default="scope">
<div
style="color: dodgerblue;cursor: pointer;"
@click="skipToPage(scope, 9)"
>
{{ scope.row.drugIssueAmount }}
</div>
</template>
</el-table-column>
</el-table>
</div>
</div>
</template>
<script setup>
import {onMounted, reactive, ref} from 'vue';
import {ElMessage} from 'element-plus';
// 导入路由钩子
import {useRouter} from 'vue-router';
// 假设API模块存在实际项目中需要根据实际情况导入
import {getList, getPharmacyList} from './components/api.js';
// 创建路由实例
const router = useRouter();
// 搜索参数
const searchParams = reactive({
locationId: '',
startTime: '',
endTime: ''
});
// 搜索表单引用
const searchFormRef = ref(null);
// 库房选项
const locationOptions = ref([]);
// 对账数据
const reconciliationData = ref([]);
// 加载状态
const loading = ref(false);
// 格式化金额
const formatMoney = (value) => {
if (value === null || value === undefined) return '0.00';
return Number(value).toFixed(2);
};
// 格式化日期为YYYY-MM-DD
const formatDate = (date) => {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
};
// 设置默认日期范围(今日之前一个月)
const setDefaultDateRange = () => {
const today = new Date();
// 结束时间为昨天
const endDate = new Date(today);
endDate.setDate(today.getDate() - 1);
// 开始时间为一个月前的今天
const startDate = new Date(today);
startDate.setMonth(today.getMonth() - 1);
// 处理月份溢出如1月减1个月变为12月
if (startDate.getMonth() === 11 && today.getMonth() === 0) {
startDate.setFullYear(today.getFullYear() - 1);
}
// 确保日期有效性(处理不同月份天数差异)
const lastDayOfMonth = new Date(startDate.getFullYear(), startDate.getMonth() + 1, 0).getDate();
if (startDate.getDate() > lastDayOfMonth) {
startDate.setDate(lastDayOfMonth);
}
searchParams.startTime = formatDate(startDate);
searchParams.endTime = formatDate(endDate);
};
// 查询数据
const handleSearch = async () => {
try {
loading.value = true;
// 构建查询参数并拼接时间
const params = {
locationId: searchParams.locationId
};
// 处理开始时间,拼接 00:00:00
if (searchParams.startTime) {
params.startTime = searchParams.startTime + ' 00:00:00';
}
// 处理结束时间,拼接 00:00:00
if (searchParams.endTime) {
params.endTime = searchParams.endTime + ' 00:00:00';
}
// 调用API获取数据实际项目中替换为真实API调用
const response = await getList(params);
loading.value = false;
console.log('查询结果:', response)
reconciliationData.value = [];
reconciliationData.value.push(response.data.data)
} catch (error) {
ElMessage.error('获取对账数据失败: ' + (error.message || '未知错误'));
console.error('Failed to get reconciliation data:', error);
} finally {
loading.value = false;
}
};
// 重置表单
const resetForm = () => {
searchFormRef.value?.resetFields();
// 重置后重新设置默认日期范围
setDefaultDateRange();
};
// 获取库房列表
const getLocationList = async () => {
try {
// 调用API获取库房数据实际项目中替换为真实API调用
const response = await getPharmacyList();
locationOptions.value = response.data.locationListOptions || [];
// 默认选择第一个库房
if (locationOptions.value.length > 0) {
searchParams.locationId = locationOptions.value[0].value;
}
handleSearch()
} catch (error) {
ElMessage.error('获取库房数据失败: ' + (error.message || '未知错误'));
console.error('Failed to get location list:', error);
}
};
// 跳转到对应页面的函数
const skipToPage = (records, index) => {
// 获取当前选中的库房ID和日期范围
const { startTime, endTime } = searchParams;
console.log(records.row)
const { locationId } = records.row;
// 根据index跳转到不同页面
let path = '';
switch (index) {
case 1:
path = '/aa/4/chkstockPartDetails'; // 库存
break;
case 2:
path = '/aa/4/purchaseDocumentDetsils'; // 采购入库页
break;
case 3:
path = '/aa/4/purchaseReturnDetsils'; // 采购退货页
break;
case 4:
path = '/aa/4/requisitionDetails'; // 领用出库页
break;
case 5:
path = '/aa/4/returnOrutboundDetails'; // 领用退库页
break;
case 6:
case 10:
path = '/aa/4/transferManagentDetails'; // 调拨页
break;
case 7:
path = '/aa/4/chkstockPartDetails'; // 盘点页
break;
case 8:
path = '/aa/4/lossReportingDetails'; // 报损页
break;
case 9:
path = '/aa/3/medicationDetails'; // 药品发放
break;
default:
ElMessage.warning('无效的页面索引');
return;
}
// 跳转到对应页面并传递参数
if(index === 10) {
router.push({
path: path,
query: {
sourceLocationId: locationId,
occurrenceTimeSTime: startTime,
occurrenceTimeETime: endTime,
}
});
}else if(index ===1) {
router.push({
path: path,
query: {
sourceLocationId: locationId,
time: endTime,
type: '1'
}
});
}else {
router.push({
path: path,
query: {
purposeLocationId: locationId,
occurrenceTimeSTime: startTime,
occurrenceTimeETime: endTime
}
});
}
}
// 组件初始化
onMounted(() => {
// 设置默认日期范围
setDefaultDateRange();
getLocationList();
});
</script>
<style scoped>
.table-header-search {
width: 200px;
float: left;
margin-right: 15px;
}
.table-header {
margin-top: 0px;
margin-bottom: 15px;
overflow: hidden;
}
.table-header-button {
float: right;
margin-left: 10px;
}
.table-container {
background-color: #fff;
padding: 16px;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
overflow-x: auto;
}
.text-red {
color: #f56c6c;
}
.text-green {
color: #67c23a;
}
</style>