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:
2026-06-04 22:39:10 +08:00
parent b8d719429d
commit 1d21661a78
781 changed files with 57907 additions and 1301 deletions

View File

@@ -0,0 +1,916 @@
<template>
<div class="app-container">
<el-form
ref="queryRef"
style="margin-top: 20px; margin-left: 20px"
:model="queryParams"
:inline="true"
label-width="90px"
>
<el-form-item label="收费时间:">
<el-date-picker
v-model="occurrenceTime"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
style="width: 300px"
value-format="YYYY-MM-DD"
/>
</el-form-item>
<el-form-item label="统计类型:">
<el-select
v-model="queryParams.statisticsType"
placeholder=""
style="width: 220px"
@change="inventoryChange(queryParams.statisticsType)"
>
<el-option
v-for="supplyStatus in inventoryOptions"
:key="supplyStatus.value"
:label="supplyStatus.label"
:value="supplyStatus.value"
/>
</el-select>
</el-form-item>
<el-form-item
label="科室:"
prop="departmentId"
>
<el-select
v-model="queryParams.departmentId"
placeholder=""
clearable
style="width: 150px"
>
<el-option
v-for="supplyStatus in getDepartmentOptions"
:key="supplyStatus.id"
:label="supplyStatus.name"
:value="supplyStatus.id"
/>
</el-select>
</el-form-item>
<el-form-item
label="开单人:"
prop="issuerId"
>
<el-select
v-model="queryParams.issuerId"
placeholder=""
clearable
style="width: 150px"
>
<el-option
v-for="supplyStatus in issuerOptions"
:key="supplyStatus.id"
:label="supplyStatus.name"
:value="supplyStatus.id"
/>
</el-select>
</el-form-item>
<el-form-item
label="收费人:"
prop="payeeId"
>
<el-select
v-model="queryParams.payeeId"
placeholder=""
clearable
style="width: 150px"
>
<el-option
v-for="supplyStatus in payeeOptions"
:key="supplyStatus.id"
:label="supplyStatus.name"
:value="supplyStatus.id"
/>
</el-select>
</el-form-item>
<el-form-item
label="项目类型:"
prop="clinicalType"
label-width="90px"
>
<el-tree-select
v-model="selectedTypeIds"
:data="clinicalTree"
:props="treeProps"
placeholder="选择项目类型"
clearable
multiple
style="width: 220px"
:filterable="true"
:check-strictly="false"
:collapse-tags="selectedTypeIds.length > 2"
:max-tag-count="3"
:collapse-tags-tooltip="true"
@change="handleTreeChange"
@clear="handleTreeClear"
/>
</el-form-item>
<el-form-item
label="医保号/门诊号/患者姓名/项目名/项目编码"
prop="searchKey"
label-width="295"
>
<el-input
v-model="queryParams.searchKey"
placeholder="输入医保号/门诊号/患者姓名/项目名称/项目编码后回车查询"
clearable
style="width: 395px"
@keyup.enter="handleQuery"
/>
</el-form-item>
</el-form>
<el-row
:gutter="10"
class="mb8"
style="margin-left: 20px; margin-right: 0px; margin-bottom: 5px"
>
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="Search"
@click="handleQuery"
>
查询
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="CircleClose"
@click="handleClear"
>
重置
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="Download"
@click="handleExport"
>
导出
</el-button>
</el-col>
</el-row>
<el-table
v-loading="loading"
style="padding: 0 20px; width: 100%; height: 67vh"
border
stripe
:data="purchaseinventoryList"
:span-method="arraySpanMethod"
@selection-change="handleSelectionChange"
>
<el-table-column
type="selection"
width="50px"
align="center"
/>
<el-table-column
key="busNo"
label="门诊号"
align="center"
min-width="150px"
:show-overflow-tooltip="true"
resizable
>
<template #default="scope">
<el-button
type="text"
@click="handleArchive(scope.row)"
>
{{ scope.row.busNo }}
</el-button>
</template>
</el-table-column>
<el-table-column
key="departmentName"
label="科室"
align="center"
prop="departmentName"
:show-overflow-tooltip="true"
resizable
/>
<el-table-column
key="name"
label="姓名"
align="center"
prop="name"
width="90px"
:show-overflow-tooltip="true"
resizable
/>
<el-table-column
key="ybCode"
label="医保号"
align="center"
prop="ybCode"
min-width="200px"
:show-overflow-tooltip="true"
resizable
/>
<el-table-column
key="clinicalName"
label="药品项目"
align="center"
prop="clinicalName"
:show-overflow-tooltip="true"
resizable
/>
<el-table-column
key="ybNo"
label="医保码"
align="center"
prop="ybNo"
min-width="250px"
:show-overflow-tooltip="true"
resizable
/>
<el-table-column
key="type_dictText"
label="医保类别"
align="center"
prop="type_dictText"
:show-overflow-tooltip="true"
resizable
/>
<el-table-column
key="issuerName"
label="开单人"
align="center"
prop="issuerName"
:show-overflow-tooltip="true"
resizable
/>
<el-table-column
key="payeeName"
label="收费人"
align="center"
prop="payeeName"
:show-overflow-tooltip="true"
resizable
/>
<el-table-column
key="totalVolume"
label="规格"
align="center"
prop="totalVolume"
width="135px"
:show-overflow-tooltip="true"
resizable
/>
<el-table-column
key="number"
label="数量"
align="center"
prop="number"
:show-overflow-tooltip="true"
resizable
/>
<el-table-column
key="price"
label="单价"
align="center"
prop="price"
:show-overflow-tooltip="true"
resizable
>
<template #default="scope">
<span>{{ scope.row.price || scope.row.salePrice || '0.00' }}</span>
</template>
</el-table-column>
<el-table-column
key="totalPrice"
label="金额"
align="center"
prop="totalPrice"
:show-overflow-tooltip="true"
/>
<el-table-column
key="chrgitmLv_enumText"
label="医保等级"
align="center"
prop="chrgitmLv_enumText"
:show-overflow-tooltip="true"
/>
<el-table-column
key="chargeTime"
label="收费时间"
align="center"
prop="chargeTime"
:show-overflow-tooltip="true"
resizable
>
<template #default="scope">
<span>{{ parseTime(scope.row.chargeTime || scope.row.createTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0 && !queryParams.searchKey"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
:total="total"
@pagination="getList(1)"
/>
<el-row
:gutter="10"
class="mb8"
style="
margin-top: 10px;
display: flex;
align-items: center;
justify-content: flex-start;
margin-left: 0px;
margin-right: 0px;
padding: 0 20px;
"
>
<el-col :span="3">
<span>制单人:{{ userStore.name }}</span>
</el-col>
</el-row>
</div>
</template>
<script setup name="outPatientCharge">
import {getDepartmentList, getReportChargeInit, getReportChargePage,} from './statisticalManagent';
import useUserStore from '@/store/modules/user';
import {watch} from 'vue';
const userStore = useUserStore();
const router = useRouter();
const { proxy } = getCurrentInstance();
const totalAmount = ref(0);
const purchaseinventoryListAll = ref([]);
const xiaojiTotal = ref([]);
const rowSpanMap = ref({});
const rowSpan = ref(1);
const issuerOptions = ref([]);
const payeeOptions = ref([]);
const inventoryOptions = ref([]);
const clinicalTypeOptions = ref([]);
const purchaseinventoryList = ref([]);
const loading = ref(true);
const ids = ref([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const occurrenceTime = ref([]);
const getDepartmentOptions = ref([]);
// 树形结构相关变量
const selectedTypeIds = ref([]); // 选中的节点ID集合
const clinicalTree = ref([]); // 树形结构数据
const treeProps = ref({
label: 'label',
value: 'value',
children: 'children',
disabled: 'disabled',
});
// 字典
const { device_category_code, med_category_code, activity_category_code } = proxy.useDict(
'device_category_code',
'med_category_code',
'activity_category_code'
);
const data = reactive({
form: {},
queryParams: {
pageNo: 1,
pageSize: 10,
statisticsType: 1,
searchKey: undefined,
departmentId: undefined,
issuerId: undefined,
payeeId: undefined,
clinicalType: undefined,
medicationCategoryCode: undefined,
deviceCategoryCode: undefined,
activityCategoryCode: undefined,
chargeTimeSTime: undefined,
chargeTimeETime: undefined,
},
rules: {},
});
const { queryParams, form, rules } = toRefs(data);
// 监听表格数据变化计算合计金额
watch(
() => purchaseinventoryList.value,
(newValue) => {
if (newValue && newValue.length > 0) {
handleTotalAmount();
}
},
{ immediate: true }
);
// 监听统计类型变化
watch(
() => queryParams.value.statisticsType,
(newValue) => {
queryParams.value.statisticsType = newValue;
},
{ immediate: true }
);
// 构建树形结构数据
function buildClinicalTree() {
clinicalTree.value = [];
if (!clinicalTypeOptions.value || !Array.isArray(clinicalTypeOptions.value)) {
return;
}
clinicalTypeOptions.value.forEach((topOption) => {
if (!topOption) return;
const rootNode = {
label: topOption.label || '',
value: String(topOption.value),
children: [],
disabled: false,
};
const parentValue = String(topOption.value);
switch (parentValue) {
case '1': // 药品类别
if (med_category_code.value && Array.isArray(med_category_code.value)) {
rootNode.children = med_category_code.value.map((item) => ({
label: item.label || '',
value: `med_${item.value}`,
disabled: false,
}));
}
break;
case '2': // 器械类别
if (device_category_code.value && Array.isArray(device_category_code.value)) {
rootNode.children = device_category_code.value.map((item) => ({
label: item.label || '',
value: `dev_${item.value}`,
disabled: false,
}));
}
break;
case '3': // 诊疗类别
if (activity_category_code.value && Array.isArray(activity_category_code.value)) {
rootNode.children = activity_category_code.value.map((item) => ({
label: item.label || '',
value: `act_${item.value}`,
disabled: false,
}));
}
break;
case '4': // 挂号类别(无子节点)
rootNode.children = [];
break;
default:
break;
}
clinicalTree.value.push(rootNode);
});
}
// 树形选择器变化处理
function handleTreeChange(selectedIds) {
if (!Array.isArray(selectedIds)) {
selectedIds = [];
}
// 获取所有选中的叶子节点
const leafNodeIds = getLeafNodeIds(selectedIds);
// 按类型拆分参数
const medIds = [];
const devIds = [];
const actIds = [];
const clinicalTypes = [];
leafNodeIds.forEach((id) => {
const idStr = String(id);
if (idStr === '4') {
// 挂号类型
if (!clinicalTypes.includes('4')) clinicalTypes.push('4');
} else if (idStr.startsWith('med_')) {
// 药品子类别
medIds.push(idStr.replace('med_', ''));
if (!clinicalTypes.includes('1')) clinicalTypes.push('1');
} else if (idStr.startsWith('dev_')) {
// 器械子类别
devIds.push(idStr.replace('dev_', ''));
if (!clinicalTypes.includes('2')) clinicalTypes.push('2');
} else if (idStr.startsWith('act_')) {
// 诊疗子类别
actIds.push(idStr.replace('act_', ''));
if (!clinicalTypes.includes('3')) clinicalTypes.push('3');
} else if (['1', '2', '3'].includes(idStr)) {
// 父节点选中(全选)
clinicalTypes.push(idStr);
// 自动选中所有子类别
const parentNode = clinicalTree.value.find(node => String(node.value) === idStr);
if (parentNode?.children?.length) {
parentNode.children.forEach(child => {
const childId = String(child.value);
if (childId.startsWith('med_')) medIds.push(childId.replace('med_', ''));
if (childId.startsWith('dev_')) devIds.push(childId.replace('dev_', ''));
if (childId.startsWith('act_')) actIds.push(childId.replace('act_', ''));
});
}
}
});
// 更新查询参数
queryParams.value.clinicalType = clinicalTypes.length ? clinicalTypes.join(',') : undefined;
queryParams.value.medicationCategoryCode = medIds.length ? medIds.join(',') : undefined;
queryParams.value.deviceCategoryCode = devIds.length ? devIds.join(',') : undefined;
queryParams.value.activityCategoryCode = actIds.length ? actIds.join(',') : undefined;
console.log('最终查询参数:', {
clinicalType: queryParams.value.clinicalType,
medicationCategoryCode: queryParams.value.medicationCategoryCode,
deviceCategoryCode: queryParams.value.deviceCategoryCode,
activityCategoryCode: queryParams.value.activityCategoryCode
});
}
// 获取所有叶子节点ID处理父节点选中情况
function getLeafNodeIds(selectedIds) {
const leafIds = [];
const traverse = (nodes) => {
nodes.forEach(node => {
const nodeValue = String(node.value);
if (selectedIds.includes(nodeValue)) {
if (!node.children || !node.children.length) {
// 叶子节点直接添加
leafIds.push(nodeValue);
} else {
// 父节点选中,递归获取所有子节点
traverse(node.children);
}
} else if (node.children && node.children.length) {
// 继续递归检查子节点
traverse(node.children);
}
});
};
traverse(clinicalTree.value);
// 处理直接选中的叶子节点(非父节点递归获取的)
selectedIds.forEach(id => {
const idStr = String(id);
// 挂号类型或无子节点的节点直接添加
if (idStr === '4' || !clinicalTree.value.some(node =>
String(node.value) === idStr && node.children && node.children.length
)) {
if (!leafIds.includes(idStr)) {
leafIds.push(idStr);
}
}
});
return [...new Set(leafIds)];
}
// 树形选择器清空处理
function handleTreeClear() {
selectedTypeIds.value = [];
queryParams.value.clinicalType = undefined;
queryParams.value.medicationCategoryCode = undefined;
queryParams.value.deviceCategoryCode = undefined;
queryParams.value.activityCategoryCode = undefined;
}
// 计算合计金额
function handleTotalAmount() {
totalAmount.value = purchaseinventoryList.value.reduce((accumulator, currentRow) => {
return accumulator + (Number(currentRow.totalPrice) || 0);
}, 0);
}
// 表格合并行方法(纯函数,不修改数据)
const arraySpanMethod = ({ row, column, rowIndex, columnIndex }) => {
// 合并门诊号列columnIndex === 1
if (columnIndex === 1) {
const spanInfo = rowSpanMap.value[rowIndex];
if (spanInfo) {
return { rowspan: spanInfo.rowspan, colspan: spanInfo.colspan || 1 };
} else {
return { rowspan: 0, colspan: 0 };
}
}
// 其他列不合并
return { rowspan: 1, colspan: 1 };
};
// 预处理列表数据:插入小计行、计算合并行信息
// 此函数替代了原来在 arraySpanMethod 中 splice 修改数据的做法
function processListWithSubtotals(list) {
rowSpanMap.value = {};
xiaojiTotal.value = [];
const result = [];
let i = 0;
while (i < list.length) {
const row = list[i];
// 跳过已有的合计行
if (row.departmentName === '合计') {
result.push(row);
rowSpanMap.value[result.length - 1] = { rowspan: 1, colspan: 1 };
i++;
continue;
}
const currentBusNo = row.busNo;
let rowspan = 0;
let totalPriceSum = 0;
let j = i;
// 计算相同门诊号的行数
while (j < list.length && list[j].busNo === currentBusNo && list[j].departmentName !== '合计') {
rowspan++;
totalPriceSum += Number(list[j].totalPrice) || 0;
j++;
}
// 设置第一行的 rowspan
const startRow = result.length;
rowSpanMap.value[startRow] = { rowspan, colspan: 1 };
// 添加数据行
for (let k = i; k < j; k++) {
result.push(list[k]);
}
// 添加小计行多于1行时才添加
if (rowspan > 1) {
const subtotalRow = {
departmentName: '小计',
totalPrice: totalPriceSum.toFixed(4),
};
// 小计行不合并
rowSpanMap.value[result.length] = { rowspan: 1, colspan: 1 };
result.push(subtotalRow);
xiaojiTotal.value.push({
inde: result.length,
busNo: currentBusNo,
genderEnum_enumText: list[i].genderEnum_enumText,
totalPrice: totalPriceSum.toFixed(4),
});
}
i = j;
}
return result;
}
// 统计类型变化处理
function inventoryChange(val) {
queryParams.value.statisticsType = val;
xiaojiTotal.value = [];
purchaseinventoryList.value = [];
rowSpanMap.value = {};
getList();
}
// 初始化数据加载
function getPharmacyCabinetLists() {
getReportChargeInit().then((response) => {
inventoryOptions.value = response.data.statisticsTypeOptions;
queryParams.value.statisticsType = 1;
issuerOptions.value = response.data.issuerOptions;
payeeOptions.value = response.data.payeeOptions;
clinicalTypeOptions.value = response.data.clinicalTypeOptions || [];
// 确保字典数据加载完成后再构建树形
nextTick(() => {
buildClinicalTree();
});
});
getDepartmentList().then((response) => {
getDepartmentOptions.value = response.data || [];
});
}
// 查询列表数据
function getList(type) {
if (type) {
xiaojiTotal.value = [];
purchaseinventoryList.value = [];
}
loading.value = true;
var totalPrice2 = 0;
// 构建请求参数自动排除undefined/null属性
let param = {
...queryParams.value,
pageSize: queryParams.value.searchKey ? 1000 : queryParams.value.pageSize,
pageNo: queryParams.value.searchKey ? 1 : queryParams.value.pageNo,
};
// 移除空值参数
Object.keys(param).forEach(key => {
if (param[key] === undefined || param[key] === null || param[key] === '') {
delete param[key];
}
});
getReportChargePage(param).then((res) => {
purchaseinventoryList.value = res.data.records || [];
total.value = res.data.total;
purchaseinventoryList.value.map((k) => {
k.totalPrice = k.totalPrice ? k.totalPrice.toFixed(4) : '0.0000';
k.price = k.price ? k.price.toFixed(4) : '0.0000';
k.number = k.number
? k.number + (k.quantityUnit_dictText ? k.quantityUnit_dictText : '')
: '0.0000' + (k.quantityUnit_dictText ? k.quantityUnit_dictText : '');
});
// 处理搜索关键词或单页数据
if (queryParams.value.searchKey || (total.value && total.value <= queryParams.value.pageSize)) {
// 先处理小计行和合并信息
purchaseinventoryList.value = processListWithSubtotals(purchaseinventoryList.value);
purchaseinventoryList.value.forEach((k) => {
if (k.departmentName !== '小计' && k.departmentName !== '合计') {
totalPrice2 += Number(k.totalPrice) || 0;
}
});
totalPrice2 = totalPrice2 ? totalPrice2.toFixed(4) : totalPrice2;
let pageNoAll = total.value / queryParams.value.pageSize;
if (Math.ceil(pageNoAll) == queryParams.value.pageNo) {
purchaseinventoryList.value.push({ departmentName: '合计', totalPrice: totalPrice2 });
rowSpanMap.value[purchaseinventoryList.value.length - 1] = { rowspan: 1, colspan: 1 };
}
loading.value = false;
} else if (total.value && total.value > queryParams.value.pageSize && !queryParams.value.searchKey) {
// 多页数据先处理当前页数据确保rowSpanMap正确初始化避免表格格式错乱
purchaseinventoryList.value = processListWithSubtotals(purchaseinventoryList.value);
loading.value = false;
// 然后获取全部数据进行完整处理
let queryParamsValue = { ...queryParams.value };
queryParamsValue.pageSize = total.value;
queryParamsValue.pageNo = 1;
Object.keys(queryParamsValue).forEach(key => {
if (queryParamsValue[key] === undefined || queryParamsValue[key] === null || queryParamsValue[key] === '') {
delete queryParamsValue[key];
}
});
getReportChargePage(queryParamsValue).then((res) => {
purchaseinventoryListAll.value = res.data.records || [];
if (purchaseinventoryListAll.value.length > 0) {
purchaseinventoryListAll.value.map((k) => {
k.totalPrice = k.totalPrice ? k.totalPrice.toFixed(4) : '0.0000';
k.price = k.price ? k.price.toFixed(4) : '0.0000';
k.number = k.number
? k.number + (k.quantityUnit_dictText ? k.quantityUnit_dictText : '')
: '0.0000' + (k.quantityUnit_dictText ? k.quantityUnit_dictText : '');
totalPrice2 += Number(k.totalPrice);
});
purchaseinventoryList.value = processListWithSubtotals(purchaseinventoryListAll.value);
totalPrice2 = totalPrice2 ? totalPrice2.toFixed(4) : totalPrice2;
let pageNoAll = total.value / queryParams.value.pageSize;
if (Math.ceil(pageNoAll) == queryParams.value.pageNo) {
purchaseinventoryList.value.push({ departmentName: '合计', totalPrice: totalPrice2 });
rowSpanMap.value[purchaseinventoryList.value.length - 1] = { rowspan: 1, colspan: 1 };
}
}
});
}
});
}
// 查询按钮点击事件
function handleQuery() {
queryParams.value.chargeTimeSTime =
occurrenceTime.value && occurrenceTime.value.length == 2
? occurrenceTime.value[0] + ' 00:00:00'
: '';
queryParams.value.chargeTimeETime =
occurrenceTime.value && occurrenceTime.value.length == 2
? occurrenceTime.value[1] + ' 23:59:59'
: '';
queryParams.value.pageNo = 1;
getList(1);
}
// 重置按钮点击事件
function handleClear() {
occurrenceTime.value = [];
queryParams.value.chargeTimeSTime = '';
queryParams.value.chargeTimeETime = '';
queryParams.value.searchKey = undefined;
queryParams.value.departmentId = undefined;
queryParams.value.issuerId = undefined;
queryParams.value.payeeId = undefined;
queryParams.value.clinicalType = undefined;
queryParams.value.medicationCategoryCode = undefined;
queryParams.value.deviceCategoryCode = undefined;
queryParams.value.activityCategoryCode = undefined;
selectedTypeIds.value = [];
proxy.resetForm('queryRef');
getList(1);
}
// 表格选择事件
function handleSelectionChange(selection) {
ids.value = selection.map((item) => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
}
// 初始化日期范围为当月
function initDefaultDateRange() {
const now = new Date();
const year = now.getFullYear();
const month = now.getMonth();
const firstDay = new Date(year, month, 1);
const today = now;
const formatDate = (date) => {
const y = date.getFullYear();
const m = String(date.getMonth() + 1).padStart(2, '0');
const d = String(date.getDate()).padStart(2, '0');
return `${y}-${m}-${d}`;
};
occurrenceTime.value = [formatDate(firstDay), formatDate(today)];
queryParams.value.chargeTimeSTime = occurrenceTime.value[0] + ' 00:00:00';
queryParams.value.chargeTimeETime = occurrenceTime.value[1] + ' 23:59:59';
}
// 导出Excel
function handleExport() {
// 构建导出参数(移除分页参数)
const exportParams = { ...queryParams.value };
delete exportParams.pageNo;
delete exportParams.pageSize;
// 移除空值参数
Object.keys(exportParams).forEach(key => {
if (exportParams[key] === undefined || exportParams[key] === null || exportParams[key] === '') {
delete exportParams[key];
}
});
proxy.downloadGet(
'/report-manage/charge/excel-out',
exportParams,
`门诊收费报表_${proxy.formatDateStr(new Date(), 'YYYY-MM-DD')}.xlsx`
);
}
// 初始化页面
getPharmacyCabinetLists();
initDefaultDateRange();
getList();
</script>
<style scoped>
.custom-tree-node {
display: flex;
align-items: center;
}
.pagination-container {
margin-right: 20px;
}
</style>