检查项目设置->套餐设置->套餐管理补充

This commit is contained in:
2025-11-27 09:24:26 +08:00
parent e23d42404d
commit 065f7052c6
4 changed files with 270 additions and 252 deletions

View File

@@ -124,7 +124,7 @@ public class CheckTypeController extends BaseController {
return AjaxResult.success(result);
} else {
List<CheckPackage> list = checkPackageService.list(wrapper);
return AjaxResult.success(list);
return AjaxResult.success(list);
}
}

View File

@@ -95,9 +95,11 @@
{{ getLevelLabel(row.packageLevel) }}
</template>
</el-table-column>
<el-table-column prop="department" label="科室" width="120" align="center">
<el-table-column prop="department" label="科室" width="150" align="center">
<template #default="{ row }">
{{ getDeptName(row.department) }}
<span :title="row.department && /^[A-Z]\d{2}$/.test(row.department.trim()) ? '旧编码格式,建议编辑套餐重新选择科室' : ''">
{{ getDeptName(row.department) }}
</span>
</template>
</el-table-column>
<el-table-column prop="user" label="用户" width="100" align="center" />
@@ -232,60 +234,65 @@ onMounted(async () => {
console.error('获取套餐级别字典失败:', error)
}
// 获取科室列表 - 优先使用Organization API包含编码和名称
// 获取科室列表 - 使用Organization完整API包含编码和名称
try {
// 尝试使用Organization API获取科室列表包含编码
// 使用Organization完整API获取科室列表包含busNo编码)
const orgResponse = await request({
url: '/app-common/department-list',
method: 'get'
url: '/base-data-manage/organization/organization',
method: 'get',
params: {
pageNo: 1,
pageSize: 1000 // 获取足够多的数据
}
})
console.log('科室Organization API响应:', orgResponse)
let orgList = []
if (orgResponse) {
if (Array.isArray(orgResponse)) {
orgList = orgResponse
} else if (orgResponse.data) {
if (Array.isArray(orgResponse.data)) {
if (orgResponse.data) {
if (orgResponse.data.records && Array.isArray(orgResponse.data.records)) {
orgList = orgResponse.data.records
} else if (Array.isArray(orgResponse.data)) {
orgList = orgResponse.data
} else if (orgResponse.data.data && Array.isArray(orgResponse.data.data)) {
orgList = orgResponse.data.data
}
} else if (orgResponse.code === 200 && orgResponse.data) {
orgList = Array.isArray(orgResponse.data) ? orgResponse.data : []
} else if (Array.isArray(orgResponse)) {
orgList = orgResponse
}
}
// 展开树结构过滤出科室类型typeEnum=2
if (orgList && orgList.length > 0) {
const flattenList = []
function flatten(nodes) {
nodes.forEach(node => {
if (node.typeEnum === 2 && node.busNo && node.name) {
flattenList.push(node)
}
if (node.children && node.children.length > 0) {
flatten(node.children)
}
})
}
flatten(orgList)
orgList = flattenList
}
if (orgList && orgList.length > 0) {
// 使用Organization数据包含编码和名称
departments.value = orgList.map(org => {
const busNo = (org.busNo || org.code || '').trim()
const name = (org.name || org.deptName || '').trim()
// 如果busNo是层级编码如 "A01.001"),同时存储前缀("A01")用于匹配
const busNoPrefix = busNo ? busNo.split('.')[0] : ''
return {
dictValue: name,
dictLabel: name,
deptId: org.id || org.deptId,
deptCode: busNo || name, // 优先使用busNo如果没有则使用名称
busNoPrefix: busNoPrefix, // 存储前缀用于匹配
rawOrg: org // 保存原始数据用于调试
deptCode: busNo || name,
busNoPrefix: busNoPrefix,
rawOrg: org
}
})
console.log('科室数据加载成功Organization:', departments.value.length)
console.log('科室映射关系前5个:', departments.value.slice(0, 5).map(d => ({
deptCode: `"${d.deptCode}"`,
busNoPrefix: `"${d.busNoPrefix}"`,
codeLength: d.deptCode ? d.deptCode.length : 0,
name: d.dictLabel,
rawBusNo: d.rawOrg?.busNo
})))
} else {
// 如果Organization API没有数据使用系统部门API
const deptResponse = await listDept()
console.log('科室API响应:', deptResponse)
// 处理不同的响应格式
let deptList = []
if (deptResponse) {
if (Array.isArray(deptResponse)) {
@@ -302,26 +309,21 @@ onMounted(async () => {
}
if (deptList && deptList.length > 0) {
// 将部门列表转换为字典格式
departments.value = deptList.map(dept => ({
dictValue: dept.deptName || dept.name,
dictLabel: dept.deptName || dept.name,
deptId: dept.deptId || dept.id,
deptCode: dept.deptName || dept.name // 如果没有编码,使用名称
deptCode: dept.deptName || dept.name
}))
console.log('科室数据加载成功Dept:', departments.value.length, departments.value)
} else {
console.warn('科室列表为空,尝试使用字典方式')
// 如果获取失败,尝试使用字典方式
try {
const dictResponse = await getDicts('dept')
console.log('科室字典响应:', dictResponse)
if (dictResponse && dictResponse.data) {
departments.value = dictResponse.data
console.log('使用字典方式加载科室数据成功:', departments.value.length)
}
} catch (dictError) {
console.error('获取科室字典失败:', dictError)
console.error('获取科室字典失败:', dictError)
}
}
}
@@ -432,34 +434,11 @@ function getDeptName(deptValue) {
return dept.dictLabel
}
// 如果找不到,输出详细信息用于调试
const deptCodes = departments.value.map(d => ({
deptCode: String(d.deptCode || '').trim(),
deptCodeUpper: String(d.deptCode || '').trim().toUpperCase(),
busNoPrefix: String(d.busNoPrefix || '').trim().toUpperCase(),
name: d.dictLabel,
rawBusNo: d.rawOrg?.busNo,
rawBusNoUpper: d.rawOrg?.busNo ? String(d.rawOrg.busNo).trim().toUpperCase() : '',
rawBusNoPrefix: d.rawOrg?.busNo ? String(d.rawOrg.busNo).trim().toUpperCase().split('.')[0] : ''
}))
// 输出详细的调试信息,包括所有科室的完整信息
console.group('🔍 科室匹配失败 - 详细信息')
console.log('搜索值:', trimmedValue)
console.log('搜索值(大写):', trimmedValue.toUpperCase())
console.log('搜索值长度:', trimmedValue.length)
console.log('可用科室总数:', deptCodes.length)
console.log('前5个科室详情:', deptCodes.slice(0, 5))
console.log('所有科室编码列表:', deptCodes.map(d => ({
deptCode: d.deptCode,
deptCodeUpper: d.deptCodeUpper,
busNoPrefix: d.busNoPrefix,
rawBusNo: d.rawBusNo,
rawBusNoUpper: d.rawBusNoUpper,
rawBusNoPrefix: d.rawBusNoPrefix,
name: d.name
})))
console.groupEnd()
// 无法匹配时,返回原始编码值
const isOldFormat = /^[A-Z]\d{2}$/.test(trimmedValue)
if (isOldFormat) {
return trimmedValue + ' (旧格式)'
}
return trimmedValue
}
@@ -494,8 +473,6 @@ async function handleQuery() {
tableData.value = []
total.value = 0
}
console.log('查询成功,共', total.value, '条数据')
}
} catch (error) {
console.error('查询失败:', error)
@@ -520,28 +497,17 @@ function handleReset() {
handleQuery()
}
// 返回套餐设置界面
function handleBackToSettings() {
emit('back-to-settings')
}
// 新增
function handleAdd() {
console.log('新增套餐')
// 通知父组件切换到套餐设置界面,模式为新增
emit('switch-to-settings', { mode: 'add', data: null })
}
// 编辑
async function handleEdit(row) {
try {
console.log('编辑套餐:', row.id)
// 获取完整的套餐数据(包含明细)
const response = await getCheckPackage(row.id)
if (response && (response.code === 200 || response.code === 0) && response.data) {
// 通知父组件切换到套餐设置界面,模式为编辑
emit('switch-to-settings', { mode: 'edit', data: response.data })
} else {
ElMessage.error('加载套餐数据失败')
@@ -555,13 +521,9 @@ async function handleEdit(row) {
// 查看
async function handleView(row) {
try {
console.log('查看套餐:', row.id)
// 获取完整的套餐数据(包含明细)
const response = await getCheckPackage(row.id)
if (response && (response.code === 200 || response.code === 0) && response.data) {
// 通知父组件切换到套餐设置界面,模式为查看
emit('switch-to-settings', { mode: 'view', data: response.data })
} else {
ElMessage.error('加载套餐数据失败')
@@ -589,7 +551,6 @@ function handleDelete(row) {
if (response && (response.code === 200 || response.code === 0)) {
ElMessage.success('删除成功')
// 刷新列表
handleQuery()
} else {
ElMessage.error(response?.msg || response?.message || '删除失败')
@@ -598,9 +559,7 @@ function handleDelete(row) {
console.error('删除失败:', error)
ElMessage.error('删除失败: ' + (error.message || '未知错误'))
}
}).catch(() => {
console.log('用户取消删除')
})
}).catch(() => {})
}
</script>

View File

@@ -10,7 +10,7 @@
</div>
<!-- 基本信息表单区 -->
<div class="basic-info-section" v-loading="loading" element-loading-text="正在加载诊疗项目数据...">
<div class="basic-info-section">
<h3 class="section-title">基本信息</h3>
<el-form
ref="basicFormRef"
@@ -49,12 +49,12 @@
<el-col v-if="formData.packageLevel === '2'" :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="科室选择" prop="department">
<el-select v-model="formData.department" placeholder="请选择科室" style="width: 100%">
<el-select v-model="formData.department" placeholder="请选择科室" style="width: 100%" :disabled="isReadOnly">
<el-option
v-for="dept in departments"
:key="dept.dictValue"
:key="dept.deptCode || dept.dictValue"
:label="dept.dictLabel"
:value="dept.dictValue"
:value="dept.deptCode || dept.busNoPrefix || dept.rawOrg?.busNo || dept.dictValue"
/>
</el-select>
</el-form-item>
@@ -95,7 +95,7 @@
<el-input
v-model="formData.discount"
placeholder="请输入折扣"
@input="validateNumberInput($event, 'discount')"
@input="handleDiscountChange"
:disabled="isReadOnly"
>
<template #append>%</template>
@@ -386,6 +386,7 @@ import { addCheckPackage, updateCheckPackage } from '@/api/system/checkType'
import { getDiagnosisTreatmentList } from '@/views/catalog/diagnosistreatment/components/diagnosistreatment'
import useUserStore from '@/store/modules/user'
import request from '@/utils/request' // 导入request工具用于调用Organization API
import cache from '@/plugins/cache' // 导入缓存工具
// 接收props
const props = defineProps({
@@ -477,7 +478,6 @@ const detailData = ref([])
// 监听packageData变化加载数据
watch(() => props.packageData, (newData) => {
if (newData) {
console.log('加载套餐数据:', newData)
loadPackageData(newData)
}
}, { immediate: true })
@@ -486,12 +486,33 @@ watch(() => props.packageData, (newData) => {
function loadPackageData(data) {
if (!data) return
console.log('开始加载套餐数据到表单...')
// 填充基本信息
Object.keys(formData).forEach(key => {
if (data[key] !== undefined) {
formData[key] = data[key]
// 特殊处理科室字段:检查编码格式并匹配
if (key === 'department' && data[key]) {
const deptValue = String(data[key]).trim()
const isOldFormat = /^[A-Z]\d{2}$/.test(deptValue)
if (isOldFormat && departments.value.length > 0) {
// 旧编码格式:在下拉框中添加临时选项
const tempDept = {
deptCode: deptValue,
dictLabel: `旧编码: ${deptValue} (请重新选择)`,
dictValue: deptValue,
isOldFormat: true
}
const exists = departments.value.find(d => d.deptCode === deptValue)
if (!exists) {
departments.value.unshift(tempDept)
}
formData[key] = deptValue
} else {
formData[key] = data[key]
}
} else {
formData[key] = data[key]
}
}
})
@@ -515,8 +536,6 @@ function loadPackageData(data) {
filteredList: diagnosisTreatmentList.value
}))
}
console.log('套餐数据加载完成')
}
onMounted(async () => {
@@ -534,30 +553,53 @@ onMounted(async () => {
console.error('✗ 获取套餐级别字典失败:', error)
}
// 获取科室列表 - 优先使用Organization API包含编码和名称
// 获取科室列表 - 使用Organization完整API包含编码和名称
try {
// 尝试使用Organization API获取科室列表包含编码
// 使用Organization完整API获取科室列表包含busNo编码)
const orgResponse = await request({
url: '/app-common/department-list',
method: 'get'
url: '/base-data-manage/organization/organization',
method: 'get',
params: {
pageNo: 1,
pageSize: 1000 // 获取足够多的数据
}
})
console.log('科室Organization API响应:', orgResponse)
console.log('科室Organization完整API响应:', orgResponse)
let orgList = []
if (orgResponse) {
if (Array.isArray(orgResponse)) {
orgList = orgResponse
} else if (orgResponse.data) {
if (Array.isArray(orgResponse.data)) {
// 处理分页响应格式:{ code: 200, data: { records: [...], total: ... } }
if (orgResponse.data) {
if (orgResponse.data.records && Array.isArray(orgResponse.data.records)) {
// 分页格式提取records
orgList = orgResponse.data.records
} else if (Array.isArray(orgResponse.data)) {
orgList = orgResponse.data
} else if (orgResponse.data.data && Array.isArray(orgResponse.data.data)) {
orgList = orgResponse.data.data
}
} else if (orgResponse.code === 200 && orgResponse.data) {
orgList = Array.isArray(orgResponse.data) ? orgResponse.data : []
} else if (Array.isArray(orgResponse)) {
orgList = orgResponse
}
}
// 如果是树结构需要展开所有节点包括children并过滤出科室类型typeEnum=2
if (orgList && orgList.length > 0) {
const flattenList = []
function flatten(nodes) {
nodes.forEach(node => {
// 只包含科室类型typeEnum=2且有busNo的节点
if (node.typeEnum === 2 && node.busNo && node.name) {
flattenList.push(node)
}
if (node.children && node.children.length > 0) {
flatten(node.children)
}
})
}
flatten(orgList)
orgList = flattenList
console.log('展开后的科室列表包含busNo:', orgList.length, orgList.slice(0, 3).map(o => ({ busNo: o.busNo, name: o.name })))
}
if (orgList && orgList.length > 0) {
// 使用Organization数据包含编码和名称
departments.value = orgList.map(org => {
@@ -637,91 +679,127 @@ onMounted(async () => {
}
}
// 获取诊疗项目列表 - 使用分批加载策略
loading.value = true
// 加载诊疗项目列表(优先使用缓存)
await loadDiagnosisTreatmentList(false)
// 初始化一行空数据
handleAddRow()
} catch (error) {
console.error('✗ 初始化数据失败:', error)
}
})
// 诊疗项目列表缓存key和过期时间30分钟
const DIAGNOSIS_TREATMENT_CACHE_KEY = 'check_package_diagnosis_treatment_list'
const CACHE_EXPIRE_TIME = 30 * 60 * 1000 // 30分钟
// 加载诊疗项目列表(支持缓存)
async function loadDiagnosisTreatmentList(forceRefresh = false) {
// 如果不是强制刷新,先尝试从缓存加载
if (!forceRefresh) {
try {
console.log('开始获取诊疗项目列表...')
// 分批加载数据,避免一次性加载过多导致超时
let allItems = []
const maxBatches = 3 // 最多加载3批
const batchSize = 50 // 每批50条
for (let page = 1; page <= maxBatches; page++) {
try {
const treatmentResponse = await getDiagnosisTreatmentList({
pageNo: page,
pageSize: batchSize
})
console.log(`第${page}批API响应:`, treatmentResponse)
// 处理不同的响应格式
let batchData = []
if (treatmentResponse) {
if (treatmentResponse.data && treatmentResponse.data.records) {
batchData = treatmentResponse.data.records
} else if (treatmentResponse.data && Array.isArray(treatmentResponse.data)) {
batchData = treatmentResponse.data
} else if (treatmentResponse.records && Array.isArray(treatmentResponse.records)) {
batchData = treatmentResponse.records
}
}
if (batchData.length > 0) {
allItems = allItems.concat(batchData)
console.log(`✓ 第${page}批加载成功: ${batchData.length}条,累计: ${allItems.length}条`)
// 如果这批数据少于pageSize说明已经是最后一批了
if (batchData.length < batchSize) {
break
}
} else {
break // 没有更多数据了
}
} catch (batchError) {
console.error(`第${page}批加载失败:`, batchError)
break // 出错就停止继续加载
const cachedData = cache.session.getJSON(DIAGNOSIS_TREATMENT_CACHE_KEY)
if (cachedData && cachedData.data && cachedData.timestamp) {
const now = Date.now()
const cacheAge = now - cachedData.timestamp
// 检查缓存是否过期
if (cacheAge < CACHE_EXPIRE_TIME) {
diagnosisTreatmentList.value = cachedData.data
// 静默加载,不显示消息
return
}
}
} catch (error) {
// 缓存读取失败继续从API加载
console.error('读取缓存失败:', error)
}
}
// 从API加载数据
loading.value = true
try {
let allItems = []
const maxBatches = 3
const batchSize = 50
for (let page = 1; page <= maxBatches; page++) {
try {
const treatmentResponse = await getDiagnosisTreatmentList({
pageNo: page,
pageSize: batchSize
})
let batchData = []
if (treatmentResponse) {
if (treatmentResponse.data && treatmentResponse.data.records) {
batchData = treatmentResponse.data.records
} else if (treatmentResponse.data && Array.isArray(treatmentResponse.data)) {
batchData = treatmentResponse.data
} else if (treatmentResponse.records && Array.isArray(treatmentResponse.records)) {
batchData = treatmentResponse.records
}
}
if (batchData.length > 0) {
allItems = allItems.concat(batchData)
if (batchData.length < batchSize) {
break
}
} else {
break
}
} catch (batchError) {
console.error(`第${page}批加载失败:`, batchError)
if (page === 1) {
throw batchError
}
break
}
}
if (allItems.length > 0) {
diagnosisTreatmentList.value = allItems
if (allItems.length > 0) {
diagnosisTreatmentList.value = allItems
console.log(`✓ 诊疗项目加载完成,共${allItems.length}条`)
// 保存到缓存
try {
cache.session.setJSON(DIAGNOSIS_TREATMENT_CACHE_KEY, {
data: allItems,
timestamp: Date.now()
})
} catch (cacheError) {
console.error('保存缓存失败:', cacheError)
}
// 只在强制刷新时显示成功消息
if (forceRefresh) {
ElMessage.success(`成功加载${allItems.length}个诊疗项目`)
} else {
console.warn('未获取到任何诊疗项目数据')
}
} else {
if (forceRefresh) {
ElMessage.warning({
message: '未获取到诊疗项目数据。请先在【系统管理-目录管理-诊疗项目】中添加数据',
duration: 6000,
showClose: true
})
}
} catch (error) {
console.error('获取诊疗项目列表失败:', error)
}
} catch (error) {
console.error('获取诊疗项目列表失败:', error)
if (forceRefresh) {
ElMessage.error({
message: '获取诊疗项目列表失败,请检查网络连接或联系管理员',
duration: 6000,
showClose: true
})
} finally {
loading.value = false
}
// 初始化一行空数据
handleAddRow()
console.log('=== PackageSettings 组件初始化完成 ===')
console.log('最终诊疗项目列表:', diagnosisTreatmentList.value)
} catch (error) {
console.error('✗ 初始化数据失败:', error)
} finally {
loading.value = false
}
})
}
// 套餐级别变更处理
function handlePackageLevelChange(value) {
console.log('套餐级别变更:', value)
// 重置关联字段
if (value !== '2') {
formData.department = ''
@@ -915,10 +993,45 @@ function calculateTotal(row) {
calculatePackagePrice()
}
// 计算套餐金额
// 计算套餐金额(应用折扣)
function calculatePackagePrice() {
// 计算所有明细项目的总金额
const total = detailData.value.reduce((sum, item) => sum + (item.total || 0), 0)
formData.packagePrice = total.toFixed(2)
// 如果有折扣,应用折扣计算
let finalPrice = total
if (formData.discount && parseFloat(formData.discount) > 0 && parseFloat(formData.discount) <= 100) {
const discountRate = parseFloat(formData.discount) / 100 // 将百分比转换为小数如10% -> 0.1
const discountAmount = total * discountRate // 折扣金额
finalPrice = total - discountAmount // 折扣后金额
}
formData.packagePrice = finalPrice.toFixed(2)
}
// 折扣变更处理
function handleDiscountChange(value) {
// 验证并清理输入
const regex = /^\d*\.?\d*$/
if (!regex.test(value)) {
formData.discount = value.replace(/[^\d.]/g, '')
return
}
// 验证折扣范围
const discountValue = parseFloat(formData.discount)
if (discountValue && (discountValue < 0 || discountValue > 100)) {
ElMessage.warning('折扣必须在0-100之间')
// 重置为有效值
if (discountValue < 0) {
formData.discount = '0'
} else if (discountValue > 100) {
formData.discount = '100'
}
}
// 重新计算套餐金额
calculatePackagePrice()
}
// 套餐管理
@@ -927,66 +1040,12 @@ function handlePackageManagement() {
emit('switch-to-management')
}
// 刷新 - 重新加载诊疗项目数据
// 刷新 - 清除缓存并重新加载诊疗项目数据
async function handleRefresh() {
try {
loading.value = true
console.log('开始刷新诊疗项目数据...')
// 分批加载数据,避免一次性加载过多导致超时
let allItems = []
const maxBatches = 3 // 最多加载3批
const batchSize = 50 // 每批50条
for (let page = 1; page <= maxBatches; page++) {
try {
const treatmentResponse = await getDiagnosisTreatmentList({
pageNo: page,
pageSize: batchSize
})
console.log(`第${page}批API响应:`, treatmentResponse)
let batchData = []
if (treatmentResponse) {
if (treatmentResponse.data && treatmentResponse.data.records) {
batchData = treatmentResponse.data.records
} else if (treatmentResponse.data && Array.isArray(treatmentResponse.data)) {
batchData = treatmentResponse.data
} else if (treatmentResponse.records && Array.isArray(treatmentResponse.records)) {
batchData = treatmentResponse.records
}
}
if (batchData.length > 0) {
allItems = allItems.concat(batchData)
console.log(` 第${page}批加载成功: ${batchData.length}累计: ${allItems.length}`)
// 如果这批数据少于pageSize说明已经是最后一批了
if (batchData.length < batchSize) {
break
}
} else {
break // 没有更多数据了
}
} catch (batchError) {
console.error(`第${page}批加载失败:`, batchError)
break // 出错就停止继续加载
}
}
if (allItems.length > 0) {
diagnosisTreatmentList.value = allItems
ElMessage.success('刷新成功,共加载 ' + allItems.length + ' 个项目')
} else {
ElMessage.warning('未获取到项目数据,请先在【系统管理-目录管理-诊疗项目】中添加数据')
}
} catch (error) {
console.error('刷新失败:', error)
ElMessage.error('刷新失败,请检查网络连接或联系管理员')
} finally {
loading.value = false
}
// 清除缓存
cache.session.remove(DIAGNOSIS_TREATMENT_CACHE_KEY)
// 强制刷新加载
await loadDiagnosisTreatmentList(true)
}
// 数字输入验证 - 用于表单字段

View File

@@ -55,17 +55,17 @@
<!-- 检查类型/方法/部位的表格视图 -->
<template v-else>
<div class="header">
<div class="header">
<h1>{{ activeMenu }}管理</h1>
<div class="header-actions">
<button class="btn btn-add-new" @click="handleAddNewRow">
+
</button>
</div>
<div class="header-actions">
<button class="btn btn-add-new" @click="handleAddNewRow">
+
</button>
</div>
</div>
<div class="table-container">
<table>
<div class="table-container">
<table>
<thead>
<tr>
<th style="width: 50px;"></th>
@@ -196,12 +196,12 @@
</table>
</div>
<!-- 分页区域 -->
<div class="pagination">
<button class="pagination-btn"></button>
<span>1</span>
<button class="pagination-btn"></button>
</div>
<!-- 分页区域 -->
<div class="pagination">
<button class="pagination-btn"></button>
<span>1</span>
<button class="pagination-btn"></button>
</div>
</template>
</div>
</div>
@@ -322,7 +322,7 @@ function handleMenuClick(menu) {
currentPackageData.value = null
console.log('显示套餐设置界面')
} else {
loadMenuData(menu);
loadMenuData(menu);
}
}