检验项目设置-套餐设置-套餐管理

This commit is contained in:
2026-01-27 09:26:27 +08:00
parent ea5215a1b0
commit 802f845231
5 changed files with 369 additions and 54 deletions

View File

@@ -1,5 +1,6 @@
<template>
<div class="package-management">
<!-- 调试信息如果看到这个注释说明模板已加载 -->
<div class="package-management" @vue:mounted="console.log('PackageManagement 模板已挂载')">
<!-- 左侧导航栏 -->
<nav class="sidebar" :class="{ active: sidebarActive }">
<div class="sidebar-item" @click="navigateToTab(0)">检验类型</div>
@@ -167,7 +168,12 @@
<script setup>
import {computed, onMounted, ref} from 'vue';
import {useRouter} from 'vue-router';
import {ElMessage} from 'element-plus';
import {getLocationTree} from '@/views/charge/outpatientregistration/components/outpatientregistration';
import {listInspectionPackage} from '@/api/system/inspectionPackage';
console.log('PackageManagement 组件脚本开始执行')
console.log('listInspectionPackage 函数:', listInspectionPackage)
// 创建路由实例
const router = useRouter();
@@ -210,20 +216,10 @@ function getDepartmentList() {
// 获取科室数据 - 与门诊挂号页面保持一致,在组件初始化时直接调用
getDepartmentList();
// 初始化数据
onMounted(() => {
// 其他初始化逻辑
});
// 表格数据
const tableData = ref([
{id: 2348, hospital: '演示医院', date: '2025-11-17', name: '血脂333', type: '检验套餐', level: '全院套餐', dept: '', user: '', amount: 40.00, fee: 0.00, total: 40.00, combined: '否', display: '是', enabled: '是', operator: '徐斌'},
{id: 2341, hospital: '演示医院', date: '2025-10-31', name: '病理检测', type: '检验套餐', level: '全院套餐', dept: '', user: '', amount: 50.00, fee: 0.00, total: 50.00, combined: '否', display: '是', enabled: '是', operator: '徐斌'},
{id: 2340, hospital: '演示医院', date: '2025-10-31', name: '肝功能', type: '检验套餐', level: '全院套餐', dept: '', user: '', amount: 31.00, fee: 0.00, total: 31.00, combined: '否', display: '是', enabled: '是', operator: '徐斌'},
{id: 2339, hospital: '演示医院', date: '2025-10-31', name: '风湿', type: '检验套餐', level: '全院套餐', dept: '', user: '', amount: 119.00, fee: 0.00, total: 119.00, combined: '否', display: '是', enabled: '是', operator: '徐斌'},
{id: 2338, hospital: '演示医院', date: '2025-10-31', name: '尿常规', type: '检验套餐', level: '全院套餐', dept: '', user: '', amount: 1.00, fee: 0.00, total: 1.00, combined: '否', display: '是', enabled: '是', operator: '徐斌'},
{id: 2297, hospital: '演示医院', date: '2025-04-30', name: '测试', type: '检验套餐', level: '全院套餐', dept: '', user: '', amount: 241.00, fee: 0.00, total: 241.00, combined: '否', display: '是', enabled: '否', operator: '徐斌'},
]);
// 表格数据 - 从API获取
const tableData = ref([])
const loading = ref(false)
const total = ref(0)
// 获取当前日期的函数格式为YYYY-MM-DD
function getCurrentDate() {
@@ -243,24 +239,121 @@ const searchParams = ref({
department: ''
});
// 过滤后的数据
// 从API加载数据
async function loadData() {
try {
console.log('loadData 函数被调用')
loading.value = true
// 构建查询参数(匹配后端 InspectionPackage 实体字段)
const params = {
pageNum: 1,
pageSize: 1000, // 获取足够多的数据
packageCategory: '检验套餐' // InspectionPackage 使用 packageCategory 而不是 packageType
}
// 处理日期范围(后端可能不支持日期范围查询,先保留)
// if (searchParams.value.startDate) {
// params.startDate = searchParams.value.startDate
// }
// if (searchParams.value.endDate) {
// params.endDate = searchParams.value.endDate
// }
if (searchParams.value.packageName) {
params.packageName = searchParams.value.packageName
}
if (searchParams.value.packageLevel) {
params.packageLevel = searchParams.value.packageLevel
}
if (searchParams.value.department) {
params.department = searchParams.value.department
}
console.log('准备调用 listInspectionPackage API参数:', params)
const response = await listInspectionPackage(params)
console.log('listInspectionPackage API 返回:', response)
if (response) {
// 处理不同的响应格式优先按若依风格response.rows / response.total
let dataList = []
if (Array.isArray(response)) {
// 直接返回数组
dataList = response
total.value = response.length
} else if (Array.isArray(response.rows)) {
// TableDataInfo 格式:{ rows: [], total: 0 }
dataList = response.rows
total.value = response.total || response.rows.length || 0
} else if (response.data) {
// 兼容 axios 原始 response.data 写法
const data = response.data
if (Array.isArray(data)) {
dataList = data
total.value = data.length
} else if (Array.isArray(data.rows)) {
dataList = data.rows
total.value = data.total || data.rows.length || 0
} else if (Array.isArray(data.records)) {
dataList = data.records
total.value = data.total || data.records.length || 0
}
}
// 转换数据格式以匹配前端显示InspectionPackage 字段映射)
console.log('原始数据列表:', dataList)
console.log('数据列表长度:', dataList.length)
tableData.value = (dataList || []).map(item => {
const mappedItem = {
id: item.basicInformationId || item.id, // 优先使用 basicInformationId
packageId: item.packageId || item.basicInformationId || item.id, // 保存packageId用于跳转
basicInformationId: item.basicInformationId, // 保存原始basicInformationId
hospital: item.orgName || '演示医院',
date: item.createTime ? (item.createTime.split('T')[0] || item.createTime.substring(0, 10)) : '',
name: item.packageName || '',
type: item.packageCategory || '检验套餐',
level: item.packageLevel || '',
dept: item.department || '',
user: item.userId || '',
amount: parseFloat(item.packageAmount || 0),
fee: parseFloat(item.serviceFee || 0),
total: parseFloat(item.packageAmount || 0) + parseFloat(item.serviceFee || 0),
combined: item.enablePackagePrice === true ? '是' : '否',
display: item.showPackageName === true ? '是' : '否',
enabled: item.isDisabled === true ? '否' : '是',
operator: item.createBy || ''
}
console.log('原始数据项:', item)
console.log('映射后的数据项:', mappedItem)
return mappedItem
})
console.log('最终 tableData.value:', tableData.value)
console.log('tableData.value 长度:', tableData.value.length)
} else {
tableData.value = []
total.value = 0
}
} catch (error) {
console.error('加载数据失败:', error)
ElMessage.error('加载数据失败: ' + (error.message || '未知错误'))
tableData.value = []
total.value = 0
} finally {
loading.value = false
}
}
// 初始化数据
onMounted(() => {
console.log('onMounted 被调用,准备加载数据')
loadData()
})
// 过滤后的数据 - 现在直接从API获取这里保留前端过滤作为补充
const filteredData = computed(() => {
return tableData.value.filter(item => {
// 日期筛选
if (searchParams.value.startDate && item.date < searchParams.value.startDate) return false;
if (searchParams.value.endDate && item.date > searchParams.value.endDate) return false;
// 套餐名称筛选
if (searchParams.value.packageName && !item.name.toLowerCase().includes(searchParams.value.packageName.toLowerCase())) return false;
// 套餐级别筛选
if (searchParams.value.packageLevel && item.level !== searchParams.value.packageLevel) return false;
// 科室筛选
if (searchParams.value.department && item.department !== searchParams.value.department) return false;
return true;
});
return tableData.value
});
// 返回套餐设置主界面
@@ -280,7 +373,7 @@ function toggleSidebar() {
// 处理查询
function handleSearch() {
// 过滤逻辑已在computed属性中实现
loadData()
}
// 处理重置
@@ -292,6 +385,7 @@ function handleReset() {
packageLevel: '',
department: ''
};
loadData()
}
// 处理新增
@@ -301,12 +395,40 @@ function handleAdd() {
// 处理编辑
function handleEdit(item) {
alert(`准备编辑套餐:${item.name}\n数据已加载至编辑表单套餐设置主界面`);
// 跳转到套餐设置主界面并传递套餐ID用于加载数据
// 后端接口使用 basicInformationId 作为路径参数
const packageId = item.basicInformationId || item.id;
if (!packageId) {
ElMessage.error('无法获取套餐ID请刷新页面后重试');
return;
}
router.push({
path: '/maintainSystem/Inspection',
query: {
tab: '2',
packageId: packageId,
mode: 'edit'
}
});
}
// 处理查看
function handleView(item) {
alert(`准备查看套餐:${item.name}\n数据已加载至查看表单套餐设置主界面`);
// 跳转到套餐设置主界面并传递套餐ID用于加载数据
// 后端接口使用 basicInformationId 作为路径参数
const packageId = item.basicInformationId || item.id;
if (!packageId) {
ElMessage.error('无法获取套餐ID请刷新页面后重试');
return;
}
router.push({
path: '/maintainSystem/Inspection',
query: {
tab: '2',
packageId: packageId,
mode: 'view'
}
});
}
// 处理删除

View File

@@ -2074,6 +2074,13 @@ onMounted(() => {
if (query.tab === '0' || query.tab === '1' || query.tab === '2') {
activeNav.value = parseInt(query.tab);
}
// 检查URL参数中是否有packageId如果有则加载套餐数据用于编辑或查看
if (query.packageId) {
// 切换到套餐设置标签页
activeNav.value = 2;
// 加载套餐数据
loadInspectionPackage(query.packageId);
}
// 初始化计算套餐金额和服务费
calculateAmounts();
});

View File

@@ -3,33 +3,29 @@
<!-- 左侧导航栏 -->
<div class="sidebar">
<div class="sidebar-header">
<h3>检查项目管理</h3>
<h3>需求描述</h3>
</div>
<div class="sidebar-menu">
<!-- 明确列出所有导航项 -->
<button
class="menu-item active"
@click="handleMenuClick('检类型')"
class="menu-item"
:class="{ active: activeMenu === '检类型' }"
@click="handleMenuClick('检验类型')"
>
<span class="menu-icon">📋</span>
<span class="menu-text">类型</span>
<span class="menu-text">类型</span>
</button>
<button
class="menu-item"
@click="handleMenuClick('检查方法')"
:class="{ active: activeMenu === '检验项目' }"
@click="handleMenuClick('检验项目')"
>
<span class="menu-icon">🔬</span>
<span class="menu-text">查方法</span>
</button>
<button
class="menu-item"
@click="handleMenuClick('检查部位')"
>
<span class="menu-icon">🎯</span>
<span class="menu-text">检查部位</span>
<span class="menu-text">验项目</span>
</button>
<button
class="menu-item"
:class="{ active: activeMenu === '套餐设置' }"
@click="handleMenuClick('套餐设置')"
>
<span class="menu-icon">📦</span>
@@ -57,7 +53,7 @@
@switch-to-settings="handleSwitchToSettings"
/>
</template>
<!-- 类型的表格视图 -->
<!-- 类型的表格视图 -->
<template v-if="activeMenu === '检查类型'">
<div class="header">
<h1>{{ activeMenu }}管理</h1>
@@ -208,7 +204,7 @@
</div>
</template>
<!-- 查方法的表格视图 -->
<!-- 验项目的表格视图对应检查方法 -->
<template v-else-if="activeMenu === '检查方法'">
<div class="header">
<h1>{{ activeMenu }}管理</h1>
@@ -560,6 +556,55 @@
<button class="pagination-btn"></button>
</div>
</div>
<!-- 右侧侧边栏 -->
<div class="right-sidebar">
<el-tabs v-model="rightTabActive" class="right-tabs">
<el-tab-pane label="基本信息" name="basic">
<div class="info-content">
<div class="info-item">
<span class="info-label">所属模块:</span>
<span class="info-value">维护</span>
</div>
<div class="info-item">
<span class="info-label">父需求:</span>
<span class="info-value">检验项</span>
</div>
<div class="info-item">
<span class="info-label">需求层级:</span>
<span class="info-value"></span>
</div>
<div class="info-item">
<span class="info-label">当前状态:</span>
<span class="info-value">激活</span>
</div>
<div class="info-item">
<span class="info-label">优先级:</span>
<span class="info-value priority">3</span>
</div>
<div class="info-item">
<span class="info-label">预计工时:</span>
<span class="info-value">0h</span>
</div>
</div>
<el-tabs v-model="subTabActive" class="sub-tabs">
<el-tab-pane label="相关需求" name="related">
<div class="empty-content">暂无相关需求</div>
</el-tab-pane>
<el-tab-pane label="迭代" name="iteration">
<div class="empty-content">暂无迭代信息</div>
</el-tab-pane>
</el-tabs>
</el-tab-pane>
<el-tab-pane label="需求" name="requirement">
<div class="requirement-content">
<div class="requirement-text">
<p>1如上图1所示:增加套餐管理界面</p>
</div>
</div>
</el-tab-pane>
</el-tabs>
</div>
</div>
</template>
@@ -589,10 +634,15 @@ import {
import PackageSettings from './components/PackageSettings.vue';
import PackageManagement from './components/PackageManagement.vue';
// 菜单数据
const menus = ['检类型', '检查方法', '检查部位', '套餐设置'];
// 菜单数据(显示名称)
const menus = ['检类型', '检验项目', '套餐设置'];
// 内部业务逻辑名称(用于条件判断)
const activeMenu = ref('检查类型');
// 右侧侧边栏状态
const rightTabActive = ref('basic');
const subTabActive = ref('related');
// 套餐视图状态: management-套餐管理列表, settings-套餐设置
const packageView = ref('management')
// 套餐设置模式: add-新增, edit-编辑, view-查看
@@ -763,12 +813,21 @@ onMounted(async () => {
}
});
// 菜单名称映射:将显示名称映射到内部业务逻辑名称
const menuMapping = {
'检验类型': '检查类型',
'检验项目': '检查方法',
'套餐设置': '套餐设置'
};
// 处理菜单点击
function handleMenuClick(menu) {
console.log('点击菜单:', menu);
console.log('当前activeMenu:', activeMenu.value);
activeMenu.value = menu;
// 将显示名称映射到内部业务逻辑名称
const internalMenu = menuMapping[menu] || menu;
activeMenu.value = internalMenu;
console.log('更新后activeMenu:', activeMenu.value);
@@ -1493,6 +1552,7 @@ select {
min-height: 100vh;
background-color: #f5f7fa;
color: #000000;
position: relative;
}
/* 左侧导航栏样式 */
@@ -1611,6 +1671,109 @@ select {
overflow-x: auto;
overflow-y: auto;
background-color: #f8f9fa;
margin-right: 300px; /* 为右侧侧边栏留出空间 */
}
/* 右侧侧边栏样式 */
.right-sidebar {
position: fixed;
right: 0;
top: 0;
width: 300px;
height: 100vh;
background: #ffffff;
box-shadow: -2px 0 8px rgba(0, 0, 0, 0.08);
border-left: 1px solid #e8e8e8;
z-index: 100;
overflow-y: auto;
}
.right-tabs {
height: 100%;
}
.right-tabs :deep(.el-tabs__header) {
margin: 0;
padding: 16px 16px 0 16px;
border-bottom: 1px solid #e8e8e8;
}
.right-tabs :deep(.el-tabs__content) {
padding: 16px;
height: calc(100% - 60px);
overflow-y: auto;
}
.info-content {
margin-bottom: 20px;
}
.info-item {
display: flex;
justify-content: space-between;
padding: 12px 0;
border-bottom: 1px solid #f0f0f0;
}
.info-item:last-child {
border-bottom: none;
}
.info-label {
font-size: 14px;
color: #666;
font-weight: 500;
}
.info-value {
font-size: 14px;
color: #333;
}
.info-value.priority {
display: inline-block;
width: 24px;
height: 24px;
line-height: 24px;
text-align: center;
background: #1890FF;
color: #fff;
border-radius: 50%;
font-weight: bold;
}
.sub-tabs {
margin-top: 20px;
}
.sub-tabs :deep(.el-tabs__header) {
margin: 0;
border-bottom: 1px solid #e8e8e8;
}
.sub-tabs :deep(.el-tabs__content) {
padding: 16px 0;
}
.empty-content {
text-align: center;
color: #999;
padding: 40px 0;
font-size: 14px;
}
.requirement-content {
padding: 16px 0;
}
.requirement-text {
font-size: 14px;
line-height: 1.8;
color: #333;
}
.requirement-text p {
margin: 0 0 12px 0;
}
.header {