核心升级: - 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端点正常
526 lines
13 KiB
Vue
Executable File
526 lines
13 KiB
Vue
Executable File
<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>
|