瀏覽代碼

质量指标总体看板调整

cfort 1 年之前
父節點
當前提交
da7eb48ec5

+ 10 - 17
src/views/system/jbdHome/qualityTarget/components/container.vue → src/views/business/qualityTarget/components/monthChart.vue

@@ -21,7 +21,7 @@
 </template>
 <script>
 import * as echarts from 'echarts'
-import { chartOption } from './option'
+import { monthChartOption } from '../constants/option'
 export default {
     name: 'chart',
     components: {},
@@ -66,35 +66,28 @@ export default {
     methods: {
         init () {
             const D = new Date()
-            // 控制数据显示,历史数据显示整年,本年度数据显示到当前
+            // 控制数据显示,历史数据显示整年,本年度数据显示到上一个
             const y = parseInt(D.toJSON().slice(0, 4))
-            const m = parseInt(this.chooseYear) < y ? 12 : parseInt(D.toJSON().split('-')[1])
+            const m = parseInt(this.chooseYear) < y ? 12 : parseInt(D.toJSON().split('-')[1]) - 1
             const w = window.innerWidth
             this.fontSize = w >= 1600 ? 20 : w > 1366 && w < 1600 ? 18 : 16
             setTimeout(() => {
                 this.info.forEach((item, index) => {
                     const chart = echarts.init(document.getElementById(`card${index}`))
-                    const option = JSON.parse(JSON.stringify(chartOption))
-                    const xData = item.data.map((i, index) => index + 1).slice(0, m)
+                    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.limit).filter(i => i !== undefined)[0]
-                    const limitValue = item.data.map(i => i.limitValue).filter(i => i)[0]
-                    // if (parseFloat(limit) > parseFloat(yMax)) {
-                    //     // console.log('>', parseFloat(limit), parseFloat(yMax), item.title)
-                    //     option.yAxis.max = limit
-                    // }
-                    // if (parseFloat(limit) < parseFloat(yMin)) {
-                    //     // console.log('<', parseFloat(limit), parseFloat(yMax), item.title)
-                    //     option.yAxis.min = limit
-                    // }
+                    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}`
+                    option.title.subtext = `限值${limitValue.replace(/@/g, '')}`
                     option.xAxis.data = xData
                     option.series[0].data = yData
                     option.series[0].markLine.data[0].yAxis = limit

+ 131 - 0
src/views/business/qualityTarget/components/quarterChart.vue

@@ -0,0 +1,131 @@
+<template>
+    <div :class="$style.container">
+        <template v-for="(row, rowIndex) in rowData">
+            <dv-decoration-10 v-if="rowIndex === 1" :key="`lineOne${rowIndex}`" />
+            <div :key="`row${rowIndex}`" :class="$style.row" :style="`width: ${row.length / 2 * 100}%;`">
+                <template v-for="(item, index) in row">
+                    <div :key="`${rowIndex * 2 + index}`" :class="$style.column" :style="`width: ${1 / row.length * 100}%;`">
+                        <div :id="`card${rowIndex * 2 + index}`" />
+                    </div>
+                    <dv-decoration-2
+                        v-if="index !== row.length - 1"
+                        :key="`line${rowIndex * 2 + index}`"
+                        :reverse="true"
+                        :dur="2 + index * 2"
+                    />
+                </template>
+            </div>
+            <!-- <dv-decoration-10 v-if="rowIndex === 1" :key="`lineTwo${rowIndex}`" /> -->
+        </template>
+    </div>
+</template>
+<script>
+import * as echarts from 'echarts'
+import { quarterChartOption } from '../constants/option'
+export default {
+    name: 'chart',
+    components: {},
+    props: {
+        info: {
+            type: Array,
+            default: () => []
+        },
+        fontSize: {
+            type: Number,
+            default: 18
+        },
+        chooseYear: {
+            type: String,
+            default: ''
+        }
+    },
+    data () {
+        return {}
+    },
+    computed: {
+        rowData () {
+            const data = []
+            for (let i = 0; i < this.info.length; i += 2) {
+                data.push(this.info.slice(i, i + 2))
+            }
+            return data
+        }
+    },
+    watch: {
+        info: {
+            handler () {
+                this.init()
+            },
+            deep: true
+        }
+    },
+    created () {},
+    mounted () {
+        this.init()
+    },
+    methods: {
+        init () {
+            const D = new Date()
+            const w = window.innerWidth
+            this.fontSize = w >= 1600 ? 20 : w > 1366 && w < 1600 ? 18 : 16
+            setTimeout(() => {
+                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)
+                })
+            }, 100)
+        }
+    }
+}
+</script>
+<style lang="scss" module>
+    .container {
+        width: 96%;
+        height: calc(100% - 40px);
+        padding: 20px 2%;
+        .row {
+            position: relative;
+            display: flex;
+            justify-content: space-between;
+            width: 100%;
+            height: calc((100% - 40px) / 2);
+            // margin: 15px 0 15px;
+            .column {
+                width: 48%;
+                height: 100%;
+                background-color: rgba(6, 30, 93, 0.5);
+                > div {
+                    width: 100%;
+                    height: 100%;
+                }
+            }
+        }
+        :global {
+            .dv-decoration-10 {
+                width: 96%;
+                height: 5px;
+                margin: 15px 2%;
+            }
+            .dv-decoration-2 {
+                width:5px;
+                height:100%;
+            }
+        }
+    }
+</style>

+ 131 - 0
src/views/business/qualityTarget/components/yearChart.vue

@@ -0,0 +1,131 @@
+<template>
+    <div :class="$style.container">
+        <template v-for="(row, rowIndex) in rowData">
+            <dv-decoration-10 v-if="rowIndex === 1" :key="`lineOne${rowIndex}`" />
+            <div :key="`row${rowIndex}`" :class="$style.row" :style="`width: ${row.length / 2 * 100}%;`">
+                <template v-for="(item, index) in row">
+                    <div :key="`${rowIndex * 2 + index}`" :class="$style.column" :style="`width: ${1 / row.length * 100}%;`">
+                        <div :id="`card${rowIndex * 2 + index}`" />
+                    </div>
+                    <dv-decoration-2
+                        v-if="index !== row.length - 1"
+                        :key="`line${rowIndex * 2 + index}`"
+                        :reverse="true"
+                        :dur="2 + index * 2"
+                    />
+                </template>
+            </div>
+            <!-- <dv-decoration-10 v-if="rowIndex === 1" :key="`lineTwo${rowIndex}`" /> -->
+        </template>
+    </div>
+</template>
+<script>
+import * as echarts from 'echarts'
+import { quarterChartOption } from '../constants/option'
+export default {
+    name: 'chart',
+    components: {},
+    props: {
+        info: {
+            type: Array,
+            default: () => []
+        },
+        fontSize: {
+            type: Number,
+            default: 18
+        },
+        chooseYear: {
+            type: String,
+            default: ''
+        }
+    },
+    data () {
+        return {}
+    },
+    computed: {
+        rowData () {
+            const data = []
+            for (let i = 0; i < this.info.length; i += 2) {
+                data.push(this.info.slice(i, i + 2))
+            }
+            return data
+        }
+    },
+    watch: {
+        info: {
+            handler () {
+                this.init()
+            },
+            deep: true
+        }
+    },
+    created () {},
+    mounted () {
+        this.init()
+    },
+    methods: {
+        init () {
+            const D = new Date()
+            const w = window.innerWidth
+            this.fontSize = w >= 1600 ? 20 : w > 1366 && w < 1600 ? 18 : 16
+            setTimeout(() => {
+                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)
+                })
+            }, 100)
+        }
+    }
+}
+</script>
+<style lang="scss" module>
+    .container {
+        width: 96%;
+        height: calc(100% - 40px);
+        padding: 20px 2%;
+        .row {
+            position: relative;
+            display: flex;
+            justify-content: space-between;
+            width: 100%;
+            height: calc((100% - 40px) / 2);
+            // margin: 15px 0 15px;
+            .column {
+                width: 48%;
+                height: 100%;
+                background-color: rgba(6, 30, 93, 0.5);
+                > div {
+                    width: 100%;
+                    height: 100%;
+                }
+            }
+        }
+        :global {
+            .dv-decoration-10 {
+                width: 96%;
+                height: 5px;
+                margin: 15px 2%;
+            }
+            .dv-decoration-2 {
+                width:5px;
+                height:100%;
+            }
+        }
+    }
+</style>

+ 265 - 0
src/views/business/qualityTarget/constants/option.js

@@ -0,0 +1,265 @@
+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: 18,
+            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 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}'
+    }
+}

+ 88 - 66
src/views/system/jbdHome/qualityTarget/index.vue → src/views/business/qualityTarget/index.vue

@@ -21,15 +21,15 @@
                         @change="updateAll"
                     />
                 </dv-border-box-8>
-                <dv-decoration-7 :class="$style.dept">
-                    <el-dropdown @command="changeDept">
-                        <span class="el-dropdown-link" :style="`font-size: ${fontSize}px;`">{{ selectedDept }}</span>
+                <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 deptList"
-                                :key="item.positionId"
+                                v-for="(item, index) in cycleList"
+                                :key="index"
                                 :command="index"
-                            >{{ item.positionName }}</el-dropdown-item>
+                            >{{ item }}</el-dropdown-item>
                         </el-dropdown-menu>
                     </el-dropdown>
                 </dv-decoration-7>
@@ -43,7 +43,9 @@
             </div>
             <!-- 图表区域 -->
             <dv-border-box-1>
-                <container v-if="renderData.length" :info="renderData" :font-size="fontSize" :choose-year="year" />
+                <month-chart v-if="renderData.length && selectedCycle === '每月'" :info="renderData" :font-size="fontSize" :choose-year="year" />
+                <quarter-chart v-if="renderData.length && selectedCycle === '每季度'" :info="renderData" :font-size="fontSize" :choose-year="year" />
+                <year-chart v-if="renderData.length && selectedCycle === '每年'" :info="renderData" :font-size="fontSize" :choose-year="year" />
             </dv-border-box-1>
         </dv-full-screen-container>
     </div>
@@ -52,21 +54,27 @@
 import screenfull from 'screenfull'
 export default {
     components: {
-        container: () => import('./components/container.vue')
+        MonthChart: () => import('./components/monthChart.vue'),
+        QuarterChart: () => import('./components/quarterChart.vue'),
+        YearChart: () => import('./components/yearChart.vue')
     },
     data () {
         const d = new Date()
         return {
-            deptList: [],
-            // selectedDept: '',
             level: '',
             title: '质量指标统计',
             year: d.toJSON().slice(0, 4),
+            cycleList: [],
+            sizeMap: {
+                '每月': 12,
+                '每季度': 4,
+                '每年': 4
+            },
             // year: '2023',
             initData: {},
             renderData: [],
             fontSize: 18,
-            deptIndex: 0,
+            itemIndex: 0,
             chartIndex: 0,
             dataFetchTimer: null,
             autoPlayTimer: null,
@@ -74,13 +82,19 @@ export default {
         }
     },
     computed: {
-        selectedDept () {
-            return this.deptList[this.deptIndex].positionName
+        selectedCycle () {
+            return this.cycleList[this.itemIndex] || '每月'
+        },
+        size () {
+            return this.sizeMap[this.selectedCycle]
         }
     },
     watch: {
         chartIndex (v) {
-            this.renderData = this.initData[this.selectedDept] ? this.initData[this.selectedDept].slice(v * 12, (v + 1) * 12) : []
+            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) {
@@ -108,16 +122,10 @@ export default {
     methods: {
         initializeData () {
             const w = window.innerWidth
-            const special = ['综合', '样品', '科研', '医疗', '教学', '急诊', 'test', '测试']
-            const { deptList = [] } = this.$store.getters || {}
-            const poct = deptList.find(item => item.positionName.includes('poct') || item.positionName.includes('POCT') && item.depth === 3) || {}
-            const deptFilter = deptList.filter(item => { return !special.some(i => item.positionName.includes(i)) && item.depth === 4 && !item.path.includes(poct.positionId) }).sort(i => i.sn)
             const { first = '', second = '' } = this.$store.getters.level || {}
 
             this.initData = {}
-            this.deptList = deptFilter
-            this.dept = deptFilter[0].positionName
-            this.deptIndex = 0
+            this.itemIndex = 0
             this.chartIndex = 0
             this.level = second || first
             this.fontSize = w >= 1600 ? 20 : w > 1366 && w < 1600 ? 18 : 16
@@ -127,39 +135,40 @@ export default {
             this.fetchData().then(() => {
                 this.startAutoPlay()
                 this.setupTimer()
-                this.renderData = this.initData[this.selectedDept] ? this.initData[this.selectedDept].slice(this.chartIndex * 12, (this.chartIndex + 1) * 12) : []
+                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_yue_fen_ as months, 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 bian_zhi_bu_men_, tong_ji_yue_fen_, max(create_time_) as max from t_zlzbpjb group by bian_zhi_bu_men_, tong_ji_yue_fen_) a_latest on a.bian_zhi_bu_men_ = a_latest.bian_zhi_bu_men_ and 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_yue_fen_ like '${this.year}%'`
+            // 月度指标统计本年度,季度指标统计今年和去年,年度指标统计所有
+            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 => {
                     const { data = [] } = res.variables || {}
-                    data.forEach(item => {
-                        const { dept, months, target } = item
-                        item.deptName = this.tranformData(dept)
-                        item.month = parseInt(months.split('-')[1])
-                        // 截取指标限值
-                        item.limit = parseFloat(item.limitValue.match(/(\d+(\.\d+)?)/))
-                        // 创建组装后的数据结构
-                        if (!this.initData[item.deptName]) {
-                            this.initData[item.deptName] = []
+                    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] = []
                         }
-                        const index = this.initData[item.deptName].findIndex(i => i.title === target)
-                        // if (!this.initData[item.deptName][target]) {
-                        //     this.initData[item.deptName][target] = new Array(12).fill({})
-                        // }
-                        if (index === -1) {
-                            const t = {
+                        let targetIndex = result[cycle].findIndex(i => i.title === target)
+                        if (targetIndex === -1) {
+                            result[cycle].push({
                                 title: target,
-                                data: new Array(12).fill({})
-                            }
-                            t.data[item.month - 1] = item
-                            this.initData[item.deptName].push(t)
-                        } else {
-                            this.initData[item.deptName][index].data[item.month - 1] = item
+                                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 => {
@@ -167,6 +176,26 @@ export default {
                 })
             })
         },
+        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) {
@@ -174,7 +203,7 @@ export default {
             }
             this.autoPlayTimer = setInterval(() => {
                 this.showNextData()
-            }, 3000)
+            }, 5000)
         },
         stopAutoPlay () {
             this.autoPlay = false
@@ -185,17 +214,17 @@ export default {
             if (!this.autoPlay) {
                 return
             }
-            if (!this.initData[this.selectedDept]) {
+            if (!this.initData[this.selectedCycle]) {
                 this.clenUp()
                 return
             }
-            if ((this.chartIndex + 1) * 12 < this.initData[this.selectedDept].length) {
+            if ((this.chartIndex + 1) * this.size < this.initData[this.selectedCycle].length) {
                 this.chartIndex++
-            } else if (this.deptIndex < this.deptList.length - 1) {
-                this.deptIndex++
+            } else if (this.itemIndex < this.cycleList.length - 1) {
+                this.itemIndex++
                 this.chartIndex = 0
             } else {
-                this.deptIndex = 0
+                this.itemIndex = 0
                 this.chartIndex = 0
             }
         },
@@ -206,17 +235,17 @@ export default {
             }
             this.dataFetchTimer = setInterval(() => {
                 this.fetchData()
-            }, 10 * 1000)
+            }, 180 * 1000)
         },
         clenUp () {
             clearInterval(this.dataFetchTimer)
             clearInterval(this.autoPlayTimer)
         },
-        changeDept (e) {
-            // 手动切换部门
+        changeCycle (e) {
+            // 手动切换
             this.stopAutoPlay()
             // 更新当前指标
-            this.deptIndex = e
+            this.itemIndex = e
             this.chartIndex = 0
             this.startAutoPlay()
         },
@@ -225,13 +254,6 @@ export default {
         },
         goBack () {
             this.$router.back(-1)
-        },
-        tranformData (v) {
-            if (!v) {
-                return v
-            }
-            const t = this.deptList.find(i => i.positionId === v)
-            return t ? t.positionName : v
         }
     }
 }
@@ -307,7 +329,7 @@ export default {
                 top: 15px;
                 transform: translateX(-50%);
             }
-            .year, .dept, .back, .parse {
+            .year, .cycle, .back, .parse {
                 width: 8%;
                 max-width: 180px;
                 cursor: pointer;
@@ -338,7 +360,7 @@ export default {
                     }
                 }
             }
-            .dept {
+            .cycle {
                 display: flex;
                 min-width: 150px;
                 justify-content: flex-end;
@@ -374,7 +396,7 @@ export default {
                 }
             }
             @media only screen and (max-width: 1680px) {
-                .year, .dept, .back, .parse {
+                .year, .cycle, .back, .parse {
                     height: 2.5rem;
                     line-height: 2.5rem;
                     margin-top: 2.5%;
@@ -382,7 +404,7 @@ export default {
                 .year {
                     right: 82%;
                 }
-                .dept {
+                .cycle {
                     width: 5%;
                     min-width: 120px;
                     font-size: 18px;
@@ -396,7 +418,7 @@ export default {
                 .year {
                     right: 80%;
                 }
-                .dept {
+                .cycle {
                     right: 70%;
                     min-width: 140px;
                     font-size: 16px;

+ 0 - 116
src/views/system/jbdHome/qualityTarget/components/option.js

@@ -1,116 +0,0 @@
-import * as echarts from 'echarts'
-
-export const chartOption = {
-    title: {
-        show: true,
-        text: '',
-        subtext: '',
-        textStyle: {
-            color: '#fff',
-            fontSize: 18,
-            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'
-            }
-        },
-        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}'
-    }
-}