检验项目设置-套餐设置-套餐管理
This commit is contained in:
@@ -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'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 处理删除
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user