|
@@ -0,0 +1,429 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <div class="druglist">
|
|
|
|
|
+ <!-- 顶部筛选 -->
|
|
|
|
|
+ <div class="screening">
|
|
|
|
|
+ <div class="screening-title flex-vertical-center-l">
|
|
|
|
|
+ <img src="~@/assets/filters.png" alt/>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="screening-form flex-vertical-center-l flex-wrap">
|
|
|
|
|
+ <div class="screening-item flex-vertical-center-l">
|
|
|
|
|
+ <div class="input" style="display: flex;">
|
|
|
|
|
+ <el-date-picker size="mini" v-model="start" type="month" placeholder="起始年月"
|
|
|
|
|
+ :picker-options="startPickerOptions" format="yyyy-MM" :clearable="false"></el-date-picker>
|
|
|
|
|
+ <el-date-picker size="mini" v-model="end" type="month" placeholder="结束年月"
|
|
|
|
|
+ :picker-options="endPickerOptions" format="yyyy-MM"></el-date-picker>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="screening-item flex-vertical-center-l">
|
|
|
|
|
+ <span>医疗机构名称:</span>
|
|
|
|
|
+ <div class="input">
|
|
|
|
|
+ <el-select
|
|
|
|
|
+ size="mini"
|
|
|
|
|
+ v-model="cascader[1]"
|
|
|
|
|
+ placeholder="请选择"
|
|
|
|
|
+ @change="getCascaderC($event)"
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-option
|
|
|
|
|
+ :label="item.name"
|
|
|
|
|
+ :value="item.pid"
|
|
|
|
|
+ v-for="(item) in cascaderBOptions"
|
|
|
|
|
+ :key="item.pid"
|
|
|
|
|
+ ></el-option>
|
|
|
|
|
+ </el-select>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="screening-item flex-vertical-center-l">
|
|
|
|
|
+ <span>科室名称:</span>
|
|
|
|
|
+ <div class="input">
|
|
|
|
|
+ <el-select size="mini" v-model="cascader[2]" placeholder="请选择" multiple collapse-tags clearable
|
|
|
|
|
+ @change="getCascaderD('')">
|
|
|
|
|
+ <el-option
|
|
|
|
|
+ :label="item.name"
|
|
|
|
|
+ :value="item.pid"
|
|
|
|
|
+ v-for="(item) in cascaderCOptions"
|
|
|
|
|
+ :key="item.pid"
|
|
|
|
|
+ ></el-option>
|
|
|
|
|
+ </el-select>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="screening-item flex-vertical-center-l">
|
|
|
|
|
+ <div class="input flex-vertical-center-l">
|
|
|
|
|
+ <el-checkbox v-model="checked">是否包含下级</el-checkbox>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <el-button type="primary" size="mini" @click="search()">搜索</el-button>
|
|
|
|
|
+ <el-button type="warning" size="mini" @click="clearFilter()">清空</el-button>
|
|
|
|
|
+ <!--<el-button type="primary" size="mini" @click="exportDow()">导出</el-button>-->
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 展示数据层 -->
|
|
|
|
|
+ <div class="showData">
|
|
|
|
|
+ <!-- 展示两种数据 -->
|
|
|
|
|
+ <div class="showEcharts">
|
|
|
|
|
+ <div id="myChart" :style="{width: '100%'}" class="myCharts"></div>
|
|
|
|
|
+ <div class="e-format" style="margin-bottom:20px;">
|
|
|
|
|
+ 格式:量级维度-时间:数量
|
|
|
|
|
+ <span style="margin-left:30px;"></span> X轴:时间 Y轴:单位(次)
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="showEcharts">
|
|
|
|
|
+ <div style="font-size: 18px;font-weight: 700;text-align: center;">体质与精神状态分布图</div>
|
|
|
|
|
+ <div class="pie-wrapper">
|
|
|
|
|
+ <div class="pie-container" v-for="(pie) in pieSeries">
|
|
|
|
|
+ <div class="pie-chart" :data-name="pie.name"></div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+</template>
|
|
|
|
|
+<script>
|
|
|
|
|
+import {getDepartSelect, getDoctorSelect} from "@/api/system.js";
|
|
|
|
|
+import {medicalInstitution} from "@/api/city";
|
|
|
|
|
+import {getJSJK_BarChartData, getJSJK_PieChartData} from '@/api/dataAnalysis';
|
|
|
|
|
+import {formatMonth, subtractMonths} from "@/utils/format";
|
|
|
|
|
+import {mapGetters} from "vuex";
|
|
|
|
|
+import dayjs from 'dayjs';
|
|
|
|
|
+
|
|
|
|
|
+export default {
|
|
|
|
|
+ data() {
|
|
|
|
|
+ return {
|
|
|
|
|
+ loadDoctorSelect: false,
|
|
|
|
|
+ cascaderAOptions: [],
|
|
|
|
|
+ cascaderBOptions: [],
|
|
|
|
|
+ cascaderCOptions: [],
|
|
|
|
|
+ cascaderDOptions: [],
|
|
|
|
|
+ cascader: [],
|
|
|
|
|
+ checked: false,
|
|
|
|
|
+ start: subtractMonths(-12),
|
|
|
|
|
+ end: new Date(),
|
|
|
|
|
+
|
|
|
|
|
+ xAxisData: [],
|
|
|
|
|
+ series: [],
|
|
|
|
|
+ pieSeries: [],
|
|
|
|
|
+
|
|
|
|
|
+ page: 1,
|
|
|
|
|
+ limit: 10,
|
|
|
|
|
+ total: 0,
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ startPickerOptions: {
|
|
|
|
|
+ disabledDate: (date) => {
|
|
|
|
|
+ const value = date.getTime();
|
|
|
|
|
+ return this.end && value > this.end.getTime() || value > Date.now()
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ endPickerOptions: {
|
|
|
|
|
+ disabledDate: (date) => {
|
|
|
|
|
+ const value = date.getTime();
|
|
|
|
|
+ return this.start && value < this.start.getTime() || value > Date.now()
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+ },
|
|
|
|
|
+ created() {
|
|
|
|
|
+ this.getCascaderB(this.getuserinfo.organizationid);
|
|
|
|
|
+ },
|
|
|
|
|
+ mounted() {
|
|
|
|
|
+ this.load();
|
|
|
|
|
+ },
|
|
|
|
|
+ methods: {
|
|
|
|
|
+ search() {
|
|
|
|
|
+ this.load();
|
|
|
|
|
+ },
|
|
|
|
|
+ clearFilter() {
|
|
|
|
|
+ this.getCascaderB(this.getuserinfo.organizationid)
|
|
|
|
|
+ this.orderType = void 0;
|
|
|
|
|
+ this.start = subtractMonths(-12);
|
|
|
|
|
+ this.end = new Date();
|
|
|
|
|
+
|
|
|
|
|
+ this.search();
|
|
|
|
|
+ },
|
|
|
|
|
+ exportDow() {},
|
|
|
|
|
+ // 获取医疗机构选择器
|
|
|
|
|
+ async getCascaderB(id) {
|
|
|
|
|
+ this.cascader = [id, '', [], []];
|
|
|
|
|
+ this.cascaderBOptions = []
|
|
|
|
|
+ this.cascaderCOptions = []
|
|
|
|
|
+ this.cascaderDOptions = []
|
|
|
|
|
+ let res = await medicalInstitution({organizationId: id});
|
|
|
|
|
+ if (res.ResultCode == 0) { this.cascaderBOptions = res.Data; }
|
|
|
|
|
+ },
|
|
|
|
|
+ // 获取医疗机构下的科室
|
|
|
|
|
+ async getCascaderC(id) {
|
|
|
|
|
+ this.cascader = [this.cascader[0], id, [], []];
|
|
|
|
|
+ let res = await getDepartSelect({institutionId: id});
|
|
|
|
|
+ if (res.ResultCode == 0) { this.cascaderCOptions = res.Data; }
|
|
|
|
|
+
|
|
|
|
|
+ await this.getCascaderD().catch();
|
|
|
|
|
+ },
|
|
|
|
|
+ async getCascaderD(keyword) {
|
|
|
|
|
+ if (!this.cascader[1]) return;
|
|
|
|
|
+ this.loadDoctorSelect = true;
|
|
|
|
|
+ const res = await getDoctorSelect({
|
|
|
|
|
+ keyword,
|
|
|
|
|
+ organizationid: this.cascader[0] || '',
|
|
|
|
|
+ sititutionid: this.cascader[1] || '',
|
|
|
|
|
+ departmentsIds: this.cascader[2] || [],
|
|
|
|
|
+ })
|
|
|
|
|
+ if (res.ResultCode == 0) {
|
|
|
|
|
+ this.cascaderDOptions = res.Data.Items;
|
|
|
|
|
+ }
|
|
|
|
|
+ this.loadDoctorSelect = false;
|
|
|
|
|
+ },
|
|
|
|
|
+ // 获取列表
|
|
|
|
|
+ async load() {
|
|
|
|
|
+ let params = {
|
|
|
|
|
+ startMon: formatMonth(this.start),
|
|
|
|
|
+ endMon: formatMonth(this.end),
|
|
|
|
|
+ orgId: this.cascader[0] || '',
|
|
|
|
|
+ stiId: this.cascader[1] || '',
|
|
|
|
|
+ deptId: '',
|
|
|
|
|
+ deptIds: this.cascader[2] || [],
|
|
|
|
|
+ doctorIds: this.cascader[3] || [],
|
|
|
|
|
+ };
|
|
|
|
|
+ this.load2(params);
|
|
|
|
|
+
|
|
|
|
|
+ const length = dayjs(params.endMon).diff(params.startMon, 'month');
|
|
|
|
|
+ this.xAxisData = Array.from({length: length + 1}, (_, i) => dayjs(params.startMon).add(i, 'month').format('YYYY-MM'));
|
|
|
|
|
+ let data = await getJSJK_BarChartData(params);
|
|
|
|
|
+ const series = new Map();
|
|
|
|
|
+ this.xAxisData.forEach((key, index) => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ for (const [name, value] of Object.entries(data[key])) {
|
|
|
|
|
+ if (!series.has(name)) series.set(name, {name, type: 'bar', data: []});
|
|
|
|
|
+ series.get(name).data.push(value);
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (e) {}
|
|
|
|
|
+ });
|
|
|
|
|
+ this.series = [...series.values()];
|
|
|
|
|
+ this.list = data;
|
|
|
|
|
+
|
|
|
|
|
+ this.drawLine();
|
|
|
|
|
+ },
|
|
|
|
|
+ async load2(params) {
|
|
|
|
|
+ this.pieSeries = [];
|
|
|
|
|
+ const data = await getJSJK_PieChartData(params);
|
|
|
|
|
+ for (const [name, value] of Object.entries(data)) {
|
|
|
|
|
+ this.pieSeries.push({name: name, value: value});
|
|
|
|
|
+ this.$nextTick(() => {
|
|
|
|
|
+ const el = document.querySelector(`[data-name="${name}"].pie-chart`);
|
|
|
|
|
+ const chart = this.$echarts.init(el);
|
|
|
|
|
+ chart.setOption({
|
|
|
|
|
+ title: {text: name, bottom: '10%', left: 'center'},
|
|
|
|
|
+ tooltip: {trigger: 'item'},
|
|
|
|
|
+ series: [
|
|
|
|
|
+ {
|
|
|
|
|
+ name: name,
|
|
|
|
|
+ type: 'pie',
|
|
|
|
|
+ radius: '60%',
|
|
|
|
|
+ data: Object.entries(value).map(([name, value]) => ({name, value})),
|
|
|
|
|
+ emphasis: {
|
|
|
|
|
+ itemStyle: {
|
|
|
|
|
+ shadowBlur: 10,
|
|
|
|
|
+ shadowOffsetX: 0,
|
|
|
|
|
+ shadowColor: 'rgba(0, 0, 0, 0.5)',
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ ],
|
|
|
|
|
+ });
|
|
|
|
|
+ console.log(el);
|
|
|
|
|
+ });
|
|
|
|
|
+ // let chart = this.$echarts.init();
|
|
|
|
|
+ }
|
|
|
|
|
+ console.log(this.pieSeries);
|
|
|
|
|
+ },
|
|
|
|
|
+ drawLine() {
|
|
|
|
|
+ // 基于准备好的dom,初始化echarts实例
|
|
|
|
|
+ let myChart = this.$echarts.init(document.getElementById("myChart"));
|
|
|
|
|
+ // 绘制图表
|
|
|
|
|
+ myChart.setOption({
|
|
|
|
|
+ grid: {
|
|
|
|
|
+ left: "1%",
|
|
|
|
|
+ right: "1%",
|
|
|
|
|
+ bottom: "3%",
|
|
|
|
|
+ containLabel: true
|
|
|
|
|
+ },
|
|
|
|
|
+ title: {
|
|
|
|
|
+ text: `精神健康柱状图`,
|
|
|
|
|
+ left: 'center',
|
|
|
|
|
+ },
|
|
|
|
|
+ legend: {
|
|
|
|
|
+ top: '32px',
|
|
|
|
|
+ },
|
|
|
|
|
+ tooltip: {trigger: 'axis'},
|
|
|
|
|
+ xAxis: {type: "category", data: this.xAxisData},
|
|
|
|
|
+ yAxis: {type: "value"},
|
|
|
|
|
+ series: this.series,
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ computed: {
|
|
|
|
|
+ ...mapGetters(["getuserinfo"])
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+</script>
|
|
|
|
|
+<style lang="scss" scoped>
|
|
|
|
|
+.pie-wrapper {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-wrap: wrap;
|
|
|
|
|
+ justify-content: space-evenly;
|
|
|
|
|
+ .pie-container {
|
|
|
|
|
+ $size: 500px;
|
|
|
|
|
+ margin: 10px 0;
|
|
|
|
|
+ width: 30vw;
|
|
|
|
|
+ height: 30vw;
|
|
|
|
|
+ max-width: 500px;
|
|
|
|
|
+ max-height: 400px;
|
|
|
|
|
+ }
|
|
|
|
|
+ .pie-chart {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|
|
|
|
|
+<style lang="scss" scoped>
|
|
|
|
|
+@import "../../style/common.scss";
|
|
|
|
|
+@import "../../style/base.scss";
|
|
|
|
|
+
|
|
|
|
|
+.showData {
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ border-radius: 10px;
|
|
|
|
|
+ margin-top: 5px;
|
|
|
|
|
+ padding: 10px;
|
|
|
|
|
+ height: 71vh;
|
|
|
|
|
+ overflow: auto;
|
|
|
|
|
+
|
|
|
|
|
+ .top-change {
|
|
|
|
|
+ margin-bottom: 20px;
|
|
|
|
|
+ width: 100px;
|
|
|
|
|
+ height: 34px;
|
|
|
|
|
+ border-radius: 8px;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ border: 1px solid #dcdfe6;
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+
|
|
|
|
|
+ div:first-child {
|
|
|
|
|
+ border-radius: 8px 0 0 8px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ div:last-child {
|
|
|
|
|
+ border-radius: 0 8px 8px 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ div {
|
|
|
|
|
+ height: 34px;
|
|
|
|
|
+ width: 50px;
|
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
|
+ line-height: 34px;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .choosed {
|
|
|
|
|
+ background: #9F643A;
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .bg-yellow {
|
|
|
|
|
+ border-radius: 8px;
|
|
|
|
|
+ background: #ffae45;
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+ width: 74px;
|
|
|
|
|
+ height: 34px;
|
|
|
|
|
+ margin-bottom: 20px;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ margin-left: 20px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .showEcharts {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+
|
|
|
|
|
+ .myCharts {
|
|
|
|
|
+ height: 360px;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .showList {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+
|
|
|
|
|
+ ul {
|
|
|
|
|
+ li {
|
|
|
|
|
+ padding: 15px;
|
|
|
|
|
+ border-bottom: 1px solid #dcdfe6;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ li:hover {
|
|
|
|
|
+ background: #dcdfe6;
|
|
|
|
|
+ cursor: default;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .title {
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ color: #9F643A;
|
|
|
|
|
+ width: 90px;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|
|
|
|
|
+<style lang="scss" scoped>
|
|
|
|
|
+@media screen and (min-width: 1681px) and (max-width: 1920px) {
|
|
|
|
|
+ .showData {
|
|
|
|
|
+ height: 81vh;
|
|
|
|
|
+
|
|
|
|
|
+ .showEcharts {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+
|
|
|
|
|
+ .myCharts {
|
|
|
|
|
+ height: 500px;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+@media screen and (min-width: 1601px) and (max-width: 1680px) {
|
|
|
|
|
+ .showData {
|
|
|
|
|
+ height: 80vh;
|
|
|
|
|
+
|
|
|
|
|
+ .showEcharts {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+
|
|
|
|
|
+ .myCharts {
|
|
|
|
|
+ height: 500px;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+@media screen and (min-width: 1361px) and (max-width: 1600px) {
|
|
|
|
|
+ .showData {
|
|
|
|
|
+ height: 73vh;
|
|
|
|
|
+
|
|
|
|
|
+ .showEcharts {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+
|
|
|
|
|
+ .myCharts {
|
|
|
|
|
+ height: 410px;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+@media screen and(min-width: 1281px) and (max-width: 1360px) {
|
|
|
|
|
+ .showData {
|
|
|
|
|
+ height: 73vh;
|
|
|
|
|
+
|
|
|
|
|
+ .showEcharts {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+
|
|
|
|
|
+ .myCharts {
|
|
|
|
|
+ height: 410px;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|