Parcourir la source

质量指标看板修改

cfort il y a 2 ans
Parent
commit
5759b7cd95

BIN
src/assets/images/icons/parse.png


BIN
src/assets/images/icons/play.png


+ 1 - 1
src/store/modules/ibps/modules/user.js

@@ -185,7 +185,7 @@ export default {
         getDeptList ({ state, dispatch }, { first, second }) {
         getDeptList ({ state, dispatch }, { first, second }) {
             const params = second ? ` and (pe.path_ like '%${second}%' or pe.id_ = '${first}')` : first ? ` and pe.path_ like '%${first}%'` : ''
             const params = second ? ` and (pe.path_ like '%${second}%' or pe.id_ = '${first}')` : first ? ` and pe.path_ like '%${first}%'` : ''
             // const sql = `select id_ as positionId, name_ as positionName, path_ as path, depth_ as depth, sn_ as sn from ibps_party_entity where party_type_ = 'position'${params} order by depth_ asc, sn_ asc`
             // const sql = `select id_ as positionId, name_ as positionName, path_ as path, depth_ as depth, sn_ as sn from ibps_party_entity where party_type_ = 'position'${params} order by depth_ asc, sn_ asc`
-            const sql = `select pe.id_ as positionId, pe.name_ as positionName, pe.path_ as path, pe.depth_ as depth, pe.sn_ as sn, r.name_ as manager, r.id_ as managerId from ibps_party_entity as pe left join (select em.id_, em.positions_, em.name_ from ibps_party_employee as em left join ibps_party_user_role as ur on em.id_ = ur.user_id_ left join ibps_party_role as pr on pr.id_ = ur.role_id_ where role_alias_ in ('zhsfzr', 'syszr', 'zhglzzc')) as r on find_in_set(pe.id_, r.positions_) > 0 where pe.party_type_ = 'position'${params} order by pe.depth_ asc, pe.sn_ asc`
+            const sql = `select pe.id_ as positionId, pe.name_ as positionName, pe.path_ as path, pe.depth_ as depth, pe.sn_ as sn, ifnull(r.name_, '') as manager, ifnull(r.id_, '') as managerId from ibps_party_entity as pe left join (select em.id_, em.positions_, em.name_ from ibps_party_employee as em left join ibps_party_user_role as ur on em.id_ = ur.user_id_ left join ibps_party_role as pr on pr.id_ = ur.role_id_ where role_alias_ in ('zhsfzr', 'syszr', 'zhglzzc')) as r on find_in_set(pe.id_, r.positions_) > 0 where pe.party_type_ = 'position'${params} order by pe.depth_ asc, pe.sn_ asc`
             common.request('sql', sql).then(res => {
             common.request('sql', sql).then(res => {
                 const { data = [] } = res.variables || {}
                 const { data = [] } = res.variables || {}
                 dispatch('ibps/param/setDeptList', data, {
                 dispatch('ibps/param/setDeptList', data, {

+ 15 - 3
src/views/system/jbdHome/qualityTarget/components/container.vue

@@ -70,12 +70,24 @@ export default {
             setTimeout(() => {
             setTimeout(() => {
                 this.info.forEach((item, index) => {
                 this.info.forEach((item, index) => {
                     const chart = echarts.init(document.getElementById(`card${index}`))
                     const chart = echarts.init(document.getElementById(`card${index}`))
-                    const option = chartOption
-                    const xData = item.data.map((i, index) => index).slice(0, m)
+                    const option = JSON.parse(JSON.stringify(chartOption))
+                    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 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 limit = item.data.map(i => i.limit).filter(i => i !== undefined)[0]
                     const limitValue = item.data.map(i => i.limitValue).filter(i => i)[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
+                    // }
+                    // console.log(option.yAxis.max, option.yAxis.min, item.title)
 
 
+                    // console.log(item.title, yData)
                     option.title.text = item.title
                     option.title.text = item.title
                     option.title.textStyle.fontSize = this.fontSize
                     option.title.textStyle.fontSize = this.fontSize
                     option.title.subtext = `限值${limitValue}`
                     option.title.subtext = `限值${limitValue}`
@@ -85,7 +97,7 @@ export default {
                     option.series[0].markLine.data[0].label.formatter = limit
                     option.series[0].markLine.data[0].label.formatter = limit
                     chart.setOption(option)
                     chart.setOption(option)
                 })
                 })
-            }, 1)
+            }, 100)
         }
         }
     }
     }
 }
 }

+ 178 - 115
src/views/system/jbdHome/qualityTarget/index.vue

@@ -7,12 +7,25 @@
                 <dv-decoration-5 :class="$style.center" :dur="5" />
                 <dv-decoration-5 :class="$style.center" :dur="5" />
                 <dv-decoration-8 :class="$style.right" :reverse="true" />
                 <dv-decoration-8 :class="$style.right" :reverse="true" />
                 <div :class="$style.title">{{ title }}</div>
                 <div :class="$style.title">{{ title }}</div>
-                <dv-decoration-7 :class="$style.dept" :style="`font-size: ${fontSize}px;`">
-                    <span>{{ dept }}</span>
+                <dv-decoration-7 :class="$style.dept">
+                    <el-dropdown @command="changeDept">
+                        <span class="el-dropdown-link" :style="`font-size: ${fontSize}px;`">{{ selectedDept }}</span>
+                        <el-dropdown-menu slot="dropdown" class="dept-dropdown">
+                            <el-dropdown-item
+                                v-for="(item, index) in deptList"
+                                :key="item.positionId"
+                                :command="index"
+                            >{{ item.positionName }}</el-dropdown-item>
+                        </el-dropdown-menu>
+                    </el-dropdown>
                 </dv-decoration-7>
                 </dv-decoration-7>
                 <div :class="$style.back" @click.prevent="goBack()">
                 <div :class="$style.back" @click.prevent="goBack()">
                     <dv-border-box-8>返回</dv-border-box-8>
                     <dv-border-box-8>返回</dv-border-box-8>
                 </div>
                 </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>
             </div>
             <!-- 图表区域 -->
             <!-- 图表区域 -->
             <dv-border-box-1>
             <dv-border-box-1>
@@ -28,33 +41,34 @@ export default {
         container: () => import('./components/container.vue')
         container: () => import('./components/container.vue')
     },
     },
     data () {
     data () {
-        const d = new Date()
-        const special = ['综合', '样品', '科研', '医疗', '教学', '急诊']
-        const { deptList = [] } = this.$store.getters || {}
-        const deptFilter = deptList.filter(item => { return !special.some(i => item.positionName.includes(i)) && item.depth === 4 }).sort(i => i.sn)
-        console.log(deptFilter)
-        const { first = '', second = '' } = this.$store.getters.level || {}
         return {
         return {
-            // 过滤专业组
-            deptList: deptFilter,
-            dept: deptFilter[0].positionName,
-            // 记录部门下标,用于循环渲染
-            deptIndex: 0,
-            level: second || first,
+            deptList: [],
+            // selectedDept: '',
+            level: '',
             title: '质量指标统计',
             title: '质量指标统计',
-            year: d.toJSON().slice(0, 4),
-            month: d.toJSON().slice(0, 7),
-            today: d.toJSON().slice(0, 10),
+            year: '',
             initData: {},
             initData: {},
             renderData: [],
             renderData: [],
-            showIndex: 0,
             fontSize: 18,
             fontSize: 18,
-            timer: null,
-            changeTimer: null
+            deptIndex: 0,
+            chartIndex: 0,
+            dataFetchTimer: null,
+            autoPlayTimer: null,
+            autoPlay: true
+        }
+    },
+    computed: {
+        selectedDept () {
+            return this.deptList[this.deptIndex].positionName
+        }
+    },
+    watch: {
+        chartIndex (v) {
+            this.renderData = this.initData[this.selectedDept] ? this.initData[this.selectedDept].slice(v * 12, (v + 1) * 12) : []
         }
         }
     },
     },
-    // beforeRouteEnter(to, from, next){
-    //     Promise.all([  ]).done(([ res ]) => {
+    // beforeRouteEnter (to, from, next) {
+    //     Promise.all([]).done(([res]) => {
     //         console.log(res)
     //         console.log(res)
     //     }).then(err => {
     //     }).then(err => {
     //         window.observer.trigger('error', err)
     //         window.observer.trigger('error', err)
@@ -62,114 +76,137 @@ export default {
     //     })
     //     })
     // },
     // },
     created () {
     created () {
-        const w = window.innerWidth
-        this.fontSize = w >= 1600 ? 20 : w > 1366 && w < 1600 ? 18 : 16
-
+        // 默认全屏展示
         if (screenfull.isEnabled && !screenfull.isFullscreen) {
         if (screenfull.isEnabled && !screenfull.isFullscreen) {
-            this.allView()
+            screenfull.request()
         }
         }
 
 
-        this.updateAll()
-        this.setTimer()
+        this.initializeData()
+        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) : []
+        })
     },
     },
     beforeDestroy () {
     beforeDestroy () {
         if (screenfull.isFullscreen) {
         if (screenfull.isFullscreen) {
             screenfull.toggle()
             screenfull.toggle()
         }
         }
-        clearInterval(this.timer)
-        clearInterval(this.changeTimer)
+        this.clenUp()
     },
     },
     methods: {
     methods: {
-        allView () {
-            // 默认显示全屏
-            screenfull.request()
-        },
-        goBack () {
-            this.$router.back(-1)
-        },
-        updateAll () {
-            this.getData()
-        },
-        setTimer () {
-            // 每3分钟获取一次数据
-            if (this.timer) {
-                clearInterval(this.timer)
-            }
-            this.timer = setInterval(() => {
-                this.updateAll()
-            }, 30 * 1000)
+        initializeData () {
+            const w = window.innerWidth
+            const d = new Date()
+            const special = ['综合', '样品', '科研', '医疗', '教学', '急诊', 'test', '测试']
+            const { deptList = [] } = this.$store.getters || {}
+            const deptFilter = deptList.filter(item => { return !special.some(i => item.positionName.includes(i)) && item.depth === 4 }).sort(i => i.sn)
+            const { first = '', second = '' } = this.$store.getters.level || {}
 
 
-            // 每5秒切换一次显示数据
-            if (this.changeTimer) {
-                clearInterval(this.changeTimer)
-            }
-            this.changeTimer = setInterval(() => {
-                this.renderData = this.getRenderData(+!this.showIndex)
-            }, 2 * 1000)
+            this.deptList = deptFilter
+            this.dept = deptFilter[0].positionName
+            this.level = second || first
+            this.year = d.toJSON().slice(0, 4)
+            this.fontSize = w >= 1600 ? 20 : w > 1366 && w < 1600 ? 18 : 16
         },
         },
-        getData () {
+        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.create_time_ 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_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.create_time_ like '${this.year}%'`
-            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 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 = {
-                            title: target,
-                            data: new Array(12).fill({})
+            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] = []
                         }
                         }
-                        t.data[item.month - 1] = item
-                        this.initData[item.deptName].push(t)
-                    } else {
-                        this.initData[item.deptName][index].data[item.month - 1] = item
-                    }
+                        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 = {
+                                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
+                        }
+                    })
+                    console.log(this.initData)
+                    resolve()
+                }).catch(error => {
+                    reject(error)
                 })
                 })
-                // console.log(this.initData)
-                this.renderData = this.getRenderData(0, false)
-                console.log(this.renderData)
             })
             })
         },
         },
-        tranformData (v) {
-            if (!v) {
-                return v
+        startAutoPlay () {
+            this.autoPlay = true
+            if (this.autoPlayTimer) {
+                clearInterval(this.autoPlayTimer)
             }
             }
-            const t = this.deptList.find(i => i.positionId === v)
-            return t ? t.positionName : v
+            this.autoPlayTimer = setInterval(() => {
+                this.showNextData()
+            }, 3000)
         },
         },
-        // 获取图表渲染数据
-        getRenderData (index, flag = true) {
-            this.showIndex = index
-            // 每两次切换渲染数据时切换一次部门(重新请求接口获取数据时不做切换)
-            if (!this.showIndex && flag) {
-                this.loopDept()
-            }
-            const t = this.initData[this.dept] && this.initData[this.dept].length
-            if (t) {
-                return this.initData[this.dept].slice(index * 12, (index + 1) * 12)
-            }
-            return []
+        stopAutoPlay () {
+            this.autoPlay = false
+            clearInterval(this.autoPlayTimer)
         },
         },
-        loopDept () {
-            if (this.deptIndex < this.deptList.length - 1 && this.deptIndex > 0) {
+        showNextData () {
+            // console.log(this.chartIndex)
+            if (!this.autoPlay) {
+                return
+            }
+            if ((this.chartIndex + 1) * 12 < this.initData[this.selectedDept].length) {
+                this.chartIndex++
+            } else if (this.deptIndex < this.deptList.length - 1) {
                 this.deptIndex++
                 this.deptIndex++
-                this.dept = this.deptList[this.deptIndex].positionName
+                this.chartIndex = 0
             } else {
             } else {
                 this.deptIndex = 0
                 this.deptIndex = 0
-                this.dept = this.deptList[this.deptIndex].positionName
-                this.deptIndex++
+                this.chartIndex = 0
             }
             }
+        },
+        setupTimer () {
+            // 每3分钟获取一次数据
+            if (this.dataFetchTimer) {
+                clearInterval(this.dataFetchTimer)
+            }
+            this.dataFetchTimer = setInterval(() => {
+                this.fetchData()
+            }, 10 * 1000)
+        },
+        clenUp () {
+            clearInterval(this.dataFetchTimer)
+            clearInterval(this.autoPlayTimer)
+        },
+        changeDept (e) {
+            // 手动切换部门
+            this.stopAutoPlay()
+            // 更新当前指标
+            this.deptIndex = e
+            this.chartIndex = 0
+            this.startAutoPlay()
+        },
+        toggleAutoPlay () {
+            this.autoPlay ? this.stopAutoPlay() : this.startAutoPlay()
+        },
+        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
         }
         }
     }
     }
 }
 }
@@ -191,7 +228,7 @@ export default {
                 flex-direction: column;
                 flex-direction: column;
             }
             }
             .dv-border-box-1 .border-box-content{
             .dv-border-box-1 .border-box-content{
-                height: calc(100vh - 100px);
+                height: calc(100vh - 90px);
             }
             }
             .main-content {
             .main-content {
                 flex: 1;
                 flex: 1;
@@ -224,7 +261,7 @@ export default {
         .header {
         .header {
             position: relative;
             position: relative;
             width: 100%;
             width: 100%;
-            height: 100px;
+            height: 90px;
             display: flex;
             display: flex;
             justify-content: space-between;
             justify-content: space-between;
             flex-shrink: 0;
             flex-shrink: 0;
@@ -245,35 +282,61 @@ export default {
                 top: 15px;
                 top: 15px;
                 transform: translateX(-50%);
                 transform: translateX(-50%);
             }
             }
-            .dept, .back {
+            .dept, .back, .parse {
                 width: 8%;
                 width: 8%;
-                min-width: 120px;
                 cursor: pointer;
                 cursor: pointer;
                 height: 2.825rem;
                 height: 2.825rem;
                 line-height: 2.825rem;
                 line-height: 2.825rem;
                 text-align: center;
                 text-align: center;
-                margin-top: 2.5%;
+                margin-top: 2%;
                 flex: 1;
                 flex: 1;
                 position: absolute;
                 position: absolute;
                 color: #ffffff;
                 color: #ffffff;
             }
             }
             .dept {
             .dept {
                 display: flex;
                 display: flex;
+                min-width: 150px;
                 justify-content: flex-end;
                 justify-content: flex-end;
                 // width: 125px;
                 // width: 125px;
                 right: 75%;
                 right: 75%;
-                padding: 0 10px;
+                padding-left: 10px;
                 color: #fff;
                 color: #fff;
                 font-size: 22px;
                 font-size: 22px;
                 font-weight: 400;
                 font-weight: 400;
-                span {
-                    width: 120px;
-                    text-align: center;
+                :global {
+                    .el-dropdown {
+                        width: calc(100% - 52px);
+                        .el-dropdown-link {
+                            text-align: center;
+                        }
+                    }
                 }
                 }
             }
             }
             .back {
             .back {
+                width: 5%;
                 left: 75%;
                 left: 75%;
             }
             }
+            .parse {
+                width: 2%;
+                left: calc(80% + 40px);
+                align-items: center;
+                padding: 5px;
+                > img {
+                    height: calc(100% - 10px);
+                }
+            }
+            @media only screen and (max-width: 1680px){
+                .dept, .back, .parse {
+                    height: 2.5rem;
+                    line-height: 2.5rem;
+                    margin-top: 2.5%;
+                }
+            }
+            @media only screen and (max-width: 1366px){
+                .parse {
+                    left: calc(80% + 20px);
+                }
+            }
         }
         }
     }
     }
 </style>
 </style>