Files
intc-vue3/src/views/health/marStatistic/index.vue
2024-12-23 13:10:20 +08:00

694 lines
22 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="app-container">
<div class="search-con">
<div class="title">查询条件</div>
<el-form :model="queryParams" ref="queryRef" :inline="true" :rules="rules" label-width="100px">
<el-form-item label="人员姓名" prop="id">
<el-select v-model="queryParams.id" placeholder="请选择人员姓名" @change="handlePersonChange">
<el-option v-for="person in personList" :key="person.id" :label="person.name" :value="person.id" />
</el-select>
</el-form-item>
<el-form-item label="健康档案" prop="recordId">
<el-select v-model="queryParams.recordId" placeholder="请选择健康档案" @change="handleRecordChange" clearable>
<el-option v-for="health in healthRecordList" :key="health.id" :label="health.name" :value="health.id" />
</el-select>
</el-form-item>
<el-form-item label="用药日期" prop="time" v-if="queryParams.type === 1">
<el-date-picker
v-model="queryParams.time"
type="daterange"
range-separator="~"
start-placeholder="开始时间"
end-placeholder="结束时间"
format="YYYY-MM-DD"
@calendar-change="calendarChange"
/>
</el-form-item>
<el-form-item label="" prop="time" v-if="queryParams.type === 2">
<el-date-picker
v-model="queryParams.time"
type="monthrange"
range-separator="~"
format="YYYY-MM"
start-placeholder="开始时间"
end-placeholder="结束时间"
:disabled-date="disabledDateFun"
@calendar-change="calendarChange"
/>
</el-form-item>
<el-form-item label="" prop="time" v-if="queryParams.type === 3">
<yearPicker
v-model="queryParams.time"
ref="statisticPicker"
labelText="选择年份"
:initYear="dateValue"
:showYear="showYearValue"
:maxLength="5"
sp="~"
@updateTimeRange="updateStatisticYear"
/>
</el-form-item>
</el-form>
<div class="search-btn-con">
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button type="info" icon="Refresh" @click="resetQuery">重置</el-button>
</div>
</div>
<div class="main-con" style="height: calc(100% - 1.45rem)">
<div class="summary-con" style="height: 115px">
<div class="right-con">
<div class="img">
<img src="@/assets/images/average.png" alt="" />
</div>
<div class="item-wrap">
<div class="title">用药天数</div>
<div>
<span class="num">{{ mar.marDays }}</span
><span class="unit"></span>
</div>
</div>
</div>
<div class="right-con">
<div class="img">
<img src="@/assets/images/average.png" alt="" />
</div>
<div class="item-wrap">
<div class="title">用药种类</div>
<div>
<span class="num">{{ mar.marCategoryCount }}</span
><span class="unit"></span>
</div>
</div>
</div>
<div class="right-con">
<div class="img">
<img src="@/assets/images/average.png" alt="" />
</div>
<div class="item-wrap">
<div class="title">用药次数</div>
<div>
<span class="num">{{ mar.marCount }}</span
><span class="unit"> </span>
</div>
</div>
</div>
<div class="right-con" v-show="mar.top1 > 0">
<div class="img">
<img src="@/assets/images/average.png" alt="" />
</div>
<div class="item-wrap">
<div class="title">{{ mar.top1Name }}</div>
<div>
<span class="num">{{ mar.top1 }}</span
><span class="unit"></span>
</div>
</div>
</div>
<div class="right-con" v-show="mar.top2 > 0">
<div class="img">
<img src="@/assets/images/average.png" alt="" />
</div>
<div class="item-wrap">
<div class="title">{{ mar.top2Name }}</div>
<div>
<span class="num">{{ mar.top2 }}</span
><span class="unit"></span>
</div>
</div>
</div>
<div class="right-con" v-show="mar.top3 > 0">
<div class="img">
<img src="@/assets/images/average.png" alt="" />
</div>
<div class="item-wrap">
<div class="title">{{ mar.top3Name }}</div>
<div>
<span class="num">{{ mar.top3 }}</span> <span class="unit"></span>
</div>
</div>
</div>
</div>
<div class="summary-con" v-show="mar.top4 > 0 || mar.top5 > 0 || mar.top6 > 0 || mar.top7 > 0 || mar.top8 > 0 || mar.top9 > 0" style="height: 115px">
<div class="right-con" v-show="mar.top4 > 0">
<div class="img">
<img src="@/assets/images/average.png" alt="" />
</div>
<div class="item-wrap">
<div class="title">{{ mar.top4Name }}</div>
<div>
<span class="num">{{ mar.top4 }}</span
><span class="unit"></span>
</div>
</div>
</div>
<div class="right-con" v-show="mar.top5 > 0">
<div class="img">
<img src="@/assets/images/average.png" alt="" />
</div>
<div class="item-wrap">
<div class="title">{{ mar.top5Name }}</div>
<div>
<span class="num">{{ mar.top5 }}</span> <span class="unit"></span>
</div>
</div>
</div>
<div class="right-con" v-show="mar.top6 > 0">
<div class="img">
<img src="@/assets/images/average.png" alt="" />
</div>
<div class="item-wrap">
<div class="title">{{ mar.top6Name }}</div>
<div>
<span class="num">{{ mar.top6 }}</span
><span class="unit"></span>
</div>
</div>
</div>
<div class="right-con" v-show="mar.top7 > 0">
<div class="img">
<img src="@/assets/images/average.png" alt="" />
</div>
<div class="item-wrap">
<div class="title">{{ mar.top7Name }}</div>
<div>
<span class="num">{{ mar.top7 }}</span
><span class="unit"></span>
</div>
</div>
</div>
<div class="right-con" v-show="mar.top8 > 0">
<div class="img">
<img src="@/assets/images/average.png" alt="" />
</div>
<div class="item-wrap">
<div class="title">{{ mar.top8Name }}</div>
<div>
<span class="num">{{ mar.top8 }}</span> <span class="unit"></span>
</div>
</div>
</div>
<div class="right-con" v-show="mar.top9 > 0">
<div class="img">
<img src="@/assets/images/average.png" alt="" />
</div>
<div class="item-wrap">
<div class="title">{{ mar.top9Name }}</div>
<div>
<span class="num">{{ mar.top9 }}</span> <span class="unit"></span>
</div>
</div>
</div>
<!-- <div class="right-con" v-show="mar.mianyili > 0">
<div class="img">
<img src="@/assets/images/average.png" alt="" />
</div>
<div class="item-wrap">
<div class="title">免疫力</div>
<div>
<span class="num">{{ mar.mianyili }}</span> <span class="unit"></span>
</div>
</div>
</div> -->
</div>
<div class="title-con" style="margin-top: 18px">
<div class="title">用药统计</div>
<div class="operate-btn-con">
<el-radio-group v-model="radioVal" @change="handleRadioChange">
<el-radio-button label="用药明细" />
<!-- <el-radio-button label="按天用药明细" /> -->
<el-radio-button label="用药次数柱状图" />
<el-radio-button label="用药次数折线图" />
</el-radio-group>
</div>
</div>
<div class="content-con">
<div v-show="radioVal === '用药次数柱状图'" class="chart" id="chartBar" style="height: calc(100% - 225px); margin-top: -10px"></div>
<div v-show="radioVal === '用药次数折线图'" class="chart" id="chartLine" style="height: calc(100% - 225px); margin-top: -10px"></div>
<!-- <el-table v-show="radioVal === '按天用药明细'" v-loading="loading" :data="mar.tableMarList" height="calc(100% - 245px)">
<el-table-column label="序号" width="50" type="index" align="center">
<template #default="scope">
<span>{{ scope.$index + 1 }}</span>
</template>
</el-table-column>
<el-table-column label="用药日期" align="center" prop="time" />
<el-table-column prop="detail" label="用药明细" v-if="queryParams.type === 1">
<template #default="scope">
<span v-html="formatMultiLineData(scope.row.detail)"></span>
</template>
</el-table-column>
</el-table> -->
<el-table v-show="radioVal === '用药明细'" v-loading="loading" :data="mar.marMapList" height="calc(100% - 245px)">
<el-table-column label="序号" width="50" type="index" align="center">
<template #default="scope">
<span>{{ scope.$index + 1 }}</span>
</template>
</el-table-column>
<el-table-column label="药品名称" align="center" prop="medicalName" />
<el-table-column label="用药天数" align="center" prop="useDays" />
<el-table-column label="用药次数" align="center" prop="count" />
<el-table-column label="用药总量" align="center" prop="dosage" />
<el-table-column label="单位" align="center" prop="unit" />
</el-table>
</div>
</div>
</div>
</template>
<script setup name="CreditAnalysis">
import dayjs from 'dayjs'
import * as echarts from 'echarts'
import { ElMessage } from 'element-plus'
import yearPicker from '@/components/YearPicker/index.vue'
import { getMarAnalysis } from '@/api/health/statisticAnalysis'
import { listPerson, getPerson } from '@/api/health/person'
import { listHealthRecord } from '@/api/health/healthRecord'
const { proxy } = getCurrentInstance()
const { deal_type, account_type, deal_category } = proxy.useDict('deal_type', 'account_type', 'deal_category')
const personList = ref([])
const healthRecordList = ref([])
const dateValue = ref({ startYear: 2000, endYear: new Date().getFullYear() })
const showYearValue = ref({ startShowYear: '', endShowYear: '' })
const updateStatisticYear = (startYear, endYear) => {
queryParams.value.time = [new Date(startYear, 0, 1), new Date(endYear, 0, 1)]
if (endYear - startYear > 5) {
ElMessage.warning('时间跨度不能大于5年默认选择开始日期的5年')
queryParams.value.time = [new Date(startYear, 0, 1), new Date(startYear + 5, 0, 1)]
}
}
const dates = [{ value: 1, label: '日' }]
const accountsList = ref([])
const loading = ref(true)
const total = ref(0)
const radioVal = ref('用药明细')
const dateValidate = (rules, value, callback) => {
const dateType = rules.dateType || 'days'
const num = rules.num || 31
const dateString = rules.dateString || '天'
const message = rules.message || `时间跨度不能超过${num}${dateString}`
if (value && value.length === 2) {
const start = value[0]
const end = value[1]
if (dayjs(end).diff(dayjs(start), dateType) > num) {
queryParams.value.time = [start, dayjs(start).add(23, 'months')]
ElMessage.warning(message)
}
}
}
const data = reactive({
queryParams: {
type: 1,
time: null,
id: null,
dataType: '1',
dealType: null,
dealCategory: null
},
queryPersonParams: {
pageNum: 1,
pageSize: 1000
},
queryHealthRecordParams: {
pageNum: 1,
personId: null,
state: '1',
pageSize: 1000
},
rules: {
time: [{ validator: dateValidate, dateType: 'months', num: 23, dateRange: '月', message: '时间跨度不能大于24个月默认选择开始日期的24个月' }]
}
})
const { queryParams, rules, queryPersonParams, queryHealthRecordParams } = toRefs(data)
const handleRecordChange = (recordId) => {
queryParams.value.recordId = recordId
getList()
}
const handlePersonChange = (personId) => {
queryHealthRecordParams.personId = personId
listHealthRecord(queryHealthRecordParams).then((response) => {
healthRecordList.value = response.rows
if (response.rows.length > 0) {
queryParams.value.recordId = response.rows[0].id
getList()
}
})
}
/** 查询成员管理列表 */
function getPersonList() {
listPerson(queryPersonParams.value).then((response) => {
personList.value = response.rows
if (response.rows.length > 0) {
queryParams.value.id = response.rows[0].id
queryHealthRecordParams.personId = response.rows[0].id
listHealthRecord(queryHealthRecordParams).then((res) => {
healthRecordList.value = res.rows
if (res.rows.length > 0) {
queryParams.value.recordId = res.rows[0].id
getList()
}
})
}
})
}
// const today = new Date()
// const end = today.getFullYear() + '-' + ('0' + (today.getMonth() + 1)).slice(-2) + '-' + ('0' + today.getDate()).slice(-2)
// const start = dayjs(end).add(-60, 'day')
// queryParams.value.time = [start, end]
const handleTimeChange = (type) => {
queryParams.value.time = null
if (type === 1) {
const today = new Date()
const end = today.getFullYear() + '-' + ('0' + (today.getMonth() + 1)).slice(-2) + '-' + ('0' + today.getDate()).slice(-2)
const start = dayjs(end).add(-60, 'day')
queryParams.value.time = [start, end]
} else if (type === 2) {
const today = new Date()
const end = today.getFullYear() + '-' + ('0' + (today.getMonth() + 1)).slice(-2)
const start = dayjs(end).add(-11, 'months')
queryParams.value.time = [start, end]
} else if (type === 3) {
const today = new Date()
const endYear = today.getFullYear()
queryParams.value.time = [new Date(endYear - 2, 0, 1), new Date(endYear, 0, 1)]
showYearValue.value = { startShowYear: endYear - 2, endShowYear: endYear }
}
getList()
}
function formatMultiLineData(data) {
if (data != null) {
return data.replace(/<br\/>/g, '<br/>')
}
}
const disabledDateFun = (time) => {
const arr = [0, 30, 365, 365 * 5]
const days = arr[queryParams.value.type]
if (firstChooseDate.value) {
const one = days * 24 * 3600 * 1000
const minTime = firstChooseDate.value - one
const maxTime = firstChooseDate.value + one
const startTime = minTime
const endTime = maxTime > Date.now() - 8.64e7 ? Date.now() - 8.64e7 : maxTime
return time.getTime() > endTime || time.getTime() < startTime
} else {
return time.getTime() > Date.now() - 8.64e7
}
}
const firstChooseDate = ref('')
const calendarChange = (val) => {
firstChooseDate.value = val[0].getTime()
if (val[1]) firstChooseDate.value = ''
}
const mar = ref({})
const chartData = ref({
name: [],
value1: []
})
function getList() {
loading.value = true
chartData.value = { name: [], value1: [] }
const { type, time, id, recordId } = queryParams.value
let formatValue = 'YYYY-MM-DD'
if (type === 1) {
formatValue = 'YYYY-MM-DD'
} else if (type === 2) {
formatValue = 'YYYY-MM'
} else {
formatValue = 'YYYY'
}
const params = {
type,
startTime: time && time.length > 0 ? dayjs(time[0]).format(formatValue) : '',
endTime: time && time.length > 0 ? dayjs(time[1]).format(formatValue) : '',
id,
recordId
}
getMarAnalysis(params).then((response) => {
loading.value = false
mar.value = { ...response.data }
mar.value.marList.map((item) => {
return {
name: item.time,
value: item.value
}
})
response.data.marList.map((item) => {
chartData.value.name.push(item.time)
chartData.value.value1.push(item.value)
})
handleRadioChange(currentType.value)
})
}
function handleQuery() {
getList()
}
function resetQuery() {
proxy.resetForm('queryRef')
queryParams.value.id = null
const today = new Date()
const end = today.getFullYear() + '-' + ('0' + (today.getMonth() + 1)).slice(-2) + '-' + ('0' + today.getDate()).slice(-2)
const start = dayjs(end).add(-60, 'day')
queryParams.value.time = [start, end]
total.value = 0
getPersonList()
}
const drawBar = (data) => {
if (document.getElementById('chartBar') === null) {
return
}
echarts.dispose(document.getElementById('chartBar'))
const myChart = echarts.init(document.getElementById('chartBar'))
const option = {
legend: {
// 图示例样式
show: true,
top: 50,
right: 50,
itemGap: 20
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
},
formatter: function (params) {
return params[0].name + '<br>' + '用药:' + params[0].value + '次'
}
},
grid: {
left: '5%',
right: '5%',
bottom: '5%',
containLabel: true
},
xAxis: [
{
type: 'category',
data: data.name,
axisTick: {
alignWithLabel: true // 刻度线是否与标签对齐默认false
},
// 设置 X 轴线条粗细
axisLine: {
lineStyle: {
width: 1, // 根据需求调整数值大小,单位是像素
color: '#999'
}
}
}
],
yAxis: [
{
type: 'value',
// min: 1, // 设置 y 轴的最小值为 0
// max: 16, // 设置 y 轴的最大值为 100
interval: 1, //设置y轴刻度间隔
axisTick: {
show: true // 默认为true如果要隐藏则改为 false
},
axisLine: {
show: true,
lineStyle: {
width: 1,
color: '#999'
}
}
}
],
series: [
{
data: data.value1,
type: 'bar',
barWidth: 10, // 根据需求调整数值大小,单位是像素
itemStyle: {
// 此处可以是一个固定颜色值,也可以是一个回调函数根据数据动态计算颜色
color: function (params) {
// 这里可以根据需要设置不同的颜色,比如根据数据值
if (params.data < 4) {
return '#37b328'
} else if (params.data >= 4 && params.data < 8) {
return '#ff00ff'
} else if (params.data >= 8 && params.data < 12) {
return '#ff0066'
} else if (params.data >= 12 && params.data < 15) {
return '#ff0000'
} else if (params.data >= 15) {
return '#990000' // 数据在50到99之间为蓝色
}
}
}
}
],
// 添加点击事件的处理函数
emphasis: {
// itemStyle: {
// color: '#2283cf',
// barWidth: 20 // 根据需求调整数值大小,单位是像素
// },
barWidth: 24 // 根据需求调整数值大小,单位是像素
}
}
myChart.setOption(option)
}
const drawLine = (data) => {
if (document.getElementById('chartLine') === null) {
return
}
echarts.dispose(document.getElementById('chartLine'))
const myChart = echarts.init(document.getElementById('chartLine'))
const option = {
grid: {
left: '5%',
right: '5%',
bottom: '5%',
containLabel: true
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
},
formatter: function (params) {
return params[0].name + '<br>' + '用药:' + params[0].value + '次'
}
},
xAxis: {
type: 'category',
data: data.name,
axisTick: {
alignWithLabel: true
},
axisLine: {
lineStyle: {
width: 1,
color: '#999'
}
}
},
yAxis: {
type: 'value',
// min: 1, // 设置 y 轴的最小值为 0
// max: 16, // 设置 y 轴的最大值为 100
interval: 1, //设置y轴刻度间隔
axisTick: {
show: true
},
axisLine: {
show: true,
lineStyle: {
width: 1,
color: '#999'
}
}
},
series: [
{
data: data.value1,
type: 'line',
lineStyle: {
color: '#4181c9'
},
itemStyle: {
// 此处可以是一个固定颜色值,也可以是一个回调函数根据数据动态计算颜色
color: function (params) {
// 这里可以根据需要设置不同的颜色,比如根据数据值
if (params.data < 4) {
return '#37b328'
} else if (params.data >= 4 && params.data < 8) {
return '#ff00ff'
} else if (params.data >= 8 && params.data < 12) {
return '#ff0066'
} else if (params.data >= 12 && params.data < 15) {
return '#ff0000'
} else if (params.data >= 15) {
return '#990000' // 数据在50到99之间为蓝色
}
}
},
smooth: true,
symbol: 'emptyCircle',
areaStyle: {
color: new echarts.graphic.LinearGradient(
0,
0,
0,
1,
[
{
offset: 0,
color: 'rgba(65,129,201, 0.70)'
},
{
offset: 1,
color: 'rgba(65,129,201, 0.10)'
}
],
false
),
shadowColor: 'rgba(65,129,201, 0.10)',
shadowBlur: 10
}
}
]
}
myChart.setOption(option)
}
const currentType = ref('用药次数柱状图')
const handleRadioChange = (type) => {
currentType.value = type
switch (type) {
case '用药次数柱状图':
drawBar(chartData.value)
break
case '用药次数折线图':
drawLine(chartData.value)
break
default:
break
}
}
getPersonList()
</script>