Files
his/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/components/PackageSettings.vue

697 lines
21 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="package-settings">
<!-- 顶部操作按钮区 -->
<div class="header-actions">
<el-button type="primary" @click="handlePackageManagement">套餐管理</el-button>
<el-button @click="handleRefresh">刷新</el-button>
<el-button type="success" @click="handleSave">保存</el-button>
</div>
<!-- 基本信息表单区 -->
<div class="basic-info-section">
<h3 class="section-title">基本信息</h3>
<el-form
ref="basicFormRef"
:model="formData"
:rules="formRules"
label-width="120px"
class="basic-form"
>
<el-row :gutter="20">
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="套餐类别" prop="packageType">
<el-select v-model="formData.packageType" placeholder="请选择套餐类别" style="width: 100%">
<el-option label="检查套餐" value="检查套餐" />
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="套餐级别" prop="packageLevel">
<el-select
v-model="formData.packageLevel"
placeholder="请选择套餐级别"
style="width: 100%"
@change="handlePackageLevelChange"
>
<el-option
v-for="item in packageLevelOptions"
:key="item.dictValue"
:label="item.dictLabel"
:value="item.dictValue"
/>
</el-select>
</el-form-item>
</el-col>
<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-option
v-for="dept in departments"
:key="dept.dictValue"
:label="dept.dictLabel"
:value="dept.dictValue"
/>
</el-select>
</el-form-item>
</el-col>
<el-col v-if="formData.packageLevel === '3'" :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="用户选择" prop="user">
<el-select v-model="formData.user" placeholder="请选择用户" style="width: 100%">
<el-option label="当前用户" value="当前用户" />
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="套餐名称" prop="packageName">
<el-input v-model="formData.packageName" placeholder="请输入套餐名称" />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="卫生机构">
<el-select v-model="formData.organization" placeholder="请选择卫生机构" style="width: 100%">
<el-option label="演示医院" value="演示医院" />
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="套餐金额">
<el-input v-model="formData.packagePrice" :disabled="true" placeholder="自动计算">
<template #append></template>
</el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="折扣">
<el-input v-model="formData.discount" placeholder="请输入折扣">
<template #append>%</template>
</el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="制单人">
<el-input v-model="formData.creator" :disabled="true" />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="是否停用">
<el-radio-group v-model="formData.isDisabled">
<el-radio :value="0">启用</el-radio>
<el-radio :value="1">停用</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="显示套餐名">
<el-radio-group v-model="formData.showPackageName">
<el-radio :value="1"></el-radio>
<el-radio :value="0"></el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="生成服务费">
<el-radio-group v-model="formData.generateServiceFee">
<el-radio :value="1"></el-radio>
<el-radio :value="0"></el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="套餐价格">
<el-radio-group v-model="formData.packagePriceEnabled">
<el-radio :value="1">启用</el-radio>
<el-radio :value="0">不启用</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="服务费">
<el-input-number
v-model="formData.serviceFee"
:precision="2"
:min="0"
placeholder="请输入服务费"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="日期">
<el-date-picker
v-model="formData.createDate"
type="date"
placeholder="选择日期"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
:disabled="true"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12">
<el-form-item label="备注">
<el-input v-model="formData.remark" type="textarea" placeholder="请输入备注" />
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<!-- 套餐明细表格区 -->
<div class="package-detail-section">
<h3 class="section-title">套餐明细</h3>
<el-table
:data="detailData"
border
style="width: 100%"
:max-height="450"
>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="code" label="编号" width="120" align="center">
<template #default="{ row }">
<el-input v-if="row.editing" v-model="row.code" placeholder="请输入编号" />
<span v-else>{{ row.code }}</span>
</template>
</el-table-column>
<el-table-column prop="itemName" label="项目名称/规格" min-width="200">
<template #default="{ row }">
<el-select
v-if="row.editing"
v-model="row.itemId"
placeholder="请选择项目"
filterable
style="width: 100%"
@change="handleItemSelect(row)"
>
<el-option
v-for="item in diagnosisTreatmentList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
<span v-else>{{ row.itemName }}</span>
</template>
</el-table-column>
<el-table-column prop="dose" label="剂量" width="80" align="center">
<template #default="{ row }">
<el-input v-if="row.editing" v-model="row.dose" placeholder="-" />
<span v-else>{{ row.dose || '-' }}</span>
</template>
</el-table-column>
<el-table-column prop="method" label="途径" width="80" align="center">
<template #default="{ row }">
<el-input v-if="row.editing" v-model="row.method" placeholder="-" />
<span v-else>{{ row.method || '-' }}</span>
</template>
</el-table-column>
<el-table-column prop="frequency" label="频次" width="80" align="center">
<template #default="{ row }">
<el-input v-if="row.editing" v-model="row.frequency" placeholder="-" />
<span v-else>{{ row.frequency || '-' }}</span>
</template>
</el-table-column>
<el-table-column prop="days" label="天数" width="80" align="center">
<template #default="{ row }">
<el-input v-if="row.editing" v-model="row.days" placeholder="-" />
<span v-else>{{ row.days || '-' }}</span>
</template>
</el-table-column>
<el-table-column prop="quantity" label="数量" width="100" align="center">
<template #default="{ row }">
<el-input-number
v-if="row.editing"
v-model="row.quantity"
:min="0"
:precision="0"
placeholder="请输入数量"
style="width: 100%"
@change="calculateAmount(row)"
/>
<span v-else>{{ row.quantity }}</span>
</template>
</el-table-column>
<el-table-column prop="unitPrice" label="单价" width="120" align="center">
<template #default="{ row }">
<el-input-number
v-if="row.editing"
v-model="row.unitPrice"
:min="0"
:precision="6"
placeholder="请输入单价"
style="width: 100%"
@change="calculateAmount(row)"
/>
<span v-else>{{ row.unitPrice?.toFixed(6) }}</span>
</template>
</el-table-column>
<el-table-column prop="amount" label="金额" width="100" align="center">
<template #default="{ row }">
{{ row.amount?.toFixed(2) || '0.00' }}
</template>
</el-table-column>
<el-table-column prop="serviceCharge" label="服务费" width="100" align="center">
<template #default="{ row }">
<el-input-number
v-if="row.editing"
v-model="row.serviceCharge"
:min="0"
:precision="2"
placeholder="服务费"
style="width: 100%"
@change="calculateTotal(row)"
/>
<span v-else>{{ row.serviceCharge?.toFixed(2) || '0.00' }}</span>
</template>
</el-table-column>
<el-table-column prop="total" label="总金额" width="100" align="center">
<template #default="{ row }">
{{ row.total?.toFixed(2) || '0.00' }}
</template>
</el-table-column>
<el-table-column prop="origin" label="产地" width="120">
<template #default="{ row }">
<el-input v-if="row.editing" v-model="row.origin" placeholder="-" />
<span v-else>{{ row.origin || '-' }}</span>
</template>
</el-table-column>
<el-table-column label="操作" width="150" align="center" fixed="right">
<template #default="{ row, $index }">
<el-button
v-if="!row.editing"
type="primary"
size="small"
icon="Edit"
circle
@click="handleEditRow(row)"
/>
<el-button
v-if="row.editing"
type="success"
size="small"
icon="Check"
circle
@click="handleConfirmRow(row)"
/>
<el-button
type="primary"
size="small"
icon="Plus"
circle
@click="handleAddRow"
/>
<el-button
type="danger"
size="small"
icon="Delete"
circle
@click="handleDeleteRow($index)"
/>
</template>
</el-table-column>
</el-table>
</div>
</div>
</template>
<script setup>
import { ref, reactive, computed, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { getDicts } from '@/api/system/dict/data'
import { addCheckPackage, updateCheckPackage } from '@/api/system/checkType'
import { getDiagnosisTreatmentList } from '@/views/catalog/diagnosistreatment/components/diagnosistreatment'
import { useUserStore } from '@/store/modules/user'
const userStore = useUserStore()
// 表单引用
const basicFormRef = ref(null)
// 表单数据
const formData = reactive({
id: null,
packageType: '检查套餐',
packageLevel: '',
department: '',
user: '',
packageName: '',
organization: '演示医院',
packagePrice: '0.00',
discount: '',
creator: userStore.name || '当前用户',
isDisabled: 0,
showPackageName: 1,
generateServiceFee: 0,
packagePriceEnabled: 1,
serviceFee: 0,
remark: '',
createDate: new Date().toISOString().split('T')[0] // 自动生成当前系统日期
})
// 表单验证规则
const formRules = {
packageType: [
{ required: true, message: '请选择套餐类别', trigger: 'change' }
],
packageLevel: [
{ required: true, message: '请选择套餐级别', trigger: 'change' }
],
packageName: [
{ required: true, message: '请输入套餐名称', trigger: 'blur' }
],
department: [
{ required: true, message: '请选择科室', trigger: 'change' }
],
user: [
{ required: true, message: '请选择用户', trigger: 'change' }
]
}
// 套餐级别选项
const packageLevelOptions = ref([])
// 科室选项
const departments = ref([])
// 诊疗项目列表
const diagnosisTreatmentList = ref([])
// 明细数据
const detailData = ref([])
// 初始化数据
onMounted(async () => {
try {
// 获取套餐级别字典
try {
const levelResponse = await getDicts('examination_item_package_level')
if (levelResponse && levelResponse.data) {
packageLevelOptions.value = levelResponse.data
}
} catch (error) {
console.error('获取套餐级别字典失败:', error)
}
// 获取科室字典
try {
const deptResponse = await getDicts('dept')
if (deptResponse && deptResponse.data) {
departments.value = deptResponse.data
}
} catch (error) {
console.error('获取科室字典失败:', error)
}
// 获取诊疗项目列表
try {
const treatmentResponse = await getDiagnosisTreatmentList({
pageNo: 1,
pageSize: 1000
})
if (treatmentResponse && treatmentResponse.data && treatmentResponse.data.records) {
diagnosisTreatmentList.value = treatmentResponse.data.records
}
} catch (error) {
console.error('获取诊疗项目列表失败:', error)
}
// 初始化一行空数据
handleAddRow()
} catch (error) {
console.error('初始化数据失败:', error)
}
})
// 套餐级别变更处理
function handlePackageLevelChange(value) {
// 重置关联字段
if (value !== '2') {
formData.department = ''
}
if (value !== '3') {
formData.user = ''
}
}
// 添加行
function handleAddRow() {
detailData.value.push({
code: '',
itemId: null,
itemName: '',
dose: '',
method: '',
frequency: '',
days: '',
quantity: 1,
unitPrice: 0,
amount: 0,
serviceCharge: 0,
total: 0,
origin: '',
editing: true
})
}
// 编辑行
function handleEditRow(row) {
row.editing = true
}
// 确认编辑
function handleConfirmRow(row) {
if (!row.itemName) {
ElMessage.warning('请选择项目')
return
}
if (!row.quantity || row.quantity <= 0) {
ElMessage.warning('请输入有效数量')
return
}
row.editing = false
}
// 删除行
function handleDeleteRow(index) {
ElMessageBox.confirm('确定要删除这一行吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
detailData.value.splice(index, 1)
calculatePackagePrice()
ElMessage.success('删除成功')
}).catch(() => {})
}
// 项目选择处理
function handleItemSelect(row) {
const item = diagnosisTreatmentList.value.find(i => i.id === row.itemId)
if (item) {
row.itemName = item.name || ''
row.code = item.busNo || ''
// 获取单价使用retailPrice
row.unitPrice = item.retailPrice || 0
calculateAmount(row)
}
}
// 计算金额
function calculateAmount(row) {
row.amount = (row.quantity || 0) * (row.unitPrice || 0)
calculateTotal(row)
}
// 计算总金额
function calculateTotal(row) {
row.total = (row.amount || 0) + (row.serviceCharge || 0)
calculatePackagePrice()
}
// 计算套餐金额
function calculatePackagePrice() {
const total = detailData.value.reduce((sum, item) => sum + (item.total || 0), 0)
formData.packagePrice = total.toFixed(2)
}
// 套餐管理
function handlePackageManagement() {
ElMessage.info('即将进入套餐管理界面')
}
// 刷新
function handleRefresh() {
ElMessageBox.confirm('确定要刷新页面吗?未保存的数据将丢失', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
location.reload()
}).catch(() => {})
}
// 保存
async function handleSave() {
try {
// 验证基本信息
await basicFormRef.value.validate()
// 验证明细数据
if (detailData.value.length === 0) {
ElMessage.warning('请至少添加一条套餐明细')
return
}
// 检查是否有未确认的编辑行
const hasEditingRow = detailData.value.some(row => row.editing)
if (hasEditingRow) {
ElMessage.warning('请先确认所有正在编辑的行')
return
}
// 检查明细数据完整性
const hasEmptyItem = detailData.value.some(row => !row.itemName || !row.quantity)
if (hasEmptyItem) {
ElMessage.warning('请完善所有明细项目信息')
return
}
// 更新创建日期为当前系统时间
formData.createDate = new Date().toISOString().split('T')[0]
// 构建保存数据
const saveData = {
id: formData.id,
packageName: formData.packageName,
code: formData.code || '',
description: formData.description || '',
packageType: formData.packageType,
packageLevel: formData.packageLevel,
department: formData.department || '',
user: formData.user || '',
organization: formData.organization,
packagePrice: formData.packagePrice,
discount: formData.discount ? parseFloat(formData.discount) : null,
creator: formData.creator,
isDisabled: formData.isDisabled,
showPackageName: formData.showPackageName,
generateServiceFee: formData.generateServiceFee,
packagePriceEnabled: formData.packagePriceEnabled,
serviceFee: formData.serviceFee || 0,
remark: formData.remark || '',
createDate: formData.createDate,
items: detailData.value.map(item => ({
itemCode: item.code || '',
itemName: item.itemName || '',
checkItemId: item.itemId || null, // 诊疗项目ID
dose: item.dose || '',
method: item.method || '',
frequency: item.frequency || '',
days: item.days || '',
quantity: item.quantity || 1,
unitPrice: item.unitPrice || 0,
amount: item.amount || 0,
serviceCharge: item.serviceCharge || 0,
total: item.total || 0,
origin: item.origin || ''
}))
}
// 调用API保存
const response = await addCheckPackage(saveData)
if (response && response.code === 200) {
ElMessage.success('套餐数据已保存')
// 如果有返回ID更新formData.id以便后续更新
if (response.data) {
formData.id = response.data
}
} else {
ElMessage.error(response?.msg || '保存失败,请检查表单数据')
}
} catch (error) {
console.error('保存失败:', error)
if (error !== 'cancel') {
ElMessage.error('保存失败,请检查表单数据')
}
}
}
</script>
<style scoped>
.package-settings {
padding: 24px;
background-color: #f5f7fa;
}
.header-actions {
display: flex;
gap: 10px;
margin-bottom: 24px;
padding: 12px;
background: white;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.03);
}
.basic-info-section,
.package-detail-section {
background: white;
border-radius: 8px;
padding: 24px;
margin-bottom: 24px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.03);
}
.section-title {
font-size: 16px;
font-weight: 500;
color: #000000;
margin: 0 0 16px 0;
padding-bottom: 12px;
border-bottom: 1px solid #e8e8e8;
}
.basic-form {
margin-top: 16px;
}
.el-table {
margin-top: 16px;
}
/* 响应式设计 */
@media (max-width: 768px) {
.package-settings {
padding: 16px;
}
.header-actions {
flex-direction: column;
}
.header-actions .el-button {
width: 100%;
}
.basic-info-section,
.package-detail-section {
padding: 16px;
}
}
</style>