Răsfoiți Sursa

病理版质量指标总体看板

shenqilong 1 an în urmă
părinte
comite
6ff3380acc

+ 54 - 20
src/views/business/qualityTarget/components/monthChart.vue

@@ -22,6 +22,8 @@
 <script>
 <script>
 import * as echarts from 'echarts'
 import * as echarts from 'echarts'
 import { monthChartOption } from '../constants/option'
 import { monthChartOption } from '../constants/option'
+import { monthChartOptionbl } from '../constants/optionbl'
+
 export default {
 export default {
     name: 'chart',
     name: 'chart',
     components: {},
     components: {},
@@ -37,6 +39,10 @@ export default {
         chooseYear: {
         chooseYear: {
             type: String,
             type: String,
             default: ''
             default: ''
+        },
+        name: {
+            type: String,
+            default: () => ''
         }
         }
     },
     },
     data () {
     data () {
@@ -73,26 +79,54 @@ export default {
             this.fontSize = w >= 1600 ? 20 : w > 1366 && w < 1600 ? 18 : 16
             this.fontSize = w >= 1600 ? 20 : w > 1366 && w < 1600 ? 18 : 16
             setTimeout(() => {
             setTimeout(() => {
                 this.info.forEach((item, index) => {
                 this.info.forEach((item, index) => {
-                    const chart = echarts.init(document.getElementById(`card${index}`))
-                    const option = JSON.parse(JSON.stringify(monthChartOption))
-                    const xData = item.data.map((i, index) => `${index + 1}月`).slice(0, m)
-                    const yData = item.data.map(i => i.result || 0).slice(0, m)
-                    const yMax = Math.max(...yData)
-                    const yMin = Math.min(...yData)
-                    const limit = item.data.map(i => i.limitValue).filter(i => i !== undefined)[0]
-                    const limitValue = item.data.map(i => i.originalData).filter(i => i)[0]
-                    option.yAxis.max = Math.max(parseFloat(limit), parseFloat(yMax))
-                    // option.yAxis.min = Math.min(parseFloat(limit), parseFloat(yMin))
-                    // console.log(option.yAxis.max, option.yAxis.min, item.title)
-                    // console.log(item.title, yData)
-                    option.title.text = item.title
-                    option.title.textStyle.fontSize = this.fontSize
-                    option.title.subtext = `限值${limitValue.replace(/@/g, '')}`
-                    option.xAxis.data = xData
-                    option.series[0].data = yData
-                    option.series[0].markLine.data[0].yAxis = limit
-                    option.series[0].markLine.data[0].label.formatter = limit
-                    chart.setOption(option)
+                    console.log(item)
+                    if (this.name !== '病理') {
+                        const chart = echarts.init(document.getElementById(`card${index}`))
+                        const option = JSON.parse(JSON.stringify(monthChartOption))
+                        const xData = item.data.map((i, index) => `${index + 1}月`).slice(0, m)
+                        const yData = item.data.map(i => i.result || 0).slice(0, m)
+                        const yMax = Math.max(...yData)
+                        const yMin = Math.min(...yData)
+                        const limit = item.data.map(i => i.limitValue).filter(i => i !== undefined)[0]
+                        const limitValue = item.data.map(i => i.originalData).filter(i => i)[0]
+                        option.yAxis.max = Math.max(parseFloat(limit), parseFloat(yMax))
+                        // option.yAxis.min = Math.min(parseFloat(limit), parseFloat(yMin))
+                        // console.log(option.yAxis.max, option.yAxis.min, item.title)
+                        // console.log(item.title, yData)
+                        option.title.text = item.title
+                        option.title.textStyle.fontSize = this.fontSize
+                        option.title.subtext = `限值${limitValue.replace(/@/g, '')}`
+                        option.xAxis.data = xData
+                        option.series[0].data = yData
+                        option.series[0].markLine.data[0].yAxis = limit
+                        option.series[0].markLine.data[0].label.formatter = limit
+                        chart.setOption(option)
+                    } else {
+                        const chart = echarts.init(document.getElementById(`card${index}`))
+                        const option = JSON.parse(JSON.stringify(monthChartOptionbl))
+                        const xData = item.data.map((i, index) => `${index + 1}月`).slice(0, m)
+                        const yData = item.data.map(i => this.$utils.isEmpty(i.result) ? null : i.result)
+
+                        const limit = item.data.map(i => i.limitValue).filter(i => i !== undefined)[0]
+                        const limitValue = item.data.map(i => i.originalData).filter(i => i)[0]
+
+                        option.title.text = item.title
+                        option.title.textStyle.fontSize = this.fontSize
+                        option.title.subtext = `限值${limitValue.replace(/@/g, '')}`
+                        option.xAxis.data = xData
+                        option.series[0].data = yData
+
+                        option.series[0].name = item.title
+                        const lData = item.data.map(i => this.$utils.isEmpty(i.limitValue) ? null : i.limitValue)
+                        option.series[1].data = lData
+
+                        option.series[1].name = '达标标准率'
+                        option.legend.data = [item.title, '达标标准率']
+
+                        chart.setOption(option)
+                        console.log(option)
+                        chart.setOption(option)
+                    }
                 })
                 })
             }, 100)
             }, 100)
         }
         }

+ 55 - 18
src/views/business/qualityTarget/components/quarterChart.vue

@@ -22,6 +22,7 @@
 <script>
 <script>
 import * as echarts from 'echarts'
 import * as echarts from 'echarts'
 import { quarterChartOption } from '../constants/option'
 import { quarterChartOption } from '../constants/option'
+import { quarterChartOptionbl } from '../constants/optionbl'
 export default {
 export default {
     name: 'chart',
     name: 'chart',
     components: {},
     components: {},
@@ -37,6 +38,10 @@ export default {
         chooseYear: {
         chooseYear: {
             type: String,
             type: String,
             default: ''
             default: ''
+        },
+        name: {
+            type: String,
+            default: () => ''
         }
         }
     },
     },
     data () {
     data () {
@@ -70,24 +75,56 @@ export default {
             this.fontSize = w >= 1600 ? 20 : w > 1366 && w < 1600 ? 18 : 16
             this.fontSize = w >= 1600 ? 20 : w > 1366 && w < 1600 ? 18 : 16
             setTimeout(() => {
             setTimeout(() => {
                 this.info.forEach((item, index) => {
                 this.info.forEach((item, index) => {
-                    const chart = echarts.init(document.getElementById(`card${index}`))
-                    const option = JSON.parse(JSON.stringify(quarterChartOption))
-                    const xData = item.data.map((i, dIndex) => i.statisticalTime.replace('第', '\n第'))
-                    const yData = item.data.map(i => this.$utils.isEmpty(i.result) ? null : i.result)
-                    const yMax = Math.max(...yData)
-                    const yMin = Math.min(...yData)
-                    const limit = item.data.map(i => i.limitValue).filter(i => i !== undefined)[0]
-                    const limitValue = item.data.map(i => i.originalData).filter(i => i)[0]
-                    option.yAxis.max = Math.max(parseFloat(limit), parseFloat(yMax))
-                    // option.yAxis.min = Math.min(parseFloat(limit), parseFloat(yMin))
-                    option.title.text = item.title
-                    option.title.textStyle.fontSize = this.fontSize
-                    option.title.subtext = `限值${limitValue.replace(/@/g, '')}`
-                    option.xAxis.data = xData
-                    option.series[0].data = yData
-                    option.series[0].markLine.data[0].yAxis = limit
-                    option.series[0].markLine.data[0].label.formatter = limit
-                    chart.setOption(option)
+                    if (this.name !== '病理') {
+                        console.log(item)
+                        const chart = echarts.init(document.getElementById(`card${index}`))
+                        const option = JSON.parse(JSON.stringify(quarterChartOption))
+                        const xData = item.data.map((i, dIndex) => i.statisticalTime.replace('第', '\n第'))
+                        const yData = item.data.map(i => this.$utils.isEmpty(i.result) ? null : i.result)
+                        const yMax = Math.max(...yData)
+                        const yMin = Math.min(...yData)
+                        const limit = item.data.map(i => i.limitValue).filter(i => i !== undefined)[0]
+                        const limitValue = item.data.map(i => i.originalData).filter(i => i)[0]
+                        option.yAxis.max = Math.max(parseFloat(limit), parseFloat(yMax))
+                        // option.yAxis.min = Math.min(parseFloat(limit), parseFloat(yMin))
+                        option.title.text = item.title
+                        option.title.textStyle.fontSize = this.fontSize
+                        option.title.subtext = `限值${limitValue.replace(/@/g, '')}`
+                        option.xAxis.data = xData
+                        option.series[0].data = yData
+                        option.series[0].markLine.data[0].yAxis = limit
+                        option.series[0].markLine.data[0].label.formatter = limit
+                        chart.setOption(option)
+                    } else {
+                        console.log(item)
+
+                        const chart = echarts.init(document.getElementById(`card${index}`))
+                        const option = JSON.parse(JSON.stringify(quarterChartOptionbl))
+                        const xData = item.data.map((i, dIndex) => i.statisticalTime.replace('第', '\n第'))
+                        const yData = item.data.map(i => this.$utils.isEmpty(i.result) ? null : i.result)
+                        const limit = item.data.map(i => i.limitValue).filter(i => i !== undefined)[0]
+                        const limitValue = item.data.map(i => i.originalData).filter(i => i)[0]
+                        // option.yAxis.max = Math.max(parseFloat(limit), parseFloat(yMax))
+                        // option.yAxis.min = Math.min(parseFloat(limit), parseFloat(yMin))
+                        option.title.text = item.title
+                        option.title.textStyle.fontSize = this.fontSize
+                        option.title.subtext = `限值${limitValue.replace(/@/g, '')}`
+                        option.xAxis.data = xData
+                        console.log(yData)
+
+                        option.series[0].data = yData
+                        // option.series[0].data = [null, null, 70, 98, 100, 90, 90]
+                        option.series[0].name = item.title
+                        const lData = item.data.map(i => this.$utils.isEmpty(i.limitValue) ? null : i.limitValue)
+                        option.series[1].data = lData
+                        // option.series[1].data = [null, null, 90, 90, 100, 100, 90]
+                        option.series[1].name = '达标标准率'
+                        option.legend.data = [item.title, '达标标准率']
+                        // option.series[0].markLine.data[0].yAxis = limit
+                        // option.series[0].markLine.data[0].label.formatter = limit
+                        chart.setOption(option)
+                        console.log(option)
+                    }
                 })
                 })
             }, 100)
             }, 100)
         }
         }

+ 45 - 18
src/views/business/qualityTarget/components/yearChart.vue

@@ -22,6 +22,7 @@
 <script>
 <script>
 import * as echarts from 'echarts'
 import * as echarts from 'echarts'
 import { quarterChartOption } from '../constants/option'
 import { quarterChartOption } from '../constants/option'
+import { quarterChartOptionbl } from '../constants/optionbl'
 export default {
 export default {
     name: 'chart',
     name: 'chart',
     components: {},
     components: {},
@@ -37,6 +38,10 @@ export default {
         chooseYear: {
         chooseYear: {
             type: String,
             type: String,
             default: ''
             default: ''
+        },
+        name: {
+            type: String,
+            default: () => ''
         }
         }
     },
     },
     data () {
     data () {
@@ -70,24 +75,46 @@ export default {
             this.fontSize = w >= 1600 ? 20 : w > 1366 && w < 1600 ? 18 : 16
             this.fontSize = w >= 1600 ? 20 : w > 1366 && w < 1600 ? 18 : 16
             setTimeout(() => {
             setTimeout(() => {
                 this.info.forEach((item, index) => {
                 this.info.forEach((item, index) => {
-                    const chart = echarts.init(document.getElementById(`card${index}`))
-                    const option = JSON.parse(JSON.stringify(quarterChartOption))
-                    const xData = item.data.map((i, dIndex) => i.statisticalTime)
-                    const yData = item.data.map(i => this.$utils.isEmpty(i.result) ? null : i.result)
-                    const yMax = Math.max(...yData)
-                    const yMin = Math.min(...yData)
-                    const limit = item.data.map(i => i.limitValue).filter(i => i !== undefined)[0]
-                    const limitValue = item.data.map(i => i.originalData).filter(i => i)[0]
-                    option.yAxis.max = Math.max(parseFloat(limit), parseFloat(yMax))
-                    // option.yAxis.min = Math.min(parseFloat(limit), parseFloat(yMin))
-                    option.title.text = item.title
-                    option.title.textStyle.fontSize = this.fontSize
-                    option.title.subtext = `限值${limitValue.replace(/@/g, '')}`
-                    option.xAxis.data = xData
-                    option.series[0].data = yData
-                    option.series[0].markLine.data[0].yAxis = limit
-                    option.series[0].markLine.data[0].label.formatter = limit
-                    chart.setOption(option)
+                    if (this.name !== '病理') {
+                        const chart = echarts.init(document.getElementById(`card${index}`))
+                        const option = JSON.parse(JSON.stringify(quarterChartOption))
+                        const xData = item.data.map((i, dIndex) => i.statisticalTime)
+                        const yData = item.data.map(i => this.$utils.isEmpty(i.result) ? null : i.result)
+                        const yMax = Math.max(...yData)
+                        const yMin = Math.min(...yData)
+                        const limit = item.data.map(i => i.limitValue).filter(i => i !== undefined)[0]
+                        const limitValue = item.data.map(i => i.originalData).filter(i => i)[0]
+                        option.yAxis.max = Math.max(parseFloat(limit), parseFloat(yMax))
+                        // option.yAxis.min = Math.min(parseFloat(limit), parseFloat(yMin))
+                        option.title.text = item.title
+                        option.title.textStyle.fontSize = this.fontSize
+                        option.title.subtext = `限值${limitValue.replace(/@/g, '')}`
+                        option.xAxis.data = xData
+                        option.series[0].data = yData
+                        option.series[0].markLine.data[0].yAxis = limit
+                        option.series[0].markLine.data[0].label.formatter = limit
+                        chart.setOption(option)
+                    } else {
+                        const chart = echarts.init(document.getElementById(`card${index}`))
+                        const option = JSON.parse(JSON.stringify(quarterChartOptionbl))
+                        const xData = item.data.map((i, dIndex) => i.statisticalTime)
+                        const yData = item.data.map(i => this.$utils.isEmpty(i.result) ? null : i.result)
+                        const limitValue = item.data.map(i => i.originalData).filter(i => i)[0]
+
+                        option.title.text = item.title
+                        option.title.textStyle.fontSize = this.fontSize
+                        option.title.subtext = `限值${limitValue.replace(/@/g, '')}`
+                        option.xAxis.data = xData
+                        option.series[0].data = yData
+                        option.series[0].name = item.title
+                        const lData = item.data.map(i => this.$utils.isEmpty(i.limitValue) ? null : i.limitValue)
+                        option.series[1].data = lData
+
+                        option.series[1].name = '达标标准率'
+                        option.legend.data = [item.title, '达标标准率']
+
+                        chart.setOption(option)
+                    }
                 })
                 })
             }, 100)
             }, 100)
         }
         }

+ 309 - 0
src/views/business/qualityTarget/constants/optionbl.js

@@ -0,0 +1,309 @@
+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: '80px'
+    },
+    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'
+            }
+        }
+    }
+
+}
+
+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 monthChartOptionbl = {
+    ...basicChart,
+    series: [{
+        type: 'line',
+        symbol: 'circle',
+        name: '合格率',
+        data: [],
+        symbolSize: 8,
+        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 : ''
+            }
+        }
+    },
+    {
+        type: 'line',
+        symbol: 'circle',
+        name: '合格率',
+        symbolSize: 8,
+        data: [],
+        itemStyle: {
+            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                { offset: 0, color: '#ff4949' },
+                { offset: 0.5, color: '#ff4949' },
+                { offset: 1, color: '#ff4949' }
+            ]),
+            normal: {
+                color: '#ff4949',
+                lineStyle: {
+                    // color: '#ff4949',
+                    width: 3,
+                    type: 'dotted' // 'dotted' 点型虚线 'solid' 实线 'dashed' 线型虚线
+                }
+            }
+        },
+        emphasis: {
+            itemStyle: {
+                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                    { offset: 0, color: '#ff4949' },
+                    { offset: 0.7, color: '#ff4949' },
+                    { offset: 1, color: '#ff4949' }
+                ])
+            }
+        },
+        label: {
+            show: true,
+            position: 'bottom',
+            textStyle: {
+                color: '#ff4949',
+                fontSize: 14
+            },
+            formatter (params) {
+                return params.value ? params.value : ''
+            }
+        }
+    }],
+    tooltip: {
+        show: true,
+        trigger: 'axis',
+        formatter: '指标详情<br/>{b}:{c}'
+    },
+    legend: {
+        data: [],
+        y: 'bottom',
+        textStyle: {
+            color: '#fff',
+            fontSize: 14
+            // fontStyle: 'bold'
+        }
+    }
+}
+
+export const quarterChartOptionbl = {
+    ...basicChart,
+    series: [{
+        type: 'line',
+        symbol: 'circle',
+        name: '',
+        data: [],
+        symbolSize: 8,
+
+        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
+                // fontStyle: 'bold'
+            },
+            formatter (params) {
+                return params.value ? params.value : ''
+            }
+        }
+    },
+    {
+        type: 'line',
+        symbol: 'circle',
+        name: '',
+        data: [],
+        symbolSize: 8,
+
+        itemStyle: {
+            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                { offset: 0, color: '#ff4949' },
+                { offset: 0.5, color: '#ff4949' },
+                { offset: 1, color: '#ff4949' }
+            ]),
+
+            normal: {
+                color: '#ff4949',
+                lineStyle: {
+                    // color: '#ff4949',
+                    width: 3,
+                    type: 'dotted' // 'dotted' 点型虚线 'solid' 实线 'dashed' 线型虚线
+                }
+            }
+        },
+        emphasis: {
+            itemStyle: {
+                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                    { offset: 0, color: '#ff4949' },
+                    { offset: 0.7, color: '#ff4949' },
+                    { offset: 1, color: '#ff4949' }
+                ])
+            }
+        },
+        label: {
+            show: true,
+            position: 'bottom',
+            textStyle: {
+                color: '#ff4949',
+                fontSize: 14
+                // fontStyle: 'bold'
+
+            },
+            formatter (params) {
+                return params.value ? params.value : ''
+            }
+        }
+
+    }],
+    tooltip: {
+        show: true,
+        trigger: 'axis',
+        formatter: '指标详情<br/>{b}:{c}'
+    },
+    legend: {
+        data: [],
+        y: 'bottom',
+        textStyle: {
+            color: '#fff',
+            fontSize: 14
+            // fontStyle: 'bold'
+        }
+    }
+}
+

+ 434 - 0
src/views/business/qualityTarget/indexbl.vue

@@ -0,0 +1,434 @@
+<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>
+                <month-chart v-if="renderData.length && selectedCycle === '每月'" :info="renderData" :font-size="fontSize" :choose-year="year" :name="name" />
+                <quarter-chart v-if="renderData.length && selectedCycle === '每季度'" :info="renderData" :font-size="fontSize" :choose-year="year" :name="name" />
+                <year-chart v-if="renderData.length && selectedCycle === '每年'" :info="renderData" :font-size="fontSize" :choose-year="year" :name="name" />
+            </dv-border-box-1>
+        </dv-full-screen-container>
+    </div>
+</template>
+<script>
+import screenfull from 'screenfull'
+export default {
+    components: {
+        MonthChart: () => import('./components/monthChart.vue'),
+        QuarterChart: () => import('./components/quarterChart.vue'),
+        YearChart: () => import('./components/yearChart.vue')
+    },
+    data () {
+        const d = new Date()
+        return {
+            name: '病理',
+            level: '',
+            title: '质量指标统计',
+            year: d.toJSON().slice(0, 4),
+            cycleList: [],
+            sizeMap: {
+                '每月': 12,
+                '每季度': 4,
+                '每年': 4
+            },
+            // year: '2023',
+            initData: {},
+            renderData: [],
+            fontSize: 18,
+            itemIndex: 0,
+            chartIndex: 0,
+            dataFetchTimer: null,
+            autoPlayTimer: null,
+            autoPlay: true
+        }
+    },
+    computed: {
+        selectedCycle () {
+            return this.cycleList[this.itemIndex] || '每月'
+        },
+        size () {
+            return this.sizeMap[this.selectedCycle]
+        }
+    },
+    watch: {
+        chartIndex (v) {
+            this.renderData = this.initData[this.selectedCycle] ? this.initData[this.selectedCycle].slice(v * this.size, (v + 1) * this.size) : []
+        },
+        itemIndex (v) {
+            this.renderData = this.initData[this.selectedCycle] ? this.initData[this.selectedCycle].slice(this.chartIndex * this.size, (this.chartIndex + 1) * this.size) : []
+        }
+    },
+    // beforeRouteEnter (to, from, next) {
+    //     Promise.all([]).done(([res]) => {
+    //         console.log(res)
+    //     }).then(err => {
+    //         window.observer.trigger('error', err)
+    //         next()
+    //     })
+    // },
+    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
+        },
+        updateAll () {
+            this.initializeData()
+            this.fetchData().then(() => {
+                this.startAutoPlay()
+                this.setupTimer()
+                this.renderData = this.initData[this.selectedCycle] ? this.initData[this.selectedCycle].slice(this.chartIndex * this.size, (this.chartIndex + 1) * this.size) : []
+            })
+        },
+        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 where di_dian_ = '${this.level}' 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 => {
+                    const { data = [] } = res.variables || {}
+                    const dataMap = {
+                        '每月': new Array(12).fill({}),
+                        '每季度': this.generateQuarter(),
+                        '每年': this.generateYear()
+                    }
+                    // 组装数据
+                    const result = {}
+                    data.forEach((item, index) => {
+                        const { cycle, statisticalTime, target, result: targetValue, limitValue } = item
+                        if (!result[cycle]) {
+                            result[cycle] = []
+                        }
+                        let targetIndex = result[cycle].findIndex(i => i.title === target)
+                        if (targetIndex === -1) {
+                            result[cycle].push({
+                                title: target,
+                                data: dataMap[cycle].map(d => ({ ...d }))
+                            })
+                            targetIndex = result[cycle].length - 1
+                        }
+                        const dataIndex = cycle === '每月' ? parseInt(statisticalTime.split('年')[1].split('月')[0]) - 1 : result[cycle][targetIndex].data.findIndex(i => i.statisticalTime === statisticalTime)
+                        result[cycle][targetIndex].data[dataIndex] = { ...item, result: parseFloat(targetValue), limitValue: parseFloat(limitValue) }
+                    })
+                    this.initData = result
+                    this.cycleList = Object.keys(this.initData)
+                    console.log(this.initData)
+                    resolve()
+                }).catch(error => {
+                    reject(error)
+                })
+            })
+        },
+        generateQuarter () {
+            const result = []
+            const prevYear = this.year - 1
+            // 生成上一年的季度对象
+            for (let i = 1; i <= 4; i++) {
+                result.push({ statisticalTime: `${prevYear}年第${i}季度` })
+            }
+            // 生成当前年的季度对象
+            for (let i = 1; i <= 4; i++) {
+                result.push({ statisticalTime: `${this.year}年第${i}季度` })
+            }
+            return result
+        },
+        generateYear () {
+            const result = []
+            for (let year = this.year - 8; year < this.year; year++) {
+                result.push({ statisticalTime: `${year}年度` })
+            }
+            return result
+        },
+        startAutoPlay () {
+            this.autoPlay = true
+            if (this.autoPlayTimer) {
+                clearInterval(this.autoPlayTimer)
+            }
+            this.autoPlayTimer = setInterval(() => {
+                this.showNextData()
+            }, 5000)
+        },
+        stopAutoPlay () {
+            this.autoPlay = false
+            clearInterval(this.autoPlayTimer)
+        },
+        showNextData () {
+            // console.log(this.chartIndex)
+            if (!this.autoPlay) {
+                return
+            }
+            if (!this.initData[this.selectedCycle]) {
+                this.clenUp()
+                return
+            }
+            if ((this.chartIndex + 1) * this.size < this.initData[this.selectedCycle].length) {
+                this.chartIndex++
+            } else if (this.itemIndex < this.cycleList.length - 1) {
+                this.itemIndex++
+                this.chartIndex = 0
+            } else {
+                this.itemIndex = 0
+                this.chartIndex = 0
+            }
+        },
+        setupTimer () {
+            // 每3分钟获取一次数据
+            if (this.dataFetchTimer) {
+                clearInterval(this.dataFetchTimer)
+            }
+            this.dataFetchTimer = setInterval(() => {
+                this.fetchData()
+            }, 180 * 1000)
+        },
+        clenUp () {
+            clearInterval(this.dataFetchTimer)
+            clearInterval(this.autoPlayTimer)
+        },
+        changeCycle (e) {
+            // 手动切换
+            this.stopAutoPlay()
+            // 更新当前指标
+            this.itemIndex = e
+            this.chartIndex = 0
+            this.startAutoPlay()
+        },
+        toggleAutoPlay () {
+            this.autoPlay ? this.stopAutoPlay() : this.startAutoPlay()
+        },
+        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);
+          }
+          .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>