cyy 1 rok temu
rodzic
commit
907f583707

+ 14 - 0
src/api/platform/spectaculars/lab.js

@@ -0,0 +1,14 @@
+import request from '@/utils/request'
+import { DATA_URL } from '@/api/baseUrl'
+
+/**
+ * 标记为已读
+ * @param {*} params
+ */
+export function labsDashBoard(params) {
+  return request({
+    url: DATA_URL() + '/report/statistic/labsDashBoard',
+    method: 'get',
+    params: params
+  })
+}

+ 219 - 0
src/views/business/labManagement/components/barChart.vue

@@ -0,0 +1,219 @@
+<template>
+  <!-- <div @click="toDetailed()" class="statisticsPage" :style="{width:width}"> -->
+  <div class="statisticsPage" :style="{width:width}">
+    <div :id="'bar'+id" :style="{height:height}"/>
+  </div>
+</template>
+
+<script>
+  import * as echarts from 'echarts'
+  export default {
+    props: {
+      value: {
+        type: Array,
+      },
+      width:{
+        type:String,
+        default:"20%"
+      },
+      height:{
+        type:String,
+        default: "100%"
+      },
+      id:{
+        type:Number,
+        default:1
+      },
+      click:{
+        type:String,
+        default:'true'
+      },
+      colorw:{
+        type:String,
+        default:'true'
+      },
+      direction:{
+        type:String,
+        default:'y'
+      },
+      title:{
+        type: String
+      }
+    },
+    data () {
+      return {
+        dialogOff:false,
+      }
+    },
+    watch: {
+        value: {
+            handler () {
+                this.drawLine()
+            },
+            deep: true
+        }
+    },
+    mounted(){
+      this.drawLine();
+    },
+    methods: {
+      close(){
+        this.dialogOff = false
+      },
+      /* 跳转统计页面*/
+      toDetailed(){
+        if(this.click == "true"){
+        this.dialogOff = true
+       }
+      },
+      drawLine(){
+        let bar = echarts.init(document.getElementById('bar'+this.id))
+        let option;
+        let that = this
+        let barColor = ['#00CCFF','#33FF00','#FF0000','#FFBF00','#097969','#FF66CC','#EC5800','#AAFF00','#F8DE7E','#B87333','#FF4433','	#9F2B68','#C9A9A6','#C3B1E1','#880808','#097969','#89CFF0','#5D3FD3','	#FBCEB1','#E49B0F','#ECFFDC','#A52A2A','#D27D2D','#FFBF00','#A0522D','#FF00FF','#FFB6C1','#F89880','#D8BFD8','#5D3FD3','#770737','#DA70D6']
+        let barNum = []
+        const title = ['name', 'numAll', 'numSuccess', 'numUn']
+        for (let i = 0; i < title.length-1; i++) {
+          if(i==title.length-3){
+            barNum.push({
+              type: 'bar',
+              itemStyle: {color: barColor[i]},
+              label:{
+                show: true,
+				formatter:function(params){ //标签内容
+                    let str = that.direction=='x'?params.value[params.seriesName]+' '+params.data.rate+'%':params.data.rate+'%\n'+params.value[params.seriesName]
+					return str
+			    },
+                position: this.direction=='x'?'right':'top',
+                textStyle:{
+                    fontSize: 12,
+                    color:'#B0CEFC'
+                  }
+              }
+            })
+          }else{
+            barNum.push({
+              type: 'bar',
+              itemStyle: {color: barColor[i]},
+              label:{
+                normal:{
+                  show:true,
+                  position:this.direction=='x'?'right':'top',
+                          
+                  textStyle:{
+                    fontSize: 12,
+                    color:'#B0CEFC'
+                  }
+                }
+              }
+            })
+          }
+          
+        }  
+        let heng = { 
+            splitLine:{show: false},
+            type: 'category',
+            minInterval: 1,
+            min: 0,
+            axisLabel: {
+              show: true,
+              textStyle: {
+                color: this.colorw   //这里用参数代替了
+              },
+              fontSize: 12
+            },
+            axisLine:{
+              show:true,
+              lineStyle:{
+                color:this.colorw,
+                width:1, //x轴线的宽度
+              }
+            },
+            axisTick:{
+              show:true
+            }
+          }
+        let zong = {
+            splitLine:{show: false},
+            minInterval: 1,
+            min: 0,
+            axisLabel: {
+              show: true,
+              textStyle: {
+                color: this.colorw    //这里用参数代替了
+              },
+              fontSize: 12
+            },
+            axisLine:{
+              show:true,
+              lineStyle:{
+                color:this.colorw,
+                width:1, //x轴线的宽度
+              }
+            },
+            axisTick:{
+              show:true
+            }
+          }
+        option = {
+            title: {
+            text: this.title+'各组完成情况',
+            textStyle:{ fontSize:14,color: this.colorw }
+          },
+          legend: {
+                textStyle: {
+                  fontSize: 12,
+                  color: '#B0CEFC'  // 图例文字颜色
+                },
+                top:"5%",
+                formatter: function (name) {
+                  if(name === 'numUn'){
+                    return '未完成数量';
+                  }else if(name === 'numSuccess'){
+                    return '已完成数量(完成率)';
+                  }else if(name === 'numAll'){
+                    return '计划数量';
+                  }
+                    
+                }
+
+          },
+          grid: {
+                top: '15%',
+                left: '3%',
+                right: '4%',
+                bottom: '5%',
+                containLabel: true
+          },
+          xAxis: this.direction=='x'?zong:heng,
+          yAxis: this.direction=='x'?heng:zong,
+          dataset: {
+            dimensions: title,
+            source: this.value
+          },
+          series: barNum,
+          dataZoom: [
+            {
+                id: 'dataZoomY',
+                type: 'inside',
+                yAxisIndex: [0],
+                filterMode: 'empty'
+            }
+          ],
+       
+        };
+       option && bar.setOption(option);
+      }
+    }
+  }
+</script>
+<style scoped>
+  #s8sheBeiHeCha:hover{
+    transition: all 0.5s;
+    transform:scale(1.03);
+  }
+  .statisticsPage{
+     box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+     float: left;
+  }
+</style>

+ 317 - 0
src/views/business/labManagement/components/mergeChart.vue

@@ -0,0 +1,317 @@
+<template>
+  <div  class="statisticsPage">
+    <div :id="id" :style="{height:height,width:width}"/>
+  </div>
+</template>
+
+<script>
+  import * as echarts from 'echarts'
+  import {GetPercent,GetMax} from  '../utils/config.js'
+  import data from '../constants/simulated.js'
+  import { element } from 'screenfull'
+  export default {
+    components:{
+    //   dialogView
+    },
+    props: {
+      data: {
+        type: Array,
+      },
+      width:{
+        type:String,
+        default:"98%"
+      },
+      height:{
+        type:String,
+        default: "95%"
+      },
+      id:{
+        type:String,
+        default:"mergeC"
+      }
+    },
+    data () {
+      return {
+        dialogOff:false,
+        measured:[],
+        hospitalSection:[]
+      }
+    },
+    watch: {
+        data: {
+            handler () {
+                this.drawLine()
+            },
+            deep: true
+        }
+    },
+    mounted(){
+      this.drawLine();
+    },
+    methods: {
+        close(){
+            this.dialogOff = false
+        },
+        
+        drawLine(){
+            let that = this
+            let merge = echarts.init(document.getElementById(this.id))
+            let option
+
+            let timeLineData = []
+            let success = {}
+            let un = {}
+            let rate = {}
+            let ratePie = {}
+            this.extractGroup(this.data)
+            this.data.forEach(element => {
+                timeLineData.push(element.name)
+                success[element.name] = that.dealFormatJH(element, 'numSuccess')
+                un[element.name] = that.dealFormatJH(element, 'numUn')
+                rate[element.name] = that.dealFormatJH(element, 'rate')
+                ratePie[element.name] = element.totally.rate
+            });
+            let optionData = []
+            timeLineData.forEach(element => {
+                optionData.push(that.figureData(element,success,un,rate,ratePie))
+            })
+
+            
+            option = {
+                baseOption: {
+                    timeline: {
+                        axisType: 'category',
+                        autoPlay: true,
+                        playInterval: 2000,
+                        data: timeLineData,
+                        itemStyle: {color:'#fff'},
+                        lineStyle: {color:'#fff'},
+                        label: {color:'#fff', selectedColor: '#ff0000'},
+                        controlStyle: {color:'#fff'},
+                        // label: {
+                        //     formatter: function (s) {
+                        //          return s+'\n计划';
+                        //     }
+                        // }
+                    },
+                    title: {
+                        textStyle: {
+                            color: '#fff'
+                        }
+                    },
+                    tooltip: {},
+                    legend: {
+                        align: 'auto',
+                        data: ['已完成', '未完成','完成率'],
+                        textStyle: {
+                            color: '#fff'
+                        }
+                    },
+                    calculable: true,
+                    grid: {
+                        top: 80,
+                        bottom: 100,
+                        right:'30%',
+                        left:60,
+                        tooltip: {
+                            trigger: 'axis',
+                            axisPointer: {
+                                type: 'shadow',
+                                label: {
+                                    show: true,
+                                    formatter: function (params) {
+                                        return params.value.replace('\n', '');
+                                    }
+                                }
+                            }
+                        }
+                    },
+                    xAxis: [
+                        {
+                            type: 'category',
+                            axisLabel: { interval: 0 },
+                            data:this.hospitalSection,
+                            splitLine: { show: false },
+                            axisLabel: {
+                                show: true,
+                                textStyle: {
+                                    color: '#fff'   //这里用参数代替了
+                                },
+                                fontSize: 12
+                            },
+                            axisLine:{
+                                show: true,
+                                lineStyle:{
+                                    color:'#fff',
+                                    width:1, //x轴线的宽度
+                                }
+                            }
+                        }
+                    ],
+                    yAxis: [
+                        {
+                            type: 'value',
+                            name: '数量',
+                            alignTicks: true,
+                            textStyle: {
+                                color: '#fff'
+                            },
+                            min: 0,
+                            axisLabel: {
+                                show: true,
+                                textStyle: {
+                                    color: '#fff'   //这里用参数代替了
+                                },
+                                fontSize: 12
+                            },
+                            axisLine:{
+                                show: true,
+                                lineStyle:{
+                                    color:'#fff',
+                                    width:1, //x轴线的宽度
+                                }
+                            },
+                            splitLine: {
+                                lineStyle: {
+                                    color: '#5470C6',
+                                }
+                            }
+                        },
+                        {
+                            type: 'value',
+                            name: '完成率(%)',
+                            position: 'right',
+                            alignTicks: false,
+                            max:100.00,
+                            min: 0.00,
+                            axisLabel: {
+                                show: true,
+                                textStyle: {
+                                    color: '#EE6666' 
+                                },
+                                fontSize: 12,
+                                formatter:function(value,index){
+                                    return value.toFixed(2)   
+                                }
+
+                            },
+                            axisLine:{
+                                show: true,
+                                lineStyle:{
+                                    color:'#EE6666',
+                                    width:1, 
+                                }
+                            },
+                            splitLine: {
+                                lineStyle: {
+                                    color: '#5470C6',
+                                }
+                            }
+                        }
+                    ],
+                    series: [
+                        { 
+                            name: '已完成', 
+                            type: 'bar', 
+                            stack: 'Ad' ,  
+                            label: {
+                                show: true
+                            }
+                        },
+                        { 
+                            name: '未完成', 
+                            type: 'bar', 
+                            stack: 'Ad' ,  
+                            label: {
+                                show: true,
+                                color: '#fff'
+                            }
+                        },
+                        {
+                            name: '检验科完成率',
+                            type: 'pie',
+                            center: ['85%', '45%'],
+                            radius: '28%',
+                            z: 100,
+                            itemStyle: {
+                                normal: {
+                                    color: function(params) {
+                                        // 自定义颜色数组
+                                        var colorList = [
+                                            '#26C0C0','#F0805A'
+                                        ];
+                                        return colorList[params.dataIndex % colorList.length];
+                                    }
+                                }
+                            },
+                            label: {
+                                show: true,
+                                color: '#fff', // 设置文字颜色为红色
+                                formatter: '{b}:{d}%',
+                                overflow: 'break'
+                            },
+                            labelLine: {
+                                normal: {
+                                    show: true,
+                                    length: 5,  // 设置标签线基本长度
+                                    length2: 5, // 设置标签线额外长度
+                                }
+                            }
+                        },
+                        {
+                            name: '完成率',
+                            type: 'line',
+                            yAxisIndex: 1,
+                        }
+                    ]
+                },
+                options: optionData
+            }
+            option && merge.setOption(option);
+        },
+        dealFormatJH(e,n){
+            let mid = []
+            e.groups.forEach((l,i)=>{
+                mid.push({name:l.name,value:l[n]})
+            })
+            return mid
+        },
+        figureData(element,success,un,rate,ratePie){
+            let mid = {
+                title: { text: element },
+                series: [
+                    { data: success[element] },
+                    { data: un[element] },
+                    {
+                        data: [
+                            { name: '完成率', value: ratePie[element] },
+                            { name: '未完成率', value: 100-ratePie[element] }
+                        ]
+                    },
+                    { data: rate[element] }
+                ]
+            }
+            return mid
+        },
+        extractGroup(val){
+            this.hospitalSection=[]
+            if(val.length>0&&val[0].groups.length>0){
+                val[0].groups.forEach((e,i)=>{
+                    this.hospitalSection.push(e.name)
+                })
+            }
+        }
+    }
+  }
+</script>
+<style scoped>
+  .statisticsPage{
+    width: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    height: calc(100% - 40px);
+    /* padding: 20px 2%; */
+    background-color: rgba(6, 30, 93, 0.5);
+  }
+</style>

+ 119 - 0
src/views/business/labManagement/components/pieChart.vue

@@ -0,0 +1,119 @@
+<template>
+  <div class="statisticsPage" :style="{width:width}">
+    <div :id="'pie'+id" :style="{height:height}"/>
+  </div>
+</template>
+
+<script>
+  import * as echarts from 'echarts'
+  export default {
+    props: {
+      value: {
+        type: Object,
+      },
+      width:{
+        type:String,
+        default:"20%"
+      },
+      height:{
+        type:String,
+        default: "100%"
+      },
+      id:{
+        type:Number,
+        default:0
+      },
+      click:{
+        type:String,
+        default:'true'
+      },
+      colorw:{
+        type:String,
+        default:'true'
+      },
+      wancheng:{
+        type:String,
+        default:'完成率'
+      },
+      weiwancheng:{
+        type:String,
+        default:'未完成率'
+      },
+      title:{
+        type: String
+      }
+    },
+    data () {
+      return {
+        dialogOff:false,
+        measured:[]
+      }
+    },
+    watch: {
+        value: {
+            handler () {
+                this.drawLine()
+            },
+            deep: true
+        }
+    },
+    mounted(){
+      this.drawLine();
+    },
+    methods: {
+      close(){
+        this.dialogOff = false
+      },
+      drawLine(){
+        let pie = echarts.init(document.getElementById('pie'+this.id))
+        let option;
+        let e = (100-this.value.rate).toFixed(2)
+        option = {
+          title: {
+            text: this.title+'完成率',
+            left: 'left',
+            textStyle:{ fontSize:14,color: this.colorw }
+          },
+          tooltip: {
+            trigger: 'item'
+          },
+          color:['#66CC00','#CC0000'],
+          series: [
+            {
+              type: 'pie',
+              radius: '50%',
+              label: {
+                formatter: '{b}: {d}%',
+                color: '#000',
+                fontSize: '12px'
+              },
+              data: [
+                { value: this.value.rate, name: this.wancheng },
+                { value: e, name: this.weiwancheng }
+              ],
+              emphasis: {
+                itemStyle: {
+                  shadowBlur: 10,
+                  shadowOffsetX: 0,
+                  shadowColor: 'rgba(0, 0, 0, 0.5)'
+                }
+              }
+            }
+          ]
+       };
+
+       option && pie.setOption(option);
+      }
+    }
+  }
+</script>
+<style scoped>
+  #zlmbPie:hover{
+    transition: all 0.5s;
+    transform:scale(1.03);
+  }
+  .statisticsPage{
+     box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+     float: left;
+  }
+</style>

+ 165 - 0
src/views/business/labManagement/components/tabular.vue

@@ -0,0 +1,165 @@
+<template>
+    <div :class="$style.box">
+        <div :class="$style.left">
+            <div
+                v-for="(item, index) in statData"
+                :key="index"
+                :class="$style.stat"
+            >
+                <div :class="$style.title">{{ item.title }}</div>
+                <div
+                    v-for="(v, i) in item.children"
+                    :key="i"
+                    :class="$style['stat-item']"
+                >
+                    <div :class="$style.label">{{ v.label }}</div>
+                    <div :class="$style.count">
+                        <dv-digital-flop
+                            :config="v.data"
+                            :class="$style.flop"
+                        />
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+<script>
+import { colors, getRandomColor, barChartOption } from '../constants/option'
+export default {
+    components: {},
+    props: {
+        value:{
+            type:Array
+        },
+        list: {
+            type: Array,
+            default: () => []
+        },
+        range: {
+            type: Array,
+            default: () => []
+        },
+        // fontSize: {
+        //     type: Number,
+        //     default: 18
+        // }
+    },
+    data () {
+        return {
+            stat: this.value,
+            statData: [],
+        }
+    },
+    computed: {},
+    watch: {
+        value: {
+            handler () {
+                this.init()
+            },
+            deep: true
+        }
+    },
+    mounted () {
+        this.init()
+    },
+    methods: {
+        init () {
+            const fontColor = [...colors].sort(() => Math.random() - 0.5)
+            const colorGenerator = getRandomColor(fontColor)
+            this.value.forEach(item => {
+                item.children.forEach(i => {
+                    i.data = {
+                        number: [i.value],
+                        content: '{nt}',
+                        textAlign: 'right',
+                        style: {
+                            fill: colorGenerator.next().value,
+                            fontWeight: 'bold'
+                        }
+                    }
+                })
+            })
+            this.statData = JSON.parse(JSON.stringify(this.value))
+            const D = new Date()
+            const w = window.innerWidth
+            this.fontSize = w >= 1600 ? 20 : w > 1366 && w < 1600 ? 18 : 16
+        }
+    }
+}
+</script>
+<style lang="scss" module>
+    .box {
+        width: 96%;
+        height: calc(100% - 40px);
+        padding:0 1%;
+        display: flex;
+        :global {
+            .dv-decoration-10 {
+                width: 96%;
+                height: 5px;
+                margin: 15px 2%;
+            }
+            .dv-decoration-2 {
+                width:5px;
+                height:100%;
+            }
+        }
+        .left {
+            position: relative;
+            width: 100%;
+            height: 100%;
+            display: flex;
+            // flex-shrink: 0;
+            flex-direction: column;
+            background-color: rgba(6, 30, 93, 0.4);
+            .stat {
+                // flex: 1;
+                height: 16.35%;
+                padding: 0 16px;
+                border-bottom: 5px solid rgb(6, 30, 93);
+                &:last-child {
+                    border-bottom: none;
+                }
+                .title {
+                    text-align: center;
+                    font-size: 24px;
+                    font-weight: bold;
+                    margin: 16px 0;
+                }
+                .stat-item {
+                    display: inline-block;
+                    width: 33%;
+                    .label{
+                        text-align: center;
+                        font-size: 16px;
+                    }
+                    .count {
+                        display: flex;
+                        align-items: center;
+                        justify-content: center;
+                        .flop {
+                            width: 60px;
+                            height: 40px;
+                            margin-left: -20px;
+                            font-size: 18px;
+                        }
+                        .unit {
+                            margin-left: 10px;
+                            box-sizing: border-box;
+                        }
+                    }
+                }
+            }
+        }
+        .chart {
+            height: 100%;
+            flex: 1;
+            margin: 20px 1%;
+            .chart-item {
+                height: 33%;
+                width: 100%;
+            }
+        }
+    }
+</style>

+ 349 - 0
src/views/business/labManagement/constants/option.js

@@ -0,0 +1,349 @@
+import * as echarts from 'echarts'
+
+const rowLimit = (params, max) => {
+    let result = ''
+    // 一行显示几个字
+    const rowMax = max
+    const rowNumber = Math.ceil(params.length / rowMax)
+    // 超过 3 个字换行
+    if (params.length > 3) {
+        for (let p = 0; p < rowNumber; p++) {
+            let tempStr = ''
+            const start = p * rowMax
+            const end = start + rowMax
+            if (p === rowNumber - 1) {
+                tempStr = params.substring(start, params.length)
+            } else {
+                tempStr = params.substring(start, end) + '\n'
+            }
+            result += tempStr
+        }
+    } else {
+        result = params
+    }
+    return result
+}
+
+const basicChart = {
+    title: {
+        show: true,
+        text: '',
+        subtext: '',
+        textStyle: {
+            color: '#fff',
+            fontSize: 24,
+            fontWeight: '600'
+        },
+        subtextStyle: {
+            color: '#fff',
+            fontSize: 14,
+            fontWeight: '400',
+            align: 'center'
+        },
+        textAlign: 'center',
+        left: '50%',
+        top: '5px'
+    },
+    grid: {
+        top: '80px',
+        bottom: '30px'
+    },
+    xAxis: {
+        type: 'category',
+        data: [],
+        axisTick: {
+            alignWithLabel: true
+        },
+        axisLabel: {
+            style: {
+                fill: '#fff'
+            },
+            formatter (params) {
+                return rowLimit(params, 4)
+            }
+        },
+        axisLine: {
+            lineStyle: {
+                color: '#fff'
+            }
+        }
+    },
+    yAxis: {
+        type: 'value',
+        name: '',
+        nameTextStyle: {
+            color: '#fff',
+            fontSize: 14
+        },
+        splitLine: {
+            show: false
+        },
+        axisLine: {
+            lineStyle: {
+                color: '#fff'
+            }
+        }
+    },
+    series: [{
+        type: 'line',
+        name: '合格率',
+        data: [],
+        markLine: {
+            data: [
+                {
+                    yAxis: '',
+                    tooltip: {
+                        formatter: ''
+                    },
+                    label: {
+                        show: true, position: 'inside',
+                        color: '#83bff6',
+                        formatter: ''
+                    },
+                    lineStyle: {
+                        color: '#ff4757',
+                        type: 'dashed'
+                    }
+                }
+            ]
+        },
+        itemStyle: {
+            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                { offset: 0, color: '#83bff6' },
+                { offset: 0.5, color: '#188df0' },
+                { offset: 1, color: '#188df0' }
+            ])
+        },
+        emphasis: {
+            itemStyle: {
+                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                    { offset: 0, color: '#2378f7' },
+                    { offset: 0.7, color: '#2378f7' },
+                    { offset: 1, color: '#83bff6' }
+                ])
+            }
+        },
+        label: {
+            show: true,
+            position: 'top',
+            textStyle: {
+                color: '#fff',
+                fontSize: 14
+            },
+            formatter (params) {
+                return params.value ? params.value : ''
+            }
+        }
+    }],
+    tooltip: {
+        show: true,
+        trigger: 'axis',
+        formatter: '指标详情<br/>{b}月:{c}'
+    }
+}
+
+export const colors = [
+    '#d20962',
+    '#f47721',
+    '#7ac143',
+    '#00a78e',
+    '#00bce4',
+    '#7d3f98',
+    '#037ef3',
+    '#f85a40',
+    '#00c16e',
+    '#12CBC4',
+    '#b4a996',
+    '#7552cc',
+    '#67809f',
+    '#f19066'
+]
+
+export function* getRandomColor (shuffledColors) {
+    let index = 0
+    while (index < shuffledColors.length) {
+        yield shuffledColors[index]
+        index++
+    }
+}
+
+export const monthChartOption = basicChart
+
+export const quarterChartOption = {
+    ...basicChart,
+    series: [{
+        type: 'bar',
+        name: '',
+        data: [],
+        markLine: {
+            data: [
+                {
+                    yAxis: '',
+                    tooltip: {
+                        formatter: ''
+                    },
+                    label: {
+                        show: true, position: 'inside',
+                        color: '#83bff6',
+                        formatter: ''
+                    },
+                    lineStyle: {
+                        color: '#ff4757',
+                        type: 'dashed'
+                    }
+                }
+            ]
+        },
+        itemStyle: {
+            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                { offset: 0, color: '#83bff6' },
+                { offset: 0.5, color: '#188df0' },
+                { offset: 1, color: '#188df0' }
+            ])
+        },
+        emphasis: {
+            itemStyle: {
+                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                    { offset: 0, color: '#2378f7' },
+                    { offset: 0.7, color: '#2378f7' },
+                    { offset: 1, color: '#83bff6' }
+                ])
+            }
+        },
+        label: {
+            show: true,
+            position: 'top',
+            textStyle: {
+                color: '#fff',
+                fontSize: 14
+            },
+            formatter (params) {
+                return params.value ? params.value : ''
+            }
+        }
+    }],
+    tooltip: {
+        show: true,
+        trigger: 'axis',
+        formatter: '指标详情<br/>{b}:{c}'
+    }
+}
+
+export const yearChartOption = {
+    ...basicChart,
+    series: [{
+        type: 'bar',
+        name: '',
+        data: [],
+        markLine: {
+            data: [
+                {
+                    yAxis: '',
+                    tooltip: {
+                        formatter: ''
+                    },
+                    label: {
+                        show: true, position: 'inside',
+                        color: '#83bff6',
+                        formatter: ''
+                    },
+                    lineStyle: {
+                        color: '#ff4757',
+                        type: 'dashed'
+                    }
+                }
+            ]
+        },
+        itemStyle: {
+            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                { offset: 0, color: '#83bff6' },
+                { offset: 0.5, color: '#188df0' },
+                { offset: 1, color: '#188df0' }
+            ])
+        },
+        emphasis: {
+            itemStyle: {
+                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                    { offset: 0, color: '#2378f7' },
+                    { offset: 0.7, color: '#2378f7' },
+                    { offset: 1, color: '#83bff6' }
+                ])
+            }
+        },
+        label: {
+            show: true,
+            position: 'top',
+            textStyle: {
+                color: '#fff',
+                fontSize: 14
+            },
+            formatter (params) {
+                return params.value ? params.value : ''
+            }
+        }
+    }],
+    tooltip: {
+        show: true,
+        trigger: 'axis',
+        formatter: '指标详情<br/>{b}年度:{c}'
+    }
+}
+
+export const lineChartOption = {
+    ...basicChart,
+    grid: {
+        top: '80px',
+        bottom: '30px',
+        left: '30px',
+        right: '30px'
+    }
+}
+
+export const barChartOption = {
+    ...basicChart,
+    grid: {
+        top: '80px',
+        bottom: '30px',
+        left: '30px',
+        right: '30px'
+    },
+    series: [
+        {
+            type: 'bar',
+            name: '中位数',
+            data: [],
+            barMaxWidth: '35px',
+            barStyle: {
+                fill: 'rgba(0, 186, 255, 0.4)'
+            },
+            itemStyle: {
+                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                    { offset: 0, color: "#83bff6" },
+                    { offset: 0.5, color: "#188df0" },
+                    { offset: 1, color: "#188df0" },
+                ])
+            },
+            emphasis: {
+                itemStyle: {
+                    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                        { offset: 0, color: "#2378f7" },
+                        { offset: 0.7, color: "#2378f7" },
+                        { offset: 1, color: "#83bff6" },
+                    ])
+                }
+            },
+            label: {
+                show: true,
+                position: 'top',
+                textStyle: {
+                    color: '#fff',
+                    fontSize: 14
+                },
+                formatter (params) {
+                    return params.value ? params.value : ''
+                }
+            }
+        },
+        ...basicChart.series
+    ]
+}

+ 387 - 0
src/views/business/labManagement/constants/simulated.js

@@ -0,0 +1,387 @@
+export const hospitalSection = ['综合/质量管理组', '临检组', '生化组', '免疫组', '微生物组']
+
+export const dataObj = [
+    {
+        name:'在岗人员培训计划',
+        groups:[
+            {
+                'name':'综合/质量管理组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'临检组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'生化组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'免疫组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'微生物组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            }
+        ],
+        totally:{
+            'name': '检验科',
+            'numAll': 22,
+            'numSuccess': 11,
+            'numUn': 11,
+            'rate': 50
+        }
+    },
+    {
+        name:'岗前培训计划',
+        groups:[
+            {
+                'name':'综合/质量管理组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'临检组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'生化组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'免疫组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'微生物组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            }
+        ],
+        totally:{
+            'name': '检验科',
+            'numAll': 22,
+            'numSuccess': 11,
+            'numUn': 11,
+            'rate': 50
+        }
+    },
+    {
+        name:'设备检定/校准计划',
+        groups:[
+            {
+                'name':'综合/质量管理组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'临检组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'生化组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'免疫组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'微生物组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            }
+        ],
+        totally:{
+            'name': '检验科',
+            'numAll': 22,
+            'numSuccess': 11,
+            'numUn': 11,
+            'rate': 50
+        }
+    },
+    {
+        name:'设备维护计划',
+        groups:[
+            {
+                'name':'综合/质量管理组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'临检组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'生化组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'免疫组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'微生物组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            }
+        ],
+        totally:{
+            'name': '检验科',
+            'numAll': 22,
+            'numSuccess': 11,
+            'numUn': 11,
+            'rate': 50
+        }
+    },
+    {
+        name:'内部比对实验计划',
+        groups:[
+            {
+                'name':'综合/质量管理组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'临检组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'生化组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'免疫组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'微生物组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            }
+        ],
+        totally:{
+            'name': '检验科',
+            'numAll': 22,
+            'numSuccess': 11,
+            'numUn': 11,
+            'rate': 50
+        }
+    },
+    {
+        name:'外部质量评价计划',
+        groups:[
+            {
+                'name':'综合/质量管理组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'临检组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'生化组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'免疫组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'微生物组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            }
+        ],
+        totally:{
+            'name': '检验科',
+            'numAll': 22,
+            'numSuccess': 11,
+            'numUn': 11,
+            'rate': 50
+        }
+    },
+    ,
+    {
+        name:'应急预案演练计划',
+        groups:[
+            {
+                'name':'综合/质量管理组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'临检组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'生化组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'免疫组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'微生物组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            }
+        ],
+        totally:{
+            'name': '检验科',
+            'numAll': 22,
+            'numSuccess': 11,
+            'numUn': 11,
+            'rate': 50
+        }
+    },
+    ,
+    {
+        name:'实验室风险活动识别与控制计划',
+        groups:[
+            {
+                'name':'综合/质量管理组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'临检组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'生化组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'免疫组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            },
+            {
+                'name':'微生物组',
+                'numAll': 22,
+                'numSuccess': 11,
+                'numUn': 11,
+                'rate': 50
+            }
+        ],
+        totally:{
+            'name': '检验科',
+            'numAll': 22,
+            'numSuccess': 11,
+            'numUn': 11,
+            'rate': 50
+        }
+    }
+]
+
+export default {
+    dataObj,
+    hospitalSection
+}

+ 322 - 0
src/views/business/labManagement/dataStatistics.vue

@@ -0,0 +1,322 @@
+<template>
+    <div class="screen" ref="scrollDiv" >
+      <div class="statistics">
+        <div class="editDate" style="background-color: rgba(0,0,0,0);display: block;width: 100%;height: 10%;">
+          <div 
+            style="width: 100%;
+            height:45%;
+            line-height: 45%;
+            text-align:center;
+            float: left;
+            margin: 2% 0 1% 1%;
+            font-size: 100%;
+            color: #fff !important;
+            align-items: center;
+            display:flex" >
+            <div style="color:#000;">
+              年份:
+            </div>
+            <el-date-picker
+                v-model="endDate"
+                type="year"
+                value-format="yyyy"
+                format="yyyy"
+                placeholder="统计年度"
+                style="width: 120px;background-color: rgba(0,0,0,0);"
+                :readonly="false"
+                :editable="true"
+                :clearable="false"
+                @change="checkYear(endDate,'end')"
+            />
+          </div>
+        </div>
+        <div>
+            <div v-for="(item,i) in requestData" :key="i">
+                <pie-chart :height="'200%'" :key="i+i+1" :id="i+i+1"  :colorw = "colorw" style="box-shadow:none;width:100%;" :title="item.name"
+                    v-if="showAll || showComponents[i+i+1]" v-model="item.totally"/>
+                <bar-chart :height="'500%'" :key="i+i+2" :id="i+i+2" :width="static=='row' ? '75%': '100%'" :colorw = "colorw" :direction="direction" style="box-shadow:none;width:100%;"  :title="item.name"
+                    v-if="showAll || showComponents[i+i+2]" v-model= "item.groups"/>
+            </div>
+        </div>
+      </div>
+    </div>
+</template>
+
+<script>
+  //全屏展示
+  import screenfull from 'screenfull'
+  import dataMock from './constants/simulated'
+  import PieChart from './components/pieChart.vue'
+  import BarChart from './components/barChart.vue'
+  import { labsDashBoard } from '@/api/platform/spectaculars/lab'
+
+  export default {
+    components:{
+      PieChart,
+      BarChart
+    },
+    props:{
+        shows:{ //传入的内容显示序号
+            type: Array,
+            default:() => []
+        },
+        static:{ //显示类型,默认为横向   ,作为表单统计图的外部引用为 line
+            type: String,
+            default:'row'
+        }
+    },
+    created() {
+        this.getConfigData(this.endDate)
+    },
+    mounted() {
+      /*以shows是否有参数来判断, 是否需要仅显示部分子组件*/
+      if(this.shows.length>0){
+        this.showAll=false
+        this.isShowComponents()
+      }
+      /* 开始及结束时间的默认设置*/
+    //   if (!this.BeginDate && !this.endDate) {
+    //     this.BeginDate = this.getDate(1) + ''
+    //     this.endDate = this.getDate(0)
+    //     this.dataScope.push(this.BeginDate)
+    //     this.dataScope.push(this.endDate)
+    //   }   
+    },
+    updated() {
+        //this.drawLine();
+        this.allEcharts.forEach((i) => {
+          i.resize();
+        });
+
+    },
+    data() {
+      const d = new Date()
+      return {
+        direction:'x',
+        height:(window.screen.height-200)+"px",
+        BeginDate: '',
+        endDate: d.toJSON().slice(0, 4),
+        relOf: false,
+        showAll:true,
+        showComponents:{},//显示全部统计子组件 , 若有新增,往后累计。 供动态表单进行查阅使用。
+        dataScope: [],
+        colorw: '#000',
+        quality:[],
+        allEcharts:[],
+        requestData:[]
+      }
+    },
+    beforeDestroy() {
+      if(screenfull.isFullscreen){
+        screenfull.toggle()
+      }
+    },
+    methods: {
+      /* 判断是否统计子组件中传递过来的,是否需要隐藏。若需要则进行隐藏的遍历  */
+      isShowComponents(){
+        /* 将参数进行显示 */
+          for(let i=0;i<this.shows.length;i++){
+            this.showComponents[this.shows[i]] = true
+          }
+      },
+      getNextMonth(date) {
+            let arr = date.split('-');
+            let year = arr[0]; //获取当前日期的年份
+            let month = arr[1]; //获取当前日期的月份
+            let year2 = year;
+            let month2 = parseInt(month) + 1;
+            if (month2 == 13) {
+                year2 = parseInt(year2) + 1;
+                month2 = 1;
+            }
+            month2=month2>9?month2:'0'+month2
+            let t2 = year2 + '-' +  month2;
+            return t2;
+      },
+      /* 查询统计配置中的完成率*/
+      getConfigData(end) {
+        let that = this
+        // dataMock
+        labsDashBoard({year: this.endDate}).then(res=>{
+            this.requestData = res.data
+        })
+      },
+      /* 查询全部*/
+      selectAll() {
+        this.getConfigData(this.endDate)
+        this.relOf = true
+      },
+      checkYear(year, data) {
+        this.selectAll()
+      },
+      /* 获取当前年份*/
+      getDate(year) {
+        year = year || 0
+        let nowDate = new Date();
+        let date = new Date(new Date().setDate(1)+ 31 * 24 * 60 * 60 * 1000);
+        let month = date.getMonth()+1;
+        let m1 = nowDate.getMonth()+1
+        let month1 = m1 < 10 ? "0" +m1:nowDate.getMonth()+1;
+        month = month<10 ? "0"+month : ""+month;
+        return [nowDate.getFullYear() - year + "-01",nowDate.getFullYear() - year + "-" + month1];
+      },
+   
+      goBack(){
+        this.$router.back(-1)
+        this.fadeinout = true
+      }
+    }
+  }
+</script>
+
+
+<style lang="scss" scoped>
+  .statistics {
+    height: 100%;
+    color: #fff;
+    .editDate{
+      display: contents;
+      overflow: hidden;
+      background-color:rgb(249, 255, 255);
+      position: relative;
+
+    }
+    .block{
+      float: left;
+      font-size: 14px;
+     }
+  }
+  #dv-full-screen-container {
+    background-size: 100% 100%;
+    box-shadow: 0 0 3px blue;
+    display: flex;
+    flex-direction: column;
+    display: flex;
+    flex-direction:column;
+    align-items: stretch;
+  }
+  .el-scrollbar__wrap{
+    overflow-x: hidden;
+  }
+  .goBackButton{
+    width: 2%;
+    position: absolute;
+    right: 0;
+  }
+  .shiyankanbanfanhui{
+    border: none;
+    .border-box-content{
+      display: flex;
+      align-items: center;
+      justify-content: center;
+    }
+  }
+  .stitle{
+    text-align: center;
+    font-size: 150%;
+    font-weight: 600;
+    margin: 0;
+  }
+  .ttitle{
+    font-size: 120%;
+    font-weight: 600;
+    height: 2%;
+    margin: 1% 0;
+  }
+  .screen{
+    height: 100%;
+    
+    margin: 0 0.5%;
+  }
+  .clear{ clear: both; }
+  .congxiebox7{
+    background-color: rgba(6, 30, 93, 0.5);
+    box-shadow: rgb(128 128 128 / 30%) 0px 0px 40px inset;
+    border: 1px solid rgba(128, 128, 128, 0.3);
+    margin: 1% 0 0 0 ;
+    font-size: 12px;
+  }
+  .gongshiAll{
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    // width: 20%;
+    .touwidth{
+      width: 30%;
+      text-align:right;
+    }
+    .gongshiXian{
+      border-bottom: #fff solid 2px;
+      padding-bottom: 6%;
+      text-align:center;
+      font-size: 12px;
+    }
+  }
+  .mubiaozhi{
+    text-align: center;
+    margin-top: 3%;
+  }
+  .nullDate{
+    height: 100%;
+    text-align: center;
+    line-height: 100%;
+    font-size: 6vh;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+  .componentsData{
+    height: 92%;
+  }
+  .nullDate1{
+    height: 50%;
+    width: 25%;
+    display: inline-block;
+    text-align: center;
+    line-height: 50%;
+    font-size: 2vh;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+</style>
+<style lang="scss">
+.el-year-table .today .cell {
+  color: #606266 !important;
+  font-weight: 100 !important;
+}
+ 
+</style>
+<style lang="scss" scoped>
+
+::v-deep .el-input__inner {
+  background-color: rgba(0,0,0,0);
+  color: #000;
+}
+::v-deep .el-dialog__body{
+  height:80%;
+  width:80%;
+}
+.fade-in {
+  animation: fadeIn 1s linear forwards;
+}
+@keyframes fadeIn {
+  from {
+    opacity: 0;
+  }
+  to {
+    opacity: 1;
+  }
+}
+.fade-out {
+  animation: fadeOut 1s linear forwards;
+}
+@keyframes fadeOut {
+  from {
+    opacity: 1;
+  }
+  to {
+    opacity: 0;
+  }
+}
+</style>

+ 352 - 0
src/views/business/labManagement/index.vue

@@ -0,0 +1,352 @@
+<template>
+    <div :class="$style.content">
+        <dv-full-screen-container>
+            <!-- 头部内容 -->
+            <div :class="$style.header">
+                <dv-decoration-8 :class="$style.left" />
+                <dv-decoration-5 :class="$style.center" :dur="5" />
+                <dv-decoration-8 :class="$style.right" :reverse="true" />
+                <div :class="$style.title">{{ title }}</div>
+                <dv-border-box-8 :class="$style.year">
+                    <el-date-picker
+                        v-model="year"
+                        type="year"
+                        value-format="yyyy"
+                        format="yyyy"
+                        placeholder="统计年度"
+                        style="width: 80px"
+                        :readonly="false"
+                        :editable="true"
+                        :clearable="false"
+                        @change="updateAll"
+                    />
+                </dv-border-box-8>
+                <!-- <dv-decoration-7 :class="$style.cycle">
+                    <el-dropdown @command="changeCycle">
+                        <span class="el-dropdown-link" :style="`font-size: ${fontSize}px;`">{{ selectedCycle }}</span>
+                        <el-dropdown-menu slot="dropdown" class="dept-dropdown">
+                            <el-dropdown-item
+                                v-for="(item, index) in cycleList"
+                                :key="index"
+                                :command="index"
+                            >{{ item }}</el-dropdown-item>
+                        </el-dropdown-menu>
+                    </el-dropdown>
+                </dv-decoration-7> -->
+                <div :class="$style.back" @click.prevent="goBack()">
+                    <dv-border-box-8>返回</dv-border-box-8>
+                </div>
+                <!-- <div :class="$style.parse" @click="toggleAutoPlay">
+                    <img v-if="autoPlay" src="~@/assets/images/icons/parse.png">
+                    <img v-else src="~@/assets/images/icons/play.png">
+                </div> -->
+            </div>
+            <!-- 图表区域 -->
+            <dv-border-box-1>
+                <div class="vessel">
+                    <tabular class="tabular" v-model="tabularArr1"/>
+                    <merge-chart class="merge" :data="mergeData" />
+                    <tabular v-if="tabularArr2.length>0" class="tabular" v-model="tabularArr2"/>
+                </div>
+            </dv-border-box-1>
+        </dv-full-screen-container>
+    </div>
+</template>
+<script>
+import screenfull from 'screenfull'
+import { labsDashBoard } from '@/api/platform/spectaculars/lab'
+export default {
+    components: {
+        MergeChart: () => import('./components/mergeChart.vue'),
+        Tabular: () => import('./components/tabular.vue')
+    },
+    data () {
+        const d = new Date()
+        return {
+            level: '',
+            title: '实验室管理看板',
+            year: d.toJSON().slice(0, 4),
+            cycleList: [],
+            initData: {},
+            fontSize: 18,
+            itemIndex: 0,
+            chartIndex: 0,
+            autoPlay: true,
+            tabularArr1:[],
+            tabularArr2:[],
+            mergeData:[]
+        }
+    },
+    computed: {
+        selectedCycle () {
+            return this.cycleList[this.itemIndex] || '每月'
+        },
+        size () {
+            return this.sizeMap[this.selectedCycle]
+        }
+    },
+    watch: {
+    },
+    created () {
+        // 默认全屏展示
+        if (screenfull.isEnabled && !screenfull.isFullscreen) {
+            screenfull.request()
+        }
+
+        this.updateAll()
+    },
+    beforeDestroy () {
+        if (screenfull.isFullscreen) {
+            screenfull.toggle()
+        }
+        // this.clenUp()
+    },
+    methods: {
+        initializeData () {
+            const w = window.innerWidth
+            const { first = '', second = '' } = this.$store.getters.level || {}
+
+            this.initData = {}
+            this.itemIndex = 0
+            this.chartIndex = 0
+            this.level = second || first
+            this.fontSize = w >= 1600 ? 20 : w > 1366 && w < 1600 ? 18 : 16
+            this.tabularArr1=[]
+            this.tabularArr2=[]
+        },
+        updateAll () {
+            this.initializeData()
+            // this.fetchData().then(() => {})
+            labsDashBoard({year: this.year}).then(res=>{
+                
+                this.mergeData = res.data
+                this.mergeData.forEach((item,i)=>{
+                    const child = [
+                        {
+                            label: '计划完成数',
+                            value: item.totally.numAll
+                        },
+                        {
+                            label: '已完成数',
+                            value: item.totally.numSuccess
+                        },
+                        {
+                            label: '未完成数',
+                            value: item.totally.numUn
+                        }
+                    ]
+                    const mid = {title:item.name,children:child}
+                    if(i<=5){
+                        this.tabularArr1.push(mid)
+                    }else{
+                        this.tabularArr2.push(mid)
+                    }
+                    console.log(this.tabularArr1,this.tabularArr2,'resresresres')
+
+                })
+            })
+            
+        },
+        async fetchData () {
+            // 月度指标统计本年度,季度指标统计今年和去年,年度指标统计所有
+            // const sql = `select a.id_ as aid, a.di_dian_ as place, a.bian_zhi_bu_men_ as dept, a.tong_ji_pin_lv_ as cycle, a.tong_ji_yue_fen_ as statisticalTime, a.create_time_ as createTime, b.id_ as bid, b.zhi_liang_mu_biao as goal, b.zhi_liang_zhi_bia as target, b.zhi_biao_xian_zhi as limitValue, b.shi_ji_shu_zhi_ as result, b.yuan_shi_shu_ju_ as originalData from t_zlzbpjb a inner join (select tong_ji_yue_fen_, max(create_time_) as max from t_zlzbpjb group by tong_ji_yue_fen_) a_latest on a.tong_ji_yue_fen_ = a_latest.tong_ji_yue_fen_ and a.create_time_ = a_latest.max left join t_zlzbpjzb b on a.id_ = b.parent_id_ where a.shi_fou_guo_shen_ = '已完成' and a.di_dian_ = '${this.level}' and ((a.tong_ji_pin_lv_ = '每月' and a.tong_ji_yue_fen_ like '${this.year}%') or (a.tong_ji_pin_lv_ = '每季度' and (a.tong_ji_yue_fen_ like '${this.year}%' or a.tong_ji_yue_fen_ like '${this.year - 1}%')) or a.tong_ji_pin_lv_ = '每年')`
+            // return new Promise((resolve, reject) => {
+            //     this.$common.request('sql', sql).then(res => {
+                    
+            //         resolve()
+            //     }).catch(error => {
+            //         reject(error)
+            //     })
+            // })
+        },
+        goBack () {
+            this.$router.back(-1)
+        }
+    }
+}
+</script>
+<style lang="scss" module>
+    .content {
+        width: 100%;
+        height: 100%;
+        background-color: #030409;
+        position: absolute;
+        color: #fff;
+        z-index: 999;
+        :global {
+            #dv-full-screen-container {
+                background-image: url('~@/assets/images/screen/bg.png');
+                background-size: 100% 100%;
+                box-shadow: 0 0 3px blue;
+                display: flex;
+                flex-direction: column;
+            }
+            .dv-border-box-1 .border-box-content{
+                height: calc(100vh - 90px);
+                .vessel{
+                    width: 98%;
+                    height: 98%;
+                    padding: 30px 1%;
+                    display: flex;
+                    .tabular{
+                        width: 20%;
+                    }
+                    .merge{
+                        width: 80%;
+                    }
+                }
+            }
+            .main-content {
+                flex: 1;
+                display: flex;
+                flex-direction: column;
+            }
+
+            .block-left-right-content {
+                flex: 1;
+                display: flex;
+                margin-top: 0.8%;
+            }
+
+            .block-top-bottom-content {
+                flex: 1;
+                display: flex;
+                flex-direction: column;
+                box-sizing: border-box;
+                padding-left: 0.8%;
+            }
+
+            .block-top-content {
+                height: 55%;
+                display: flex;
+                flex-grow: 0;
+                box-sizing: border-box;
+                padding-bottom: 0.8%;
+            }
+        }
+        .header {
+            position: relative;
+            width: 100%;
+            height: 90px;
+            display: flex;
+            justify-content: space-between;
+            flex-shrink: 0;
+            .left, .right {
+                width: 25%;
+                height: 60px;
+            }
+            .center {
+                width: 40%;
+                height: 60px;
+                margin-top: 30px;
+            }
+            .title {
+                position: absolute;
+                font-size: 30px;
+                font-weight: bold;
+                left: 50%;
+                top: 15px;
+                transform: translateX(-50%);
+            }
+            .year, .cycle, .back, .parse {
+                width: 8%;
+                max-width: 180px;
+                cursor: pointer;
+                height: 2.825rem;
+                line-height: 2.825rem;
+                text-align: center;
+                margin-top: 2%;
+                flex: 1;
+                position: absolute;
+                color: #ffffff;
+            }
+            .year {
+                width: 5%;
+                right: 83%;
+                display: flex;
+                justify-content: center;
+                align-items: center;
+                :global {
+                    .el-input--small .el-input__inner {
+                        width: 100% !important;
+                        background: rgba(255, 255, 255, 0);
+                        border: none;
+                        color: #fff;
+                        font-size: 16px;
+                        cursor: pointer;
+                        // padding-left: 0;
+                        padding-right: 0;
+                    }
+                }
+            }
+            .cycle {
+                display: flex;
+                min-width: 150px;
+                justify-content: flex-end;
+                // width: 125px;
+                right: 75%;
+                padding-left: 10px;
+                color: #fff;
+                font-size: 22px;
+                font-weight: 400;
+                :global {
+                    .el-dropdown {
+                        width: calc(100% - 52px);
+                        text-overflow: ellipsis;
+                        overflow: hidden;
+                        white-space: nowrap;
+                        .el-dropdown-link {
+                            text-align: center;
+                        }
+                    }
+                }
+            }
+            .back {
+                width: 5%;
+                left: calc(75% + 80px);
+            }
+            .parse {
+                width: 2%;
+                left: 75%;
+                align-items: center;
+                padding: 5px;
+                > img {
+                    height: calc(100% - 10px);
+                }
+            }
+            @media only screen and (max-width: 1680px) {
+                .year, .cycle, .back, .parse {
+                    height: 2.5rem;
+                    line-height: 2.5rem;
+                    margin-top: 2.5%;
+                }
+                .year {
+                    right: 82%;
+                }
+                .cycle {
+                    width: 5%;
+                    min-width: 120px;
+                    font-size: 18px;
+                    font-weight: normal;
+                }
+                .back {
+                    left: calc(75% + 60px);
+                }
+            }
+            @media only screen and (max-width: 1366px) {
+                .year {
+                    right: 80%;
+                }
+                .cycle {
+                    right: 70%;
+                    min-width: 140px;
+                    font-size: 16px;
+                    font-weight: normal;
+                }
+                .back {
+                    left: calc(75% + 50px);
+                }
+            }
+        }
+    }
+</style>

+ 25 - 0
src/views/business/labManagement/utils/config.js

@@ -0,0 +1,25 @@
+export const GetPercent = (num, total)=> {
+    /// <summary>
+    /// 求百分比
+    /// </summary>
+    /// <param name="num">当前数</param>
+    /// <param name="total">总数</param>
+    num = parseFloat(num);
+    total = parseFloat(total);
+    if (isNaN(num) || isNaN(total)) {
+        return "-";
+    }
+    return total <= 0 ? "0%" : (Math.round(num / total * 10000) / 100.00)+"%";
+}
+export const GetMax = (arr)=> {
+    let max = 1;
+    if(arr ==undefined)
+        return 1;
+
+    arr.forEach(v => {
+        if (max<v) {
+          max = v;
+        }
+      })
+   return max;
+}