1148 lines
27 KiB
Vue
1148 lines
27 KiB
Vue
<template>
|
|
<div class="charge-container">
|
|
<!-- 左侧列表 -->
|
|
<div class="patient-list">
|
|
<div class="list-header">
|
|
<!-- 添加状态筛选 -->
|
|
<div class="filter-options">
|
|
<div class="header-title">体检人员列表
|
|
<span
|
|
class="read-card-link"
|
|
@click="readCardId"
|
|
>读取身份证</span>
|
|
</div>
|
|
|
|
<label class="radio-label">
|
|
<input
|
|
type="radio"
|
|
name="status"
|
|
value="unpaid"
|
|
:checked="chargeStatus === 'unpaid'"
|
|
@change="handleChargeStatusChange('unpaid')"
|
|
/>
|
|
<span>未收费</span>
|
|
</label>
|
|
<label class="radio-label">
|
|
<input
|
|
type="radio"
|
|
name="status"
|
|
value="paid"
|
|
:checked="chargeStatus === 'paid'"
|
|
@change="handleChargeStatusChange('paid')"
|
|
/>
|
|
<span>已收费</span>
|
|
</label>
|
|
</div>
|
|
|
|
<!-- 添加时间筛选 -->
|
|
<div class="view-options">
|
|
<div class="view-buttons">
|
|
<button
|
|
v-for="period in timePeriods"
|
|
:key="period.value"
|
|
class="view-btn"
|
|
:class="{ active: selectedPeriod === period.value }"
|
|
@click="handlePeriodChange(period.value)"
|
|
>
|
|
{{ period.label }}
|
|
</button>
|
|
</div>
|
|
|
|
<!-- 添加日期选择器 -->
|
|
<div v-if="showDatePicker" class="date-picker-container">
|
|
<div class="date-picker-wrapper">
|
|
<el-date-picker
|
|
v-model="customDateRange"
|
|
type="daterange"
|
|
unlink-panels
|
|
range-separator="至"
|
|
start-placeholder="开始日期"
|
|
end-placeholder="结束日期"
|
|
:shortcuts="shortcuts"
|
|
format="YYYY-MM-DD"
|
|
value-format="YYYY-MM-DD"
|
|
/>
|
|
</div>
|
|
<el-button
|
|
type="primary"
|
|
@click="handleDateSearch"
|
|
class="search-button"
|
|
>搜索</el-button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 搜索框 -->
|
|
<div class="search-box">
|
|
<input
|
|
type="text"
|
|
v-model="searchQuery"
|
|
placeholder="请输入姓名"
|
|
@input="handleSearch"
|
|
/>
|
|
<i class="el-icon-search search-icon"></i>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="list-content">
|
|
<div
|
|
v-for="patient in patients"
|
|
:key="patient.id"
|
|
class="patient-item"
|
|
@click="handlePatientSelect(patient)"
|
|
:class="{ active: selectedPatient?.id === patient.id }"
|
|
>
|
|
<div class="patient-info">
|
|
<span class="name">{{ patient.pname }}</span>
|
|
<span class="medical-sn">{{ patient.medicalSn }}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 分页 -->
|
|
<div class="pagination-container">
|
|
<el-pagination
|
|
v-model:current-page="pageNo"
|
|
:page-size="20"
|
|
small
|
|
:total="total"
|
|
layout="total, prev, pager, next, jumper"
|
|
@current-change="handleCurrentChange"
|
|
>
|
|
<template #total>
|
|
<span>共 {{ total }} 条</span>
|
|
</template>
|
|
</el-pagination>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 右侧收费详情 -->
|
|
<div class="report-content" v-if="selectedPatient">
|
|
<!-- 基本信息 -->
|
|
<div class="basic-info">
|
|
<div class="info-grid">
|
|
<div class="info-row">
|
|
<div class="info-item">
|
|
<label>体检编号:</label>
|
|
<span>{{ patientData.medicalSn }}</span>
|
|
</div>
|
|
<div class="info-item">
|
|
<label>身份证号:</label>
|
|
<span>{{ patientData.cardId }}</span>
|
|
</div>
|
|
<div class="info-item">
|
|
<label>姓名:</label>
|
|
<span>{{ patientData.pname }}</span>
|
|
</div>
|
|
<div class="info-item">
|
|
<label>性别:</label>
|
|
<span>{{ patientData.gender }}</span>
|
|
</div>
|
|
</div>
|
|
<div class="info-row">
|
|
<div class="info-item">
|
|
<label>年龄:</label>
|
|
<span>{{ age }}岁</span>
|
|
</div>
|
|
<div class="info-item">
|
|
<label>电话:</label>
|
|
<span>{{ patientData.phoneNum }}</span>
|
|
</div>
|
|
<div class="info-item">
|
|
<label>国籍:</label>
|
|
<span>{{ patientData.nationality }}</span>
|
|
</div>
|
|
<div class="info-item">
|
|
<label>民族:</label>
|
|
<span>{{ patientData.nation }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 收费表单 -->
|
|
<div class="charge-form">
|
|
<div class="section-title">收费信息</div>
|
|
<div class="result-table">
|
|
<!-- 表头部分 -->
|
|
<div class="table-header">
|
|
<div class="header-row">
|
|
<div class="header-cell" style="width: 5%">#</div>
|
|
<div class="header-cell" style="width: 40%">项目名称</div>
|
|
<div class="header-cell" style="width: 20%">单价</div>
|
|
<div class="header-cell" style="width: 15%">折扣</div>
|
|
<div class="header-cell" style="width: 20%">折后价</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 表格内容部分 -->
|
|
<div class="table-body">
|
|
<div
|
|
v-for="(item, index) in form.items"
|
|
:key="item.id"
|
|
class="table-row"
|
|
>
|
|
<div class="table-cell fixed-cell" style="width: 5%">{{ index + 1 }}</div>
|
|
<div class="table-cell fixed-cell" style="width: 40%">{{ item.itemName }}</div>
|
|
<div class="table-cell" style="width: 20%">¥ {{ item.price }}</div>
|
|
<div class="table-cell" style="width: 15%">
|
|
<template v-if="!selectedPatient.chargeType">
|
|
<el-input-number
|
|
v-model="item.discounted"
|
|
:min="0"
|
|
:max="100"
|
|
:precision="0"
|
|
@change="handleDiscountChange(item)"
|
|
size="small"
|
|
/>%
|
|
</template>
|
|
<template v-else>
|
|
{{ item.discounted }}%
|
|
</template>
|
|
</div>
|
|
<div class="table-cell" style="width: 20%">¥ {{ item.discountedPrice }}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 收费信息汇总 -->
|
|
<div class="charge-summary">
|
|
<div class="summary-item">
|
|
<label>收费方式:</label>
|
|
<template v-if="!selectedPatient.chargeType">
|
|
<el-select v-model="form.chargeType" placeholder="请选择收费方式">
|
|
<el-option
|
|
v-for="item in chargeTypes"
|
|
:key="item.value"
|
|
:label="item.label"
|
|
:value="item.value"
|
|
/>
|
|
</el-select>
|
|
</template>
|
|
<template v-else>
|
|
<span>{{ getChargeTypeLabel(selectedPatient.chargeType) }}</span>
|
|
</template>
|
|
</div>
|
|
<div class="summary-item">
|
|
<label>应收金额:</label>
|
|
<span class="total-amount">¥ {{ totalAmount }}</span>
|
|
</div>
|
|
<div class="summary-item">
|
|
<label>实收金额:</label>
|
|
<template v-if="!selectedPatient.chargeType">
|
|
<el-input-number
|
|
v-model="form.actualAmount"
|
|
:min="0"
|
|
:precision="2"
|
|
:step="0.01"
|
|
/>
|
|
</template>
|
|
<template v-else>
|
|
<span>¥ {{ selectedPatient.totalPrice }}</span>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 底部操作栏 -->
|
|
<div class="form-footer">
|
|
<div class="operator-info">
|
|
<span>收费人员:{{ user?.nickname }}</span>
|
|
<span v-if="selectedPatient?.chargeType" class="charge-time">
|
|
收费时间:{{ formatDateTime(selectedPatient.chargetime) }}
|
|
</span>
|
|
</div>
|
|
<div class="form-buttons">
|
|
<el-button
|
|
@click="handlePrint"
|
|
v-if="selectedPatient.chargeType"
|
|
>打印小票</el-button>
|
|
<el-button
|
|
type="primary"
|
|
@click="handleSubmitCharge"
|
|
v-if="!selectedPatient.chargeType"
|
|
>确认收费</el-button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 未选择患者时的空状态 -->
|
|
<div class="empty-content" v-else>
|
|
<el-empty description="请选择左侧体检人员"/>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, onMounted, computed } from 'vue'
|
|
import { itemsApi } from '@/api/inspect/inspectitems'
|
|
import { PatientApi } from '@/api/inspect/inspectpatient'
|
|
import { PatientitemsApi } from '@/api/inspect/inspectpatientitems'
|
|
import { getUserProfile } from '@/api/system/user/profile'
|
|
import { ElMessage } from 'element-plus'
|
|
import { store } from '@/store'
|
|
|
|
const chargeType = ref('')
|
|
const form = ref({
|
|
chargeType: '',
|
|
items: [],
|
|
actualAmount: 0,
|
|
patientId: null
|
|
})
|
|
|
|
// 添加分页相关数据
|
|
const pageNo = ref(1)
|
|
const total = ref(0)
|
|
const patients = ref([])
|
|
const selectedPatient = ref(null)
|
|
const searchQuery = ref('')
|
|
|
|
// 添加收费状态相关的响应式数据
|
|
const chargeStatus = ref('unpaid') // 默认显示未收费
|
|
|
|
// 添加时间周期选项
|
|
const timePeriods = [
|
|
{ label: '今日', value: 'today' },
|
|
{ label: '本周', value: 'week' },
|
|
{ label: '本月', value: 'month' },
|
|
{ label: '自定义', value: 'custom' },
|
|
{ label: '重置', value: 'reset' }
|
|
]
|
|
|
|
// 添加日期相关的响应式数据
|
|
const selectedPeriod = ref('today')
|
|
const showDatePicker = ref(false)
|
|
const customDateRange = ref([])
|
|
const pageSize = ref(20)
|
|
// 添加日期快捷选项
|
|
const shortcuts = [
|
|
{
|
|
text: '最近一周',
|
|
value: () => {
|
|
const end = new Date()
|
|
const start = new Date()
|
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
|
|
return [start, end]
|
|
},
|
|
},
|
|
{
|
|
text: '最近一个月',
|
|
value: () => {
|
|
const end = new Date()
|
|
const start = new Date()
|
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
|
|
return [start, end]
|
|
},
|
|
},
|
|
{
|
|
text: '最近三个月',
|
|
value: () => {
|
|
const end = new Date()
|
|
const start = new Date()
|
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
|
|
return [start, end]
|
|
},
|
|
},
|
|
]
|
|
|
|
// 添加原始数据缓存
|
|
const originalPatients = ref([])
|
|
|
|
// 添加患者详情数据
|
|
const patientData = ref({})
|
|
|
|
// 收费方式选项
|
|
const chargeTypes = [
|
|
{ value: 'cash', label: '现金' },
|
|
{ value: 'alipay', label: '支付宝' },
|
|
{ value: 'wechat', label: '微信' },
|
|
{ value: 'card', label: '银行卡' },
|
|
{ value: 'medical', label: '医保卡' },
|
|
{ value: 'credit', label: '信用卡' },
|
|
{ value: 'transfer', label: '转账' },
|
|
{ value: 'other', label: '其他' }
|
|
]
|
|
|
|
// 修改用户信息相关的代码
|
|
const user = ref(null)
|
|
|
|
// 获取当前用户信息
|
|
const getCurrentUser = async () => {
|
|
try {
|
|
const res = await getUserProfile()
|
|
user.value = res
|
|
} catch (error) {
|
|
console.error('获取用户信息失败:', error)
|
|
ElMessage.error('获取用户信息失败')
|
|
}
|
|
}
|
|
|
|
// 获取患者体检项目数据
|
|
const getPatientItems = async (medicalSn) => {
|
|
try {
|
|
const params = {
|
|
medicalSn: medicalSn,
|
|
pageNo: 1,
|
|
pageSize: 100
|
|
}
|
|
const itemsRes = await PatientitemsApi.getPatientitemsPage(params)
|
|
if (itemsRes.list && itemsRes.list.length > 0) {
|
|
// 处理项目数据,添加折扣相关字段
|
|
form.value.items = itemsRes.list.map(item => ({
|
|
...item,
|
|
discounted: 100, // 默认折扣100%
|
|
discountedPrice: item.price // 默认折后价等于原价
|
|
}))
|
|
|
|
// 计算总金额
|
|
form.value.actualAmount = form.value.items.reduce((sum, item) =>
|
|
sum + (item.discountedPrice || 0), 0
|
|
)
|
|
}
|
|
} catch (error) {
|
|
console.error('获取体检项目失败:', error)
|
|
ElMessage.error('获取体检项目失败')
|
|
}
|
|
}
|
|
|
|
// 处理患者选择
|
|
const handlePatientSelect = async (patient) => {
|
|
try {
|
|
// 清理之前的数据
|
|
form.value = {
|
|
chargeType: '',
|
|
items: [],
|
|
actualAmount: 0,
|
|
patientId: null
|
|
}
|
|
patientData.value = {}
|
|
|
|
// 设置新选中的患者
|
|
selectedPatient.value = patient
|
|
|
|
// 获取患者详细信息
|
|
const res = await PatientApi.getPatient(patient.id)
|
|
patientData.value = res
|
|
|
|
// 如果有体检编号,获取体检项目数据
|
|
if (patient.medicalSn) {
|
|
await getPatientItems(patient.medicalSn)
|
|
}
|
|
} catch (error) {
|
|
console.error('获取患者详情失败:', error)
|
|
ElMessage.error('获取患者详情失败')
|
|
}
|
|
}
|
|
|
|
// 修改按日期获取患者列表方法
|
|
const fetchPatientsByDate = async () => {
|
|
try {
|
|
if (!customDateRange.value || customDateRange.value.length !== 2) return
|
|
|
|
const [startDate, endDate] = customDateRange.value
|
|
const params = {
|
|
pageNo: pageNo.value,
|
|
pageSize: pageSize.value,
|
|
medicalDateTime: [
|
|
`${formatDate(startDate)} 00:00:00`,
|
|
`${formatDate(endDate)} 23:59:59`
|
|
]
|
|
}
|
|
|
|
const res = await PatientApi.getPatientPage(params)
|
|
originalPatients.value = res.list
|
|
|
|
// 根据当前选中的收费状态过滤患者列表
|
|
patients.value = res.list.filter(patient => {
|
|
if (chargeStatus.value === 'unpaid') {
|
|
return !patient.chargeType
|
|
} else {
|
|
return patient.chargeType
|
|
}
|
|
})
|
|
|
|
total.value = patients.value.length
|
|
|
|
// 如果没有查询到患者,清除选中状态
|
|
if (!patients.value.length) {
|
|
selectedPatient.value = null
|
|
}
|
|
} catch (error) {
|
|
console.error('获取患者列表失败:', error)
|
|
ElMessage.error('获取患者列表失败')
|
|
}
|
|
}
|
|
|
|
// 修改收费状态切换处理方法
|
|
const handleChargeStatusChange = (status) => {
|
|
// 清除选中状态
|
|
selectedPatient.value = null
|
|
patientData.value = {}
|
|
|
|
chargeStatus.value = status
|
|
// 从原始数据中筛选
|
|
if (originalPatients.value.length) {
|
|
patients.value = originalPatients.value.filter(patient => {
|
|
if (status === 'unpaid') {
|
|
return !patient.chargeType
|
|
} else {
|
|
return patient.chargeType
|
|
}
|
|
})
|
|
total.value = patients.value.length
|
|
}
|
|
}
|
|
|
|
// 修改时间周期切换处理方法
|
|
const handlePeriodChange = (period) => {
|
|
selectedPeriod.value = period
|
|
|
|
// 清除选中状态
|
|
selectedPatient.value = null
|
|
|
|
const today = new Date()
|
|
let startDate, endDate
|
|
|
|
switch (period) {
|
|
case 'today':
|
|
startDate = new Date(today.setHours(0, 0, 0, 0))
|
|
endDate = new Date(today.setHours(23, 59, 59, 999))
|
|
customDateRange.value = [startDate, endDate]
|
|
showDatePicker.value = false
|
|
fetchPatientsByDate()
|
|
break
|
|
|
|
case 'week':
|
|
startDate = new Date(today)
|
|
startDate.setDate(today.getDate() - today.getDay())
|
|
endDate = new Date(today)
|
|
endDate.setDate(startDate.getDate() + 6)
|
|
customDateRange.value = [startDate, endDate]
|
|
showDatePicker.value = false
|
|
fetchPatientsByDate()
|
|
break
|
|
|
|
case 'month':
|
|
startDate = new Date(today.getFullYear(), today.getMonth(), 1)
|
|
endDate = new Date(today.getFullYear(), today.getMonth() + 1, 0)
|
|
customDateRange.value = [startDate, endDate]
|
|
showDatePicker.value = false
|
|
fetchPatientsByDate()
|
|
break
|
|
|
|
case 'custom':
|
|
showDatePicker.value = !showDatePicker.value
|
|
patients.value = [] // 清空患者列表
|
|
customDateRange.value = [] // 清空日期范围
|
|
break
|
|
|
|
case 'reset':
|
|
selectedPeriod.value = 'today'
|
|
const todayStart = new Date(today.setHours(0, 0, 0, 0))
|
|
const todayEnd = new Date(today.setHours(23, 59, 59, 999))
|
|
customDateRange.value = [todayStart, todayEnd]
|
|
showDatePicker.value = false
|
|
fetchPatientsByDate()
|
|
break
|
|
}
|
|
}
|
|
|
|
// 修改日期搜索处理方法
|
|
const handleDateSearch = () => {
|
|
if (customDateRange.value && customDateRange.value.length === 2) {
|
|
// 清除之前的数据
|
|
selectedPatient.value = null
|
|
originalPatients.value = []
|
|
patients.value = []
|
|
fetchPatientsByDate()
|
|
} else {
|
|
ElMessage.warning('请选择日期范围')
|
|
}
|
|
}
|
|
|
|
// 组件挂载时初始化
|
|
onMounted(() => {
|
|
// 获取用户信息
|
|
getCurrentUser()
|
|
|
|
// 设置默认为今日
|
|
const today = new Date()
|
|
selectedPeriod.value = 'today'
|
|
const todayStart = new Date(today.setHours(0, 0, 0, 0))
|
|
const todayEnd = new Date(today.setHours(23, 59, 59, 999))
|
|
customDateRange.value = [todayStart, todayEnd]
|
|
|
|
// 获取今日数据
|
|
fetchPatientsByDate()
|
|
})
|
|
|
|
// 日期格式化
|
|
const formatDate = (date) => {
|
|
if (!date) return ''
|
|
const d = new Date(date)
|
|
const year = d.getFullYear()
|
|
const month = String(d.getMonth() + 1).padStart(2, '0')
|
|
const day = String(d.getDate()).padStart(2, '0')
|
|
return `${year}-${month}-${day}`
|
|
}
|
|
|
|
// 获取状态文本
|
|
const getStatusText = (status) => {
|
|
const statusMap = {
|
|
'0': '待收费',
|
|
'1': '已收费',
|
|
'2': '已取消'
|
|
}
|
|
return statusMap[status] || '待收费'
|
|
}
|
|
|
|
// 处理折扣变化
|
|
const handleDiscountChange = (item) => {
|
|
if (item.price) {
|
|
item.discountedPrice = Number((item.price * (item.discounted / 100)).toFixed(2))
|
|
// 更新总金额
|
|
form.value.actualAmount = form.value.items.reduce((sum, item) =>
|
|
sum + (item.discountedPrice || 0), 0
|
|
)
|
|
}
|
|
}
|
|
|
|
// 计算总金额
|
|
const totalAmount = computed(() => {
|
|
return form.value.items.reduce((sum, item) => sum + (item.discountedPrice || item.price || 0), 0)
|
|
})
|
|
|
|
// 当前时间
|
|
const currentDateTime = computed(() => {
|
|
return formatDate(new Date()) + ' ' +
|
|
new Date().toLocaleTimeString('zh-CN', { hour12: false })
|
|
})
|
|
|
|
// 添加打印小票方法
|
|
const handlePrint = () => {
|
|
// 实现打印逻辑
|
|
ElMessage.info('打印功能开发中')
|
|
}
|
|
|
|
// 添加格式化时间的辅助函数
|
|
const formatSubmitDateTime = (date) => {
|
|
const pad = (num) => String(num).padStart(2, '0')
|
|
const d = new Date(date)
|
|
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`
|
|
}
|
|
|
|
const handleSubmitCharge = async () => {
|
|
try {
|
|
if (!form.value.chargeType) {
|
|
ElMessage.warning('请选择收费方式')
|
|
return
|
|
}
|
|
|
|
if (!form.value.actualAmount) {
|
|
ElMessage.warning('请输入实收金额')
|
|
return
|
|
}
|
|
|
|
const updateData = {
|
|
id: selectedPatient.value.id,
|
|
chargeType: form.value.chargeType,
|
|
totalPrice: form.value.actualAmount,
|
|
chargetime: new Date().getTime()
|
|
}
|
|
|
|
await PatientApi.updatePatient(updateData)
|
|
|
|
ElMessage.success('收费成功')
|
|
|
|
// 重新获取患者列表数据
|
|
const params = {
|
|
pageNo: pageNo.value,
|
|
pageSize: pageSize.value,
|
|
medicalDateTime: customDateRange.value ? [
|
|
`${formatDate(customDateRange.value[0])} 00:00:00`,
|
|
`${formatDate(customDateRange.value[1])} 23:59:59`
|
|
] : undefined
|
|
}
|
|
|
|
const listRes = await PatientApi.getPatientPage(params)
|
|
originalPatients.value = listRes.list
|
|
|
|
// 根据当前收费状态过滤并更新患者列表
|
|
patients.value = listRes.list.filter(patient => {
|
|
if (chargeStatus.value === 'unpaid') {
|
|
return !patient.chargeType
|
|
} else {
|
|
return patient.chargeType
|
|
}
|
|
})
|
|
total.value = patients.value.length
|
|
|
|
// 重新获取并更新当前选中患者的信息
|
|
const patientRes = await PatientApi.getPatient(selectedPatient.value.id)
|
|
selectedPatient.value = patientRes
|
|
patientData.value = patientRes
|
|
|
|
} catch (error) {
|
|
console.error('收费提交失败:', error)
|
|
ElMessage.error('收费提交失败')
|
|
}
|
|
}
|
|
|
|
// 计算年龄
|
|
const age = computed(() => {
|
|
if (!patientData.value?.birthday) return ''
|
|
const birthDate = new Date(patientData.value.birthday)
|
|
const today = new Date()
|
|
let age = today.getFullYear() - birthDate.getFullYear()
|
|
const monthDiff = today.getMonth() - birthDate.getMonth()
|
|
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
|
|
age--
|
|
}
|
|
return age
|
|
})
|
|
|
|
// 添加获取收费方式标签的方法
|
|
const getChargeTypeLabel = (value) => {
|
|
const type = chargeTypes.find(t => t.value === value)
|
|
return type ? type.label : ''
|
|
}
|
|
|
|
// 添加格式化日期时间的方法
|
|
const formatDateTime = (datetime) => {
|
|
if (!datetime) return ''
|
|
const d = new Date(datetime)
|
|
const year = d.getFullYear()
|
|
const month = String(d.getMonth() + 1).padStart(2, '0')
|
|
const day = String(d.getDate()).padStart(2, '0')
|
|
const hour = String(d.getHours()).padStart(2, '0')
|
|
const minute = String(d.getMinutes()).padStart(2, '0')
|
|
const second = String(d.getSeconds()).padStart(2, '0')
|
|
return `${year}-${month}-${day} ${hour}:${minute}:${second}`
|
|
}
|
|
|
|
// ... 其他方法实现
|
|
</script>
|
|
|
|
<style scoped>
|
|
.charge-container {
|
|
display: flex;
|
|
height: 83vh;
|
|
min-height: 600px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.patient-list {
|
|
width: 280px;
|
|
background: #fff;
|
|
border-right: 1px solid #e6e6e6;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.list-header {
|
|
padding: 15px;
|
|
border-bottom: 1px solid #e6e6e6;
|
|
}
|
|
|
|
.header-title {
|
|
font-size: 14px;
|
|
color: #333;
|
|
margin-bottom: 15px;
|
|
}
|
|
|
|
.search-box {
|
|
position: relative;
|
|
}
|
|
|
|
.search-box input {
|
|
width: 100%;
|
|
padding: 8px 30px 8px 10px;
|
|
border: 1px solid #dcdfe6;
|
|
border-radius: 4px;
|
|
font-size: 13px;
|
|
}
|
|
|
|
.search-icon {
|
|
position: absolute;
|
|
right: 10px;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
color: #c0c4cc;
|
|
}
|
|
|
|
.list-content {
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.patient-item {
|
|
padding: 12px 15px;
|
|
border-bottom: 1px solid #e6e6e6;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.patient-item:hover {
|
|
background-color: #f5f7fa;
|
|
}
|
|
|
|
.patient-item.active {
|
|
background-color: #ecf5ff;
|
|
}
|
|
|
|
.patient-info {
|
|
display: flex;
|
|
gap: 10px;
|
|
align-items: center;
|
|
}
|
|
|
|
.name {
|
|
font-size: 14px;
|
|
color: #333;
|
|
}
|
|
|
|
.medical-sn {
|
|
color: #909399;
|
|
font-size: 12px;
|
|
}
|
|
|
|
.report-content {
|
|
flex: 1;
|
|
background: #fff;
|
|
padding: 20px;
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.basic-info {
|
|
display: flex;
|
|
padding: 20px;
|
|
border-bottom: 1px solid #ebeef5;
|
|
}
|
|
|
|
.info-grid {
|
|
flex: 1;
|
|
}
|
|
|
|
.info-row {
|
|
display: flex;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.info-item {
|
|
flex: 1;
|
|
min-width: 200px;
|
|
}
|
|
|
|
.info-item label {
|
|
color: #606266;
|
|
margin-right: 8px;
|
|
}
|
|
|
|
.empty-content {
|
|
flex: 1;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
background: #fff;
|
|
}
|
|
|
|
.pagination-container {
|
|
padding: 10px;
|
|
background: #fff;
|
|
border-top: 1px solid #e6e6e6;
|
|
margin-top: auto;
|
|
}
|
|
|
|
/* 添加新的样式 */
|
|
.filter-options {
|
|
padding: 10px 15px;
|
|
border-bottom: 1px solid #e6e6e6;
|
|
}
|
|
|
|
.radio-label {
|
|
margin-right: 20px;
|
|
cursor: pointer;
|
|
font-size: 14px;
|
|
color: #606266;
|
|
}
|
|
|
|
.radio-label input[type="radio"] {
|
|
margin-right: 4px;
|
|
vertical-align: middle;
|
|
}
|
|
|
|
.view-options {
|
|
padding: 10px 15px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
border-bottom: 1px solid #e6e6e6;
|
|
}
|
|
|
|
.view-buttons {
|
|
display: flex;
|
|
gap: 8px;
|
|
}
|
|
|
|
.view-btn {
|
|
padding: 5px 12px;
|
|
border: none;
|
|
background: none;
|
|
cursor: pointer;
|
|
font-size: 13px;
|
|
color: #606266;
|
|
border-radius: 3px;
|
|
}
|
|
|
|
.view-btn:hover {
|
|
color: #409EFF;
|
|
background: #ecf5ff;
|
|
}
|
|
|
|
.view-btn.active {
|
|
color: #409EFF;
|
|
background: #ecf5ff;
|
|
}
|
|
|
|
.date-picker-container {
|
|
margin-top: 10px;
|
|
background: #fff;
|
|
padding: 10px 0;
|
|
width: 100%;
|
|
}
|
|
|
|
.date-picker-wrapper {
|
|
display: flex;
|
|
gap: 10px;
|
|
align-items: center;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.search-button {
|
|
width: 100%;
|
|
margin-top: 8px;
|
|
height: 32px;
|
|
}
|
|
|
|
.read-card-link {
|
|
margin-left: 40px;
|
|
color: #409EFF;
|
|
cursor: pointer;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.read-card-link:hover {
|
|
color: #66b1ff;
|
|
}
|
|
|
|
/* 美化滚动条样式 */
|
|
.report-content::-webkit-scrollbar {
|
|
width: 6px;
|
|
height: 6px;
|
|
}
|
|
|
|
.report-content::-webkit-scrollbar-thumb {
|
|
background: #c0c4cc;
|
|
border-radius: 3px;
|
|
}
|
|
|
|
.report-content::-webkit-scrollbar-track {
|
|
background: #f5f7fa;
|
|
}
|
|
|
|
.charge-form {
|
|
padding: 20px;
|
|
margin-top: 20px;
|
|
}
|
|
|
|
.section-title {
|
|
font-size: 16px;
|
|
font-weight: 500;
|
|
color: #303133;
|
|
margin-bottom: 20px;
|
|
padding-left: 10px;
|
|
border-left: 4px solid #409eff;
|
|
}
|
|
|
|
.charge-form-content {
|
|
padding: 20px;
|
|
background: #f8f9fa;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.form-select {
|
|
width: 200px;
|
|
}
|
|
|
|
.items-table {
|
|
margin: 10px 0;
|
|
}
|
|
|
|
.total-amount {
|
|
font-size: 20px;
|
|
color: #f56c6c;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.amount-input {
|
|
width: 200px;
|
|
}
|
|
|
|
.form-footer {
|
|
margin-top: 30px;
|
|
padding: 20px;
|
|
border-top: 1px solid #ebeef5;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
|
|
.operator-info {
|
|
color: #606266;
|
|
font-size: 14px;
|
|
display: flex;
|
|
gap: 20px;
|
|
}
|
|
|
|
.charge-time {
|
|
color: #909399;
|
|
}
|
|
|
|
.form-buttons {
|
|
display: flex;
|
|
gap: 10px;
|
|
}
|
|
|
|
/* 表格样式 */
|
|
.result-table {
|
|
margin: 20px 0;
|
|
border: 1px solid #ebeef5;
|
|
border-radius: 4px;
|
|
height: 520px; /* 固定高度 */
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.table-header {
|
|
background: #f5f7fa;
|
|
border-bottom: 1px solid #ebeef5;
|
|
}
|
|
|
|
.header-row {
|
|
display: flex;
|
|
width: 100%;
|
|
}
|
|
|
|
.header-cell {
|
|
padding: 12px 8px;
|
|
font-weight: 500;
|
|
color: #606266;
|
|
text-align: left;
|
|
border-right: 1px solid #ebeef5;
|
|
}
|
|
|
|
.table-body {
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
overflow-x: hidden;
|
|
}
|
|
|
|
.table-row {
|
|
display: flex;
|
|
border-bottom: 1px solid #ebeef5;
|
|
position: relative;
|
|
}
|
|
|
|
.table-cell {
|
|
padding: 12px 8px;
|
|
border-right: 1px solid #ebeef5;
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
/* 固定列样式 */
|
|
.fixed-cell {
|
|
position: sticky;
|
|
background: #fff;
|
|
z-index: 1;
|
|
}
|
|
|
|
.table-row .fixed-cell:nth-child(1) {
|
|
left: 0;
|
|
}
|
|
|
|
.table-row .fixed-cell:nth-child(2) {
|
|
left: 5%;
|
|
}
|
|
|
|
/* 禁用行样式 */
|
|
.disabled-row {
|
|
background-color: #f5f7fa;
|
|
color: #909399;
|
|
}
|
|
|
|
/* 美化滚动条 */
|
|
.table-body::-webkit-scrollbar {
|
|
width: 6px;
|
|
height: 6px;
|
|
}
|
|
|
|
.table-body::-webkit-scrollbar-thumb {
|
|
background: #c0c4cc;
|
|
border-radius: 3px;
|
|
}
|
|
|
|
.table-body::-webkit-scrollbar-track {
|
|
background: #f5f7fa;
|
|
}
|
|
|
|
/* 弃检状态样式 */
|
|
.table-row[data-item-status="2"] {
|
|
background-color: #ebeef5;
|
|
color: #606266;
|
|
}
|
|
|
|
.table-row[data-item-status="2"] .el-dropdown {
|
|
opacity: 0.8;
|
|
}
|
|
|
|
/* 收费信息汇总样式 */
|
|
.charge-summary {
|
|
margin-top: 30px;
|
|
padding: 10px;
|
|
background: #f8f9fa;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.summary-item {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-bottom: 15px;
|
|
}
|
|
|
|
.summary-item label {
|
|
width: 100px;
|
|
color: #606266;
|
|
}
|
|
|
|
/* 添加收费方式下拉框的宽度限制 */
|
|
.summary-item :deep(.el-select) {
|
|
width: 160px; /* 调整下拉框宽度 */
|
|
}
|
|
|
|
.total-amount {
|
|
font-size: 20px;
|
|
color: #f56c6c;
|
|
font-weight: bold;
|
|
}
|
|
|
|
/* 添加已收费状态的样式 */
|
|
.charge-form.charged {
|
|
opacity: 0.8;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.charge-summary span {
|
|
font-size: 14px;
|
|
color: #606266;
|
|
}
|
|
</style> |