inspect-front/src/views/sta/index.vue
2025-06-24 17:25:52 +08:00

431 lines
13 KiB
Vue

<template>
<ContentWrap>
<el-row>
<el-form-item label="统计时间">
<el-radio-group v-model="radioType" @change="changeRadio">
<el-radio v-for="item in radioSelector" :value="item.value" :key="item.value">{{
item.label
}}</el-radio>
</el-radio-group>
<el-date-picker
style="margin-left: 10px"
value-format="YYYY-MM-DD"
v-model="time"
type="daterange"
range-separator="To"
start-placeholder="开始时间"
end-placeholder="结束时间"
:default-time="[new Date().getDate() - 7, new Date()]"
:shortcuts="shortcuts"
size="big"
@change="changeDatePick"
/>
<el-form-item label="当前机构" style="margin-left: 10px">
<el-select v-model="selectedHospital" placeholder="请选择当前机构" style="width: 200px" clearable>
<el-option
v-for="item in hospitals"
:key="item.code"
:label="item.name"
:value="item.code"
/>
</el-select>
</el-form-item>
<el-button type="primary" @click="getList" style="margin-left: 20px">
<Icon icon="ep:search" class="mr-5px" /> 查询
</el-button>
<el-button type="primary" @click="printData" style="margin-left: 20px">
<Icon icon="ep:printer" class="mr-5px" /> 打印
</el-button>
<el-button
type="primary"
@click="exportExcel"
style="margin-left: 20px"
:loading="exportLoading"
>
<Icon icon="ep:download" class="mr-5px" /> 导出excel
</el-button>
</el-form-item>
</el-row>
</ContentWrap>
<ContentWrap>
<el-table
:data="data1"
show-summary
max-height="650"
default-expand-all
row-key="orgname"
:tree-props="{ children: 'children' }"
:default-sort="{ prop: 'sum', order: 'descending' }"
>
<el-table-column label="卫生院" align="left" min-width="180">
<template #default="{ row }">
<span v-if="row.children">{{ row.orgname || '未知' }}</span>
</template>
</el-table-column>
<el-table-column label="行政村" align="center" min-width="160">
<template #default="{ row }">
<span v-if="!row.children">{{ row.districtname || '未知' }}</span>
</template>
</el-table-column>
<el-table-column label="体检数" align="center">
<el-table-column label="老年人" align="center" prop="oldmanflag" min-width="80" />
<el-table-column label="高血压" align="center" prop="htnflag" min-width="80" />
<el-table-column label="糖尿病" align="center" prop="diaflag" min-width="80" />
<el-table-column label="精神病" align="center" prop="smiflag" min-width="80" />
<el-table-column label="肺结核" align="center" prop="pulflag" min-width="80" />
<el-table-column label="总人数" align="center" prop="sum" min-width="80" />
<el-table-column label="操作" align="center" width="120">
<template #default="{ row }">
<el-button v-if="!row.children" link type="primary" @click="handleDetail(row)">
详情
</el-button>
</template>
</el-table-column>
</el-table-column>
</el-table>
</ContentWrap>
<!-- 详情对话框 -->
<el-dialog
v-model="dialogVisible"
title="体检详情"
width="90%"
:close-on-click-modal="false"
>
<el-table
:data="detailData"
border
style="width: 100%"
height="600"
:max-height="600"
>
<el-table-column label="体检编号" prop="medicalSn" align="center" min-width="120" />
<el-table-column label="姓名" prop="pname" align="center" min-width="100" />
<el-table-column label="身份证号" prop="cardId" align="center" min-width="180" />
<el-table-column label="性别" prop="gender" align="center" min-width="80" />
<el-table-column label="老年人" align="center" min-width="80">
<template #default="{ row }">
{{ row.oldmanflag == 1 ? '是' : '否' }}
</template>
</el-table-column>
<el-table-column label="高血压" align="center" min-width="80">
<template #default="{ row }">
{{ row.htnflag == 1 ? '是' : '否' }}
</template>
</el-table-column>
<el-table-column label="糖尿病" align="center" min-width="80">
<template #default="{ row }">
{{ row.diaflag == 1 ? '是' : '否' }}
</template>
</el-table-column>
<el-table-column label="精神病" align="center" min-width="80">
<template #default="{ row }">
{{ row.smiflag == 1 ? '是' : '否' }}
</template>
</el-table-column>
<el-table-column label="肺结核" align="center" min-width="80">
<template #default="{ row }">
{{ row.pulflag == 1 ? '是' : '否' }}
</template>
</el-table-column>
</el-table>
</el-dialog>
</template>
<script setup lang="ts">
import dayjs from 'dayjs'
import { PatientApi } from '@/api/inspect/inspectpatient'
import { formatDate } from '@/utils/formatTime'
import workload from './workload'
import { hiprint } from 'vue-plugin-hiprint'
import { newHiprintPrintTemplate, preparePrintData } from './printHelper'
import download from '@/utils/download'
import { getUserProfile } from '@/api/system/user/profile'
import { InspectOrgApi } from '@/api/inspect/inspectorg'
import { hospitals } from '@/config/hospitals'
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
const loading = ref(true) // 列表的加载中
const time = ref() // 日期
const data1 = ref([])
const radioSelector = ref([
{ value: 2, label: '今天' },
{ value: 3, label: '最近一周' },
{ value: 4, label: '最近一个月' }
])
const radioType = ref(3) //
const shortcuts = [
{
text: '最近一周',
value: () => {
const end = new Date()
const start = new Date()
start.setDate(start.getDate() - 7)
return [start, end]
}
},
{
text: '最近一个月',
value: () => {
const end = new Date()
const start = new Date()
start.setMonth(start.getMonth() - 1)
return [start, end]
}
},
{
text: '今日',
value: () => {
const end = new Date()
const start = new Date()
return [start, end]
}
}
]
const dialogVisible = ref(false) // 控制对话框显示
const detailData = ref([]) // 详情数据
const selectedHospital = ref<string>('') // 选中的医院
/**
* 改变单选框
* @param e
*/
const changeRadio = (e) => {
let end = new Date()
let start = new Date()
let date = null
switch (e) {
case 2:
start = new Date()
end = new Date()
break
case 3:
start.setDate(start.getDate() - 7)
break
case 4:
start.setMonth(start.getMonth() - 1)
break
default:
start.setDate(start.getDate() - 7)
}
time.value = [formatDate(start, 'YYYY-MM-DD'), formatDate(end, 'YYYY-MM-DD')]
// 清空现有数据
data1.value = []
}
const changeDatePick = () => {
radioType.value = null
// getList()
}
const userInfo = ref()
/**
* 获取统计数据
*/
const getList = async () => {
if (!selectedHospital.value) {
message.warning('请先选择机构')
return
}
// 清空现有数据
data1.value = []
// 获取用户信息和机构信息
// userInfo.value = await getUserProfile()
// const deptInfo = await InspectOrgApi.getInspectOrg(userInfo.value.deptId)
const params = {
dates: [dayjs(time.value[0]).format('YYYY-MM-DD'), dayjs(time.value[1]).format('YYYY-MM-DD')],
hospitalNo: selectedHospital.value
}
try {
let resp = await PatientApi.getData(params)
const rawData = toRaw(resp)
data1.value = dataProcessing(rawData)
} catch (error) {
console.error('获取数据失败:', error)
}
}
/**
* 统计数据处理
* @param data 需要处理的统计数据
*/
const dataProcessing = (data) => {
const result = data.reduce((acc, current) => {
const key = current.orgname
// 初始化分组(若不存在)
if (!acc[key]) {
acc[key] = {
orgname: key,
oldmanflag: 0,
htnflag: 0,
diaflag: 0,
smiflag: 0,
pulflag: 0,
sum: 0,
children: []
}
}
// 累加各字段值
acc[key].oldmanflag += current.oldmanflag
acc[key].htnflag += current.htnflag
acc[key].diaflag += current.diaflag
acc[key].smiflag += current.smiflag
acc[key].pulflag += current.pulflag
acc[key].sum += current.sum
// 将当前对象添加到 children 中,移除 orgname
const child = { ...current }
delete child.orgname
acc[key].children.push(child)
acc[key].children.sort((a, b) => b.sum - a.sum)
return acc
}, {})
let value = Object.values(result)
value.sort((a, b) => b.sum - a.sum)
return value
}
const exportLoading = ref(false) // 导出的加载中
const exportExcel = async () => {
// 导出的二次确认
await message.exportConfirm()
// 发起导出
try {
exportLoading.value = true
const data = await PatientApi.exportData({ dates: time.value })
download.excel(data, '统计.xls')
} catch (e) {
} finally {
exportLoading.value = false
}
}
/**
* 打印数据
*/
const printData = () => {
try {
// 创建打印模板
const hiprintTemplate = newHiprintPrintTemplate('workload', {
template: workload,
settingContainer: '#workloadPrintElementOptionSetting'
})
// 准备打印数据
const printData = preparePrintData(data1.value, time.value)
// 打印参数配置
const options = {
leftOffset: 0,
topOffset: 0,
paperType: 'A4',
enableColumnsMerge: true,
enableRowsMerge: true,
firstPageTitle: true,
onlyFirstTitle: true,
notAllowRepeat: ['title'],
firstPanelPageOnly: true,
pageMode: 'single',
displayMode: {
title: 'firstPage'
},
printPanelIndex: 0,
noRepeatPrint: false,
disableHeaderRepeat: false
}
// 样式设置
const ext = {
callback: () => {
console.log('打印窗口已打开')
// 添加表头样式
setTimeout(() => {
const table = document.querySelector('.hiprint-printPanel table')
if (table) {
const ths = table.querySelectorAll('th')
ths.forEach((th, index) => {})
}
}, 100)
},
styleHandler: () => {
return `<style>
@page {
size: A4;
margin: 0;
}
@media print {
body {
margin: 0;
padding: 0;
}
.hiprint-printPanel table th:nth-child(1) b,
.hiprint-printPanel table th:nth-child(2) b {
font-weight: bold !important;
font-size: 10px !important;
}
.hiprint-printPanel table td {
font-size: 10px;
}
td[colspan="0"],
td[rowspan="0"] {
display: none;
}
/* 强制隐藏除第一页外的标题 */
.hiprint-printPanel:not(:first-of-type) [data-options*='"title":"体检工作量统计表"'] {
display: none !important;
visibility: hidden !important;
height: 0 !important;
overflow: hidden !important;
position: absolute !important;
z-index: -1 !important;
}
/* 隐藏除第一页外的表头 */
.hiprint-printPanel:not(:first-of-type) .hiprint-table-header-row {
display: none !important;
}
}
</style>`
}
}
// 调用打印
hiprintTemplate.print(printData, options, ext)
console.log('打印成功')
} catch (error) {
console.error('打印失败:', error)
}
}
/**
* 处理详情按钮点击
* @param row 当前行数据
*/
const handleDetail = async (row) => {
try {
if (row.districtname == null) {
row.districtname='未知'
}
// 查找父节点
const parentNode = data1.value.find(item =>
item.children && item.children.some(child => child.districtname === row.districtname)
)
const params = {
stadate: time.value[0],
enddate: time.value[1],
addname: row.districtname,
examhosname: parentNode ? parentNode.orgname : row.orgname,
//orgid: userInfo.value.deptId
hospitalNo: selectedHospital.value
}
const res = await PatientApi.getPatientDetails(params)
detailData.value = res
dialogVisible.value = true
} catch (error) {
console.error('获取详情数据失败:', error)
message.error('获取详情数据失败')
}
}
onMounted(() => {
changeRadio(3)
// getList()
})
</script>
<style scoped></style>