477 lines
12 KiB
Vue
477 lines
12 KiB
Vue
|
<template>
|
|||
|
<div class="container">
|
|||
|
<div class="filter-section" style="margin:0 0 20px 0">
|
|||
|
<el-date-picker v-model="dateRange" value-format="YYYY-MM-DD" type="daterange" range-separator="-"
|
|||
|
start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
|
|||
|
<el-button type="primary" @click="handleSearch" style="margin:0 0 0 10px">搜索</el-button>
|
|||
|
<el-button @click="handleReset">重置</el-button>
|
|||
|
</div>
|
|||
|
<div class="top">
|
|||
|
<div class="top-box box1" @click="handlecountMedicine">
|
|||
|
<div class="icon icon1"><img src="../../../../assets/icons/svg/storeroom.png"></div>
|
|||
|
<span class="top-box-count"> {{ countMedicines }} </span>
|
|||
|
<span class="top-box-text"> 库房药品统计</span>
|
|||
|
</div>
|
|||
|
<div class="top-box box2" @click="countAmount">
|
|||
|
<div class="icon icon2"><img src="../../../../assets/icons/svg/drug.png"></div>
|
|||
|
<span class="top-box-count"> {{ countAmounts }} </span>
|
|||
|
<span class="top-box-text"> 药品金额统计</span>
|
|||
|
</div>
|
|||
|
<div class="top-box box3" @click="navigateToDrugFiling('adevnt')">
|
|||
|
<div class="icon icon3"><img src="../../../../assets/icons/svg/advent.png"></div>
|
|||
|
<span class="top-box-count"> {{ countAdvents }} </span>
|
|||
|
<span class="top-box-text"> 临期药品统计 </span>
|
|||
|
</div>
|
|||
|
<div class="top-box box4" @click="navigateToDrugFiling('alerts')">
|
|||
|
<div class="icon icon4"><img src="../../../../assets/icons/svg/warning.png"></div>
|
|||
|
<span class="top-box-count"> {{ countAlertss }} </span>
|
|||
|
<span class="top-box-text"> 库存预警统计 </span>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div class="bottom">
|
|||
|
<!-- 接诊统计 Reception statistics -->
|
|||
|
<div class="bottom-left reception_div"></div>
|
|||
|
<!-- 接诊统计 Reception Rotundity -->
|
|||
|
<div class="bottom-right reception_rotundity"></div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</template>
|
|||
|
|
|||
|
<script setup name="medicalChar">
|
|||
|
import { ref, reactive, toRefs, onMounted, onBeforeMount } from "vue";
|
|||
|
import { getCountMedicine } from "@/api/healthcare/charMedicine/charMedicine.js";
|
|||
|
import route from "@/router";
|
|||
|
|
|||
|
const data = reactive({
|
|||
|
queryParams: {},
|
|||
|
});
|
|||
|
|
|||
|
const { queryParams } = toRefs(data);
|
|||
|
const dateRange = ref([]);
|
|||
|
|
|||
|
onMounted(() => {
|
|||
|
countMedicine();
|
|||
|
});
|
|||
|
|
|||
|
function handleSearch() {
|
|||
|
countMedicine();
|
|||
|
}
|
|||
|
|
|||
|
// 重置 方法
|
|||
|
function handleReset() {
|
|||
|
dateRange.value = [];
|
|||
|
queryParams.value.startDate = null;
|
|||
|
queryParams.value.endDate = null;
|
|||
|
countMedicine();
|
|||
|
}
|
|||
|
|
|||
|
const countMedicines = ref(0); // 库房药品统计
|
|||
|
const countAmounts = ref(0); // 药品金额统计
|
|||
|
const countAdvents = ref(0); // 临期药品统计
|
|||
|
const countAlertss = ref(0); // 库存预警统计
|
|||
|
|
|||
|
function countMedicine() {
|
|||
|
if (dateRange.value && dateRange.value.length === 2) {
|
|||
|
queryParams.value.startDate = dateRange.value[0];
|
|||
|
queryParams.value.endDate = dateRange.value[1];
|
|||
|
//
|
|||
|
const paramsTime = {};
|
|||
|
paramsTime.params = {};
|
|||
|
// 赋值 startTime 和 endTime 为 Date 对象
|
|||
|
paramsTime.params["startTime"] = dateRange.value[0];
|
|||
|
paramsTime.params["endTime"] = dateRange.value[1];
|
|||
|
// 使用
|
|||
|
tackleData(paramsTime);
|
|||
|
}
|
|||
|
|
|||
|
getCountMedicine(queryParams.value)
|
|||
|
.then((response) => {
|
|||
|
countMedicines.value = response.data.countMedicine; // 库房药品统计
|
|||
|
countAmounts.value = response.data.countAmount; // 药品金额统计
|
|||
|
countAdvents.value = response.data.countAdvent; // 临期药品统计
|
|||
|
countAlertss.value = response.data.countAlerts; // 库存预警统计
|
|||
|
})
|
|||
|
.catch((error) => {
|
|||
|
console.error("获取药品数量统计失败", error);
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
function handlecountMedicine() {
|
|||
|
console.log("库房药品统计总和");
|
|||
|
route.push({ name: "DrugFiling" });
|
|||
|
}
|
|||
|
|
|||
|
const params = ref({});
|
|||
|
import { useRouter } from "vue-router";
|
|||
|
const router = useRouter();
|
|||
|
function navigateToDrugFiling(type) {
|
|||
|
router.push(`inventory/DrugFiling?type=${type}`);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
import * as echarts from "echarts/core";
|
|||
|
import {
|
|||
|
DatasetComponent,
|
|||
|
TitleComponent,
|
|||
|
TooltipComponent,
|
|||
|
GridComponent,
|
|||
|
LegendComponent,
|
|||
|
} from "echarts/components";
|
|||
|
import { BarChart } from "echarts/charts";
|
|||
|
import { CanvasRenderer } from "echarts/renderers";
|
|||
|
import { PieChart } from "echarts/charts";
|
|||
|
import { LabelLayout } from "echarts/features";
|
|||
|
|
|||
|
echarts.use([
|
|||
|
DatasetComponent,
|
|||
|
TitleComponent,
|
|||
|
TooltipComponent,
|
|||
|
GridComponent,
|
|||
|
LegendComponent,
|
|||
|
BarChart,
|
|||
|
CanvasRenderer,
|
|||
|
PieChart,
|
|||
|
LabelLayout,
|
|||
|
]);
|
|||
|
|
|||
|
const receptionRef = ref(null);
|
|||
|
|
|||
|
//
|
|||
|
import {
|
|||
|
gainPatientDiagnosisListXml,
|
|||
|
obtainSymptomStatisticsNumber,
|
|||
|
obtainSymptomStatisticsNumberMonth,
|
|||
|
} from "@/api/healthcare/outpatientService/patientDiagnosis";
|
|||
|
|
|||
|
// 钩子
|
|||
|
onBeforeMount(() => {
|
|||
|
//
|
|||
|
console.log("组件即将挂载到 DOM");
|
|||
|
//
|
|||
|
// 获取当前时间
|
|||
|
let currentDate = new Date();
|
|||
|
|
|||
|
// 格式化当前日期
|
|||
|
const year = currentDate.getFullYear();
|
|||
|
const month = `0${currentDate.getMonth() + 1}`.slice(-2); // 月份从0开始,需要加1
|
|||
|
const day = `0${currentDate.getDate()}`.slice(-2);
|
|||
|
|
|||
|
// 创建一年前的日期
|
|||
|
let oneYearAgo = new Date(currentDate);
|
|||
|
oneYearAgo.setFullYear(currentDate.getFullYear() - 1);
|
|||
|
|
|||
|
// 打印一年前的日期(ISO 格式)
|
|||
|
console.log("一年前的日期:", oneYearAgo.toISOString());
|
|||
|
|
|||
|
// 打印当前日期和格式化后的日期
|
|||
|
console.log("时间:", currentDate, `${year}-${month}-${day}`);
|
|||
|
console.log("一年前的日期", oneYearAgo, "现在", currentDate);
|
|||
|
|
|||
|
// 格式化一年前的日期
|
|||
|
const formattedOneYearAgo = `${oneYearAgo.getFullYear()}-${`0${oneYearAgo.getMonth() + 1
|
|||
|
}`.slice(-2)}-${`0${oneYearAgo.getDate()}`.slice(-2)}`;
|
|||
|
|
|||
|
// 格式化当前日期
|
|||
|
const formattedCurrentDate = `${year}-${month}-${day}`;
|
|||
|
|
|||
|
// 初始化查询参数对象
|
|||
|
const paramsTime = {};
|
|||
|
paramsTime.params = {};
|
|||
|
|
|||
|
// 赋值 startTime 和 endTime 为 Date 对象
|
|||
|
paramsTime.params["startTime"] = formattedOneYearAgo;
|
|||
|
paramsTime.params["endTime"] = formattedCurrentDate;
|
|||
|
// 使用
|
|||
|
tackleData(paramsTime);
|
|||
|
});
|
|||
|
|
|||
|
// 数据更新后
|
|||
|
onUpdated(() => {
|
|||
|
console.log("数据已更新");
|
|||
|
//
|
|||
|
});
|
|||
|
|
|||
|
// 进行 数据 处理 tackle
|
|||
|
function tackleData(queryParamsData) {
|
|||
|
//
|
|||
|
// 获取 对象 类型
|
|||
|
obtainSymptomStatisticsNumber(queryParamsData).then((response) => {
|
|||
|
console.log("获取 患者 诊断 列表", response);
|
|||
|
// 处理数据
|
|||
|
const symptomNameList = ref([]);
|
|||
|
for (let i = 0; i < response.rows.length; i++) {
|
|||
|
symptomNameList.value.push({
|
|||
|
//
|
|||
|
name: response.rows[i].symptomName,
|
|||
|
//
|
|||
|
value: response.rows[i].number,
|
|||
|
});
|
|||
|
//
|
|||
|
}
|
|||
|
//
|
|||
|
myChart_div_rotundity.value.setOption({
|
|||
|
legend: {
|
|||
|
data: symptomNameList.value,
|
|||
|
},
|
|||
|
series: [
|
|||
|
{
|
|||
|
data: symptomNameList.value,
|
|||
|
},
|
|||
|
],
|
|||
|
});
|
|||
|
});
|
|||
|
// let symptomList = ref([]);
|
|||
|
obtainSymptomStatisticsNumberMonth(queryParamsData).then((response) => {
|
|||
|
console.log("获取 患者 诊断 列表", response);
|
|||
|
let symptomList = ref([]);
|
|||
|
let seriesList = ref([]);
|
|||
|
symptomList.value.push(["类型"]);
|
|||
|
//
|
|||
|
for (let h = 0; h < response.rows[0].length; h++) {
|
|||
|
symptomList.value[0].push(response.rows[0][h].symptomName);
|
|||
|
seriesList.value.push({ type: "bar" });
|
|||
|
}
|
|||
|
for (let i = 0; i < response.rows.length; i++) {
|
|||
|
//
|
|||
|
symptomList.value.push([`${response.rows[i][0].month}月`]);
|
|||
|
// 添加 统计 的 名字
|
|||
|
for (let j = 0; j < response.rows[i].length; j++) {
|
|||
|
symptomList.value[i + 1].push(response.rows[i][j].number);
|
|||
|
}
|
|||
|
}
|
|||
|
//
|
|||
|
console.log("统计 的 名字 数据:", symptomList.value, seriesList.value);
|
|||
|
//
|
|||
|
myChart_div.value.setOption({
|
|||
|
dataset: {
|
|||
|
source: symptomList.value,
|
|||
|
},
|
|||
|
series: seriesList.value,
|
|||
|
});
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
let myChart_div_rotundity = ref(null);
|
|||
|
//
|
|||
|
let myChart_div = ref(null);
|
|||
|
|
|||
|
// 组件挂载
|
|||
|
onMounted(() => {
|
|||
|
//
|
|||
|
// 此时 DOM 元素已渲染,可以安全地访问 myDiv.value
|
|||
|
console.log("组件已挂载,DOM 元素已渲染", receptionRef.value);
|
|||
|
var div_01 = document.getElementsByClassName("reception_div");
|
|||
|
let myChart01 = document.querySelector(".reception_div");
|
|||
|
myChart_div.value = echarts.init(document.querySelector(".reception_div"));
|
|||
|
console.log("ECharts入门示例:", div_01, receptionRef.value, myChart01, myChart_div);
|
|||
|
// var myChart = echarts.init(receptionRef.value);
|
|||
|
// 指定图表的配置项和数据
|
|||
|
let option = {
|
|||
|
legend: {},
|
|||
|
tooltip: {},
|
|||
|
dataset: {
|
|||
|
source: [],
|
|||
|
},
|
|||
|
xAxis: { type: "category" },
|
|||
|
yAxis: {},
|
|||
|
series: [],
|
|||
|
};
|
|||
|
//
|
|||
|
myChart_div.value.setOption(option);
|
|||
|
|
|||
|
// 接诊统计 圆形
|
|||
|
myChart_div_rotundity.value = echarts.init(
|
|||
|
document.querySelector(".reception_rotundity")
|
|||
|
);
|
|||
|
//
|
|||
|
let option_rotundity = {
|
|||
|
title: {
|
|||
|
text: "接诊统计",
|
|||
|
left: "center",
|
|||
|
},
|
|||
|
tooltip: {
|
|||
|
trigger: "item",
|
|||
|
formatter: "{a} <br/>{b} : {c} ({d}%)",
|
|||
|
},
|
|||
|
legend: {
|
|||
|
type: "scroll",
|
|||
|
orient: "vertical",
|
|||
|
right: 10,
|
|||
|
top: 20,
|
|||
|
bottom: 20,
|
|||
|
data: [],
|
|||
|
},
|
|||
|
series: [
|
|||
|
{
|
|||
|
name: "姓名",
|
|||
|
type: "pie",
|
|||
|
radius: "55%",
|
|||
|
center: ["40%", "50%"],
|
|||
|
data: [],
|
|||
|
emphasis: {
|
|||
|
itemStyle: {
|
|||
|
shadowBlur: 10,
|
|||
|
shadowOffsetX: 0,
|
|||
|
shadowColor: "rgba(0, 0, 0, 0.5)",
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
],
|
|||
|
};
|
|||
|
|
|||
|
//
|
|||
|
myChart_div_rotundity.value.setOption(option_rotundity);
|
|||
|
});
|
|||
|
</script>
|
|||
|
|
|||
|
<style scoped>
|
|||
|
.chart {
|
|||
|
width: 100%;
|
|||
|
height: 400px;
|
|||
|
}
|
|||
|
|
|||
|
.container {
|
|||
|
display: flex;
|
|||
|
flex-direction: column;
|
|||
|
height: 90vh;
|
|||
|
padding: 20px;
|
|||
|
/* 添加内边距以确保顶部和底部区域之间的间距 */
|
|||
|
background-color: #f5f5f5;
|
|||
|
}
|
|||
|
|
|||
|
.top {
|
|||
|
display: flex;
|
|||
|
flex-wrap: wrap;
|
|||
|
gap: 15px;
|
|||
|
/* 盒子之间的间距 */
|
|||
|
width: 100%;
|
|||
|
height: 150px;
|
|||
|
margin-bottom: 30px;
|
|||
|
/* 顶部和底部区域之间的间距 */
|
|||
|
|
|||
|
.top-box {
|
|||
|
width: calc(25% - 11.25px);
|
|||
|
/* 25% - (3 * 15px / 4) */
|
|||
|
height: 100%;
|
|||
|
box-shadow: 0 4px 8px rgba(0.3, 0.3, 0.3, 0.3);
|
|||
|
/* 添加阴影 */
|
|||
|
border-radius: 10px;
|
|||
|
/* 圆角 5px */
|
|||
|
display: flex;
|
|||
|
color: rgb(255, 255, 255);
|
|||
|
/* 文字颜色 */
|
|||
|
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
|||
|
/* 平滑过渡效果 */
|
|||
|
cursor: pointer;
|
|||
|
/* 鼠标指针变为手指形状 */
|
|||
|
background-color: white;
|
|||
|
position: relative;
|
|||
|
}
|
|||
|
|
|||
|
.top-box:hover {
|
|||
|
transform: scale(1.01);
|
|||
|
/* 鼠标悬停时向外突出 5% */
|
|||
|
box-shadow: 0 6px 12px rgba(0.3, 0.3, 0.3, 0.5);
|
|||
|
/* 加强阴影效果 */
|
|||
|
}
|
|||
|
|
|||
|
/* 4小个盒子 */
|
|||
|
.box1 {
|
|||
|
background-color: #FF9A00;
|
|||
|
}
|
|||
|
|
|||
|
.box2 {
|
|||
|
background-color: #4DB4FF;
|
|||
|
}
|
|||
|
|
|||
|
.box3 {
|
|||
|
background-color: #F96464;
|
|||
|
}
|
|||
|
|
|||
|
.box4 {
|
|||
|
background-color: #965AFF;
|
|||
|
}
|
|||
|
|
|||
|
/* 图标 */
|
|||
|
.icon {
|
|||
|
width: 170px;
|
|||
|
height: 150px;
|
|||
|
border-radius: 10px;
|
|||
|
display: flex;
|
|||
|
align-items: center;
|
|||
|
justify-content: center;
|
|||
|
box-shadow: 0 6px 12px rgba(0.1, 0.1, 0.1, 0.1);
|
|||
|
}
|
|||
|
|
|||
|
.icon1 {
|
|||
|
background: linear-gradient(90deg, #FF9900, #FFAE00);
|
|||
|
}
|
|||
|
|
|||
|
.icon2 {
|
|||
|
background: linear-gradient(90deg, #0195FF, #53BFFD);
|
|||
|
}
|
|||
|
|
|||
|
.icon3 {
|
|||
|
background: linear-gradient(90deg, #F66B6D, #F68080);
|
|||
|
}
|
|||
|
|
|||
|
.icon4 {
|
|||
|
background: linear-gradient(90deg, #673FFF, #A25DFF);
|
|||
|
}
|
|||
|
|
|||
|
.top-box-text {
|
|||
|
position: absolute;
|
|||
|
height: 70px;
|
|||
|
bottom: 0;
|
|||
|
left: 180px;
|
|||
|
font-size: 30px;
|
|||
|
font-weight: 700;
|
|||
|
}
|
|||
|
|
|||
|
.top-box-count {
|
|||
|
position: absolute;
|
|||
|
height: 130px;
|
|||
|
bottom: 0;
|
|||
|
left: 180px;
|
|||
|
font-size: 50px;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
.bottom {
|
|||
|
display: flex;
|
|||
|
flex: 1;
|
|||
|
gap: 30px;
|
|||
|
/* 两个底部区域之间的间距 */
|
|||
|
}
|
|||
|
|
|||
|
.bottom-left {
|
|||
|
width: 65%;
|
|||
|
height: 100%;
|
|||
|
background-color: white;
|
|||
|
box-shadow: 0 4px 8px rgba(0.3, 0.3, 0.3, 0.3);
|
|||
|
/* 添加阴影 */
|
|||
|
display: flex;
|
|||
|
justify-content: center;
|
|||
|
align-items: center;
|
|||
|
color: black;
|
|||
|
font-size: 18px;
|
|||
|
font-weight: bold;
|
|||
|
}
|
|||
|
|
|||
|
.bottom-right {
|
|||
|
width: 35%;
|
|||
|
/* 调整为 35% 以确保总宽度为 100% */
|
|||
|
height: 100%;
|
|||
|
background-color: white;
|
|||
|
box-shadow: 0 4px 8px rgba(0.3, 0.3, 0.3, 0.3);
|
|||
|
/* 添加阴影 */
|
|||
|
display: flex;
|
|||
|
justify-content: center;
|
|||
|
align-items: center;
|
|||
|
color: black;
|
|||
|
font-size: 18px;
|
|||
|
font-weight: bold;
|
|||
|
}
|
|||
|
</style>
|