cfort 1 год назад
Родитель
Сommit
d46ba7844e

+ 287 - 0
src/views/business/qualityTarget/components/beforeInspect1.vue

@@ -0,0 +1,287 @@
+<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.statRange">
+                    <el-date-picker
+                        v-model="statRange"
+                        type="daterange"
+                        value-format="yyyy-MM-dd"
+                        format="yyyy-MM-dd"
+                        placeholder="统计日期"
+                        :readonly="false"
+                        :editable="true"
+                        :clearable="false"
+                        @change="updateAll"
+                    />
+                </dv-border-box-8>
+                <div :class="$style.back" @click.prevent="goBack()">
+                    <dv-border-box-8>返回</dv-border-box-8>
+                </div>
+            </div>
+            <!-- 图表区域 -->
+            <dv-border-box-1>
+                <chart-item1 :list="renderData" :range="statRange" :font-size="fontSize" />
+            </dv-border-box-1>
+        </dv-full-screen-container>
+    </div>
+</template>
+<script>
+import screenfull from 'screenfull'
+export default {
+    components: {
+        ChartItem1: () => import('./chartItem1.vue')
+    },
+    data () {
+        const now = this.$common.getDateNow()
+        const before = this.$common.getFormatDate('string', 10, this.$common.getDate('month', -1, now))
+        return {
+            level: '',
+            title: '检验科质量指标-检验前',
+            statRange: [before, now],
+            initData: {},
+            renderData: [1, 2],
+            fontSize: 18,
+            chartIndex: 0,
+            dataFetchTimer: null,
+            autoPlayTimer: null,
+            autoPlay: true
+        }
+    },
+    computed: {},
+    watch: {
+        chartIndex (v) {
+            this.renderData = [1, 2]
+        }
+    },
+    // 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.chartIndex = 0
+            this.level = second || first
+            this.fontSize = w >= 1600 ? 20 : w > 1366 && w < 1600 ? 18 : 16
+        },
+        updateAll (dateRange) {
+            this.initializeData()
+            this.fetchData(dateRange).then(() => {
+                this.startAutoPlay()
+                this.setupTimer()
+            })
+        },
+        async fetchData () {
+            console.log(123)
+        },
+        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)
+        },
+        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/stars.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%);
+            }
+            .statRange, .cycle, .back, .parse {
+                width: 8%;
+                max-width: 240px;
+                cursor: pointer;
+                height: 2.825rem;
+                line-height: 2.825rem;
+                text-align: center;
+                margin-top: 2%;
+                flex: 1;
+                position: absolute;
+                color: #ffffff;
+            }
+            .statRange {
+                width: 15%;
+                right: 75%;
+                display: flex;
+                justify-content: center;
+                align-items: center;
+                :global {
+                    .el-date-editor, .el-range-separator, .el-input__icon, .el-range-input {
+                        color: #fff;
+                    }
+                    .el-date-editor, .el-range-input {
+                        width: 100% !important;
+                        background: rgba(255, 255, 255, 0);
+                        border: none;
+                        color: #fff;
+                        font-size: 16px;
+                        cursor: pointer;
+                        // padding-left: 0;
+                        padding-right: 0;
+                    }
+                }
+            }
+            .back {
+                width: 5%;
+                left: 75%;
+            }
+            @media only screen and (max-width: 1680px) {
+                .statRange, .back {
+                    height: 2.5rem;
+                    line-height: 2.5rem;
+                    margin-top: 2.5%;
+                }
+                .statRange {
+                    right: 75%;
+                }
+                .back {
+                    left: 75%;
+                }
+            }
+            @media only screen and (max-width: 1366px) {
+                .statRange {
+                    right: 75%;
+                }
+                .back {
+                    left: 75%;
+                }
+            }
+        }
+    }
+</style>

+ 254 - 0
src/views/business/qualityTarget/components/beforeInspect2.vue

@@ -0,0 +1,254 @@
+<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.statRange">
+                    <el-date-picker
+                        v-model="statRange"
+                        type="daterange"
+                        value-format="yyyy-MM-dd"
+                        format="yyyy-MM-dd"
+                        placeholder="统计日期"
+                        :readonly="false"
+                        :editable="true"
+                        :clearable="false"
+                        @change="updateAll"
+                    />
+                </dv-border-box-8>
+                <div :class="$style.back" @click.prevent="goBack()">
+                    <dv-border-box-8>返回</dv-border-box-8>
+                </div>
+            </div>
+            <!-- 图表区域 -->
+            <dv-border-box-1>
+                <chart-item2 :list="renderData" :range="statRange" :font-size="fontSize" />
+            </dv-border-box-1>
+        </dv-full-screen-container>
+    </div>
+</template>
+<script>
+import screenfull from 'screenfull'
+export default {
+    components: {
+        ChartItem2: () => import('./chartItem2.vue')
+    },
+    data () {
+        const now = this.$common.getDateNow()
+        const before = this.$common.getFormatDate('string', 10, this.$common.getDate('month', -1, now))
+        return {
+            level: '',
+            title: '检验科质量指标-检验后',
+            statRange: [before, now],
+            initData: {},
+            renderData: [1, 2],
+            fontSize: 18,
+            chartIndex: 0,
+            dataFetchTimer: null,
+            autoPlayTimer: null,
+            autoPlay: true
+        }
+    },
+    computed: {},
+    watch: {
+        chartIndex (v) {
+            this.renderData = [1, 2]
+        }
+    },
+    // 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.chartIndex = 0
+            this.level = second || first
+            this.fontSize = w >= 1600 ? 20 : w > 1366 && w < 1600 ? 18 : 16
+        },
+        updateAll (dateRange) {
+            this.initializeData()
+            this.fetchData(dateRange).then(() => {
+                this.setupTimer()
+            })
+        },
+        async fetchData () {
+            console.log(123)
+        },
+        setupTimer () {
+            // 每3分钟获取一次数据
+            if (this.dataFetchTimer) {
+                clearInterval(this.dataFetchTimer)
+            }
+            this.dataFetchTimer = setInterval(() => {
+                this.fetchData()
+            }, 180 * 1000)
+        },
+        clenUp () {
+            clearInterval(this.dataFetchTimer)
+            clearInterval(this.autoPlayTimer)
+        },
+        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/stars.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%);
+            }
+            .statRange, .cycle, .back, .parse {
+                width: 8%;
+                max-width: 240px;
+                cursor: pointer;
+                height: 2.825rem;
+                line-height: 2.825rem;
+                text-align: center;
+                margin-top: 2%;
+                flex: 1;
+                position: absolute;
+                color: #ffffff;
+            }
+            .statRange {
+                width: 15%;
+                right: 75%;
+                display: flex;
+                justify-content: center;
+                align-items: center;
+                :global {
+                    .el-date-editor, .el-range-separator, .el-input__icon, .el-range-input {
+                        color: #fff;
+                    }
+                    .el-date-editor, .el-range-input {
+                        width: 100% !important;
+                        background: rgba(255, 255, 255, 0);
+                        border: none;
+                        color: #fff;
+                        font-size: 16px;
+                        cursor: pointer;
+                        // padding-left: 0;
+                        padding-right: 0;
+                    }
+                }
+            }
+            .back {
+                width: 5%;
+                left: 75%;
+            }
+            @media only screen and (max-width: 1680px) {
+                .statRange, .back {
+                    height: 2.5rem;
+                    line-height: 2.5rem;
+                    margin-top: 2.5%;
+                }
+                .statRange {
+                    right: 75%;
+                }
+                .back {
+                    left: 75%;
+                }
+            }
+            @media only screen and (max-width: 1366px) {
+                .statRange {
+                    right: 75%;
+                }
+                .back {
+                    left: 75%;
+                }
+            }
+        }
+    }
+</style>

+ 268 - 0
src/views/business/qualityTarget/components/chartItem1.vue

@@ -0,0 +1,268 @@
+<template>
+    <div :class="$style.box">
+        <div :class="$style.top">
+            <div
+                v-for="(item, index) in statData"
+                :key="index"
+                :class="$style.stat"
+            >
+                <div :class="$style.title">{{ item.title }}</div>
+                <div
+                    v-for="(v, i) in item.children"
+                    :key="i"
+                    :class="$style['stat-item']"
+                >
+                    <div :class="$style.label">{{ v.label }}</div>
+                    <div :class="$style.count">
+                        <dv-digital-flop
+                            :config="v.data"
+                            :class="$style.flop"
+                        />
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div :class="$style.chart">
+            <div
+                v-for="(item, index) in chartList"
+                :id="`chart${index}`"
+                :key="index"
+                :class="$style['chart-item']"
+            />
+        </div>
+    </div>
+</template>
+<script>
+import * as echarts from 'echarts'
+import { colors, getRandomColor, lineChartOption } from '../constants/option'
+export default {
+    components: {},
+    props: {
+        list: {
+            type: Array,
+            default: () => []
+        },
+        range: {
+            type: Array,
+            default: () => []
+        },
+        fontSize: {
+            type: Number,
+            default: 18
+        }
+    },
+    data () {
+        return {
+            stat: [
+                {
+                    title: '检验前周转时间中位数(min)',
+                    target: '≤60min',
+                    children: [
+                        {
+                            label: '本周',
+                            value: 34
+                        },
+                        {
+                            label: '本月',
+                            value: 30
+                        },
+                        {
+                            label: '本季度',
+                            value: 32
+                        }
+                    ]
+                },
+                {
+                    title: '检验前周转时间合格率(%)',
+                    target: '≥90%',
+                    children: [
+                        {
+                            label: '本周',
+                            value: 95
+                        },
+                        {
+                            label: '本月',
+                            value: 92
+                        },
+                        {
+                            label: '本季度',
+                            value: 96
+                        }
+                    ]
+                },
+                {
+                    title: '血污染培养率(%)',
+                    target: '≤1.5%',
+                    children: [
+                        {
+                            label: '本周',
+                            value: 1.23
+                        },
+                        {
+                            label: '本月',
+                            value: 1.2
+                        },
+                        {
+                            label: '本季度',
+                            value: 1.18
+                        }
+                    ]
+                }
+            ],
+            statData: [],
+            chartList: [
+                {
+                    limit: 60,
+                    limitValue: '≤60min',
+                    title: '检验前周转时间中位数(min)'
+                },
+                {
+                    limit: 90,
+                    limitValue: '≥90%',
+                    title: '检验前周转时间合格率(%)'
+                }
+            ]
+        }
+    },
+    computed: {},
+    watch: {
+        range: {
+            handler () {
+                this.init()
+            },
+            deep: true
+        }
+    },
+    mounted () {
+        this.init()
+    },
+    methods: {
+        init () {
+            const fontColor = [...colors].sort(() => Math.random() - 0.5)
+            const colorGenerator = getRandomColor(fontColor)
+            console.log(colorGenerator.next().value)
+            this.stat.forEach(item => {
+                item.children.forEach(i => {
+                    i.data = {
+                        number: [i.value],
+                        content: '{nt}',
+                        textAlign: 'right',
+                        style: {
+                            fill: colorGenerator.next().value,
+                            fontWeight: 'bold'
+                        }
+                    }
+                })
+            })
+            this.statData = JSON.parse(JSON.stringify(this.stat))
+            console.log(this.statData)
+            const D = new Date()
+            const w = window.innerWidth
+            this.fontSize = w >= 1600 ? 20 : w > 1366 && w < 1600 ? 18 : 16
+            setTimeout(() => {
+                this.chartList.forEach((item, index) => {
+                    const chart = echarts.init(document.getElementById(`chart${index}`))
+                    const option = JSON.parse(JSON.stringify(lineChartOption))
+                    const xData = this.getDatesInRange(this.range[0], this.range[1])
+                    const yData = Array.from({ length: xData.length }, () => Math.floor(Math.random() * 100) + 1)
+                    const yMax = Math.max(...yData)
+                    const yMin = Math.min(...yData)
+                    const limit = item.limit
+                    option.yAxis.max = Math.max(parseFloat(limit), parseFloat(yMax))
+                    option.title.text = item.title
+                    option.title.textStyle.fontSize = this.fontSize
+                    option.title.subtext = `限值${item.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)
+        },
+        getDatesInRange (startDate, endDate) {
+            const start = new Date(startDate)
+            const end = new Date(endDate)
+            const dates = []
+
+            for (let d = start; d <= end; d.setDate(d.getDate() + 1)) {
+                const month = (d.getMonth() + 1) + '月' // 月份从 0 开始
+                const day = d.getDate() + '日'
+                dates.push(month + day)
+            }
+            return dates
+        }
+    }
+}
+</script>
+<style lang="scss" module>
+    .box {
+        width: 96%;
+        height: calc(100% - 40px);
+        padding: 20px 2%;
+        :global {
+            .dv-decoration-10 {
+                width: 96%;
+                height: 5px;
+                margin: 15px 2%;
+            }
+            .dv-decoration-2 {
+                width:5px;
+                height:100%;
+            }
+        }
+        .top {
+            position: relative;
+            height: 150px;
+            margin: 20px 2%;
+            display: flex;
+            // flex-shrink: 0;
+            justify-content: space-between;
+            align-items: center;
+            background-color: rgba(6, 30, 93, 0.5);
+            .stat {
+                width: 33%;
+                height: 60%;
+                padding: 12px 20px;
+                border-left: 5px solid rgb(6, 30, 93);
+                .title {
+                    text-align: center;
+                    font-size: 24px;
+                    font-weight: bold;
+                    margin-bottom: 20px;
+                }
+                .stat-item {
+                    display: inline-block;
+                    width: 33%;
+                    .label{
+                        text-align: center;
+                        font-size: 16px;
+                    }
+                    .count {
+                        display: flex;
+                        align-items: center;
+                        justify-content: center;
+                        .flop {
+                            width: 60px;
+                            height: 40px;
+                            margin-left: -20px;
+                            font-size: 18px;
+                        }
+                        .unit {
+                            margin-left: 10px;
+                            box-sizing: border-box;
+                        }
+                    }
+                }
+            }
+        }
+        .chart {
+            height: calc((100% - 200px) / 2);
+            margin: 20px 2%;
+            .chart-item {
+                height: 100%;
+                width: 100%;
+            }
+        }
+    }
+</style>

+ 333 - 0
src/views/business/qualityTarget/components/chartItem2.vue

@@ -0,0 +1,333 @@
+<template>
+    <div :class="$style.box">
+        <div :class="$style.left">
+            <div
+                v-for="(item, index) in statData"
+                :key="index"
+                :class="$style.stat"
+            >
+                <div :class="$style.title">{{ item.title }}</div>
+                <div
+                    v-for="(v, i) in item.children"
+                    :key="i"
+                    :class="$style['stat-item']"
+                >
+                    <div :class="$style.label">{{ v.label }}</div>
+                    <div :class="$style.count">
+                        <dv-digital-flop
+                            :config="v.data"
+                            :class="$style.flop"
+                        />
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div :class="$style.chart">
+            <div
+                v-for="(item, index) in chartList"
+                :id="`chart${index}`"
+                :key="index"
+                :class="$style['chart-item']"
+            />
+        </div>
+    </div>
+</template>
+<script>
+import * as echarts from 'echarts'
+import { colors, getRandomColor, barChartOption } from '../constants/option'
+export default {
+    components: {},
+    props: {
+        list: {
+            type: Array,
+            default: () => []
+        },
+        range: {
+            type: Array,
+            default: () => []
+        },
+        fontSize: {
+            type: Number,
+            default: 18
+        }
+    },
+    data () {
+        return {
+            stat: [
+                {
+                    title: '急查血常规实验室内周转时间中位数(min)',
+                    target: '≤60min',
+                    children: [
+                        {
+                            label: '本周',
+                            value: 34
+                        },
+                        {
+                            label: '本月',
+                            value: 30
+                        },
+                        {
+                            label: '本季度',
+                            value: 32
+                        }
+                    ]
+                },
+                {
+                    title: '急查血常规实验室内TAT合格率(%)',
+                    target: '≥90%',
+                    children: [
+                        {
+                            label: '本周',
+                            value: 95
+                        },
+                        {
+                            label: '本月',
+                            value: 92
+                        },
+                        {
+                            label: '本季度',
+                            value: 96
+                        }
+                    ]
+                },
+                {
+                    title: '急查凝血实验室内周转时间中位数(min)',
+                    target: '≤60min',
+                    children: [
+                        {
+                            label: '本周',
+                            value: 34
+                        },
+                        {
+                            label: '本月',
+                            value: 30
+                        },
+                        {
+                            label: '本季度',
+                            value: 32
+                        }
+                    ]
+                },
+                {
+                    title: '急查凝血实验室内TAT合格率(%)',
+                    target: '≥90%',
+                    children: [
+                        {
+                            label: '本周',
+                            value: 95
+                        },
+                        {
+                            label: '本月',
+                            value: 92
+                        },
+                        {
+                            label: '本季度',
+                            value: 96
+                        }
+                    ]
+                },
+                {
+                    title: '急查生化免疫实验室内周转时间中位数(min)',
+                    target: '≤60min',
+                    children: [
+                        {
+                            label: '本周',
+                            value: 34
+                        },
+                        {
+                            label: '本月',
+                            value: 30
+                        },
+                        {
+                            label: '本季度',
+                            value: 32
+                        }
+                    ]
+                },
+                {
+                    title: '急查生化免疫实验室内TAT合格率(%)',
+                    target: '≥90%',
+                    children: [
+                        {
+                            label: '本周',
+                            value: 95
+                        },
+                        {
+                            label: '本月',
+                            value: 92
+                        },
+                        {
+                            label: '本季度',
+                            value: 96
+                        }
+                    ]
+                }
+            ],
+            statData: [],
+            chartList: [
+                {
+                    limit: 60,
+                    limitValue: '≤60min',
+                    title: '急查血常规'
+                },
+                {
+                    limit: 90,
+                    limitValue: '≥90%',
+                    title: '急查凝血'
+                },
+                {
+                    limit: 90,
+                    limitValue: '≥90%',
+                    title: '急查生化免疫'
+                }
+            ]
+        }
+    },
+    computed: {},
+    watch: {
+        range: {
+            handler () {
+                this.init()
+            },
+            deep: true
+        }
+    },
+    mounted () {
+        this.init()
+    },
+    methods: {
+        init () {
+            const fontColor = [...colors].sort(() => Math.random() - 0.5)
+            const colorGenerator = getRandomColor(fontColor)
+            console.log(colorGenerator.next().value)
+            this.stat.forEach(item => {
+                item.children.forEach(i => {
+                    i.data = {
+                        number: [i.value],
+                        content: '{nt}',
+                        textAlign: 'right',
+                        style: {
+                            fill: colorGenerator.next().value,
+                            fontWeight: 'bold'
+                        }
+                    }
+                })
+            })
+            this.statData = JSON.parse(JSON.stringify(this.stat))
+            console.log(this.statData)
+            const D = new Date()
+            const w = window.innerWidth
+            this.fontSize = w >= 1600 ? 20 : w > 1366 && w < 1600 ? 18 : 16
+            setTimeout(() => {
+                this.chartList.forEach((item, index) => {
+                    const chart = echarts.init(document.getElementById(`chart${index}`))
+                    const option = JSON.parse(JSON.stringify(barChartOption))
+                    const xData = this.getDatesInRange(this.range[0], this.range[1])
+                    const yData1 = Array.from({ length: xData.length }, () => Math.floor(Math.random() * 100) + 1)
+                    const yData2 = Array.from({ length: xData.length }, () => Math.floor(Math.random() * 100) + 1)
+                    const yMax = Math.max(...yData2)
+                    const yMin = Math.min(...yData2)
+                    const limit = item.limit
+                    option.yAxis.max = Math.max(parseFloat(limit), parseFloat(yMax))
+                    option.title.text = item.title
+                    option.title.textStyle.fontSize = this.fontSize
+                    option.title.subtext = `限值${item.limitValue.replace(/@/g, '')}`
+                    option.xAxis.data = xData
+                    option.series[0].data = yData1
+                    option.series[1].data = yData2
+                    option.series[1].markLine.data[0].yAxis = limit
+                    option.series[1].markLine.data[0].label.formatter = limit
+                    chart.setOption(option)
+                })
+            }, 100)
+        },
+        getDatesInRange (startDate, endDate) {
+            const start = new Date(startDate)
+            const end = new Date(endDate)
+            const dates = []
+
+            for (let d = start; d <= end; d.setDate(d.getDate() + 1)) {
+                const month = (d.getMonth() + 1) + '月' // 月份从 0 开始
+                const day = d.getDate() + '日'
+                dates.push(month + day)
+            }
+            return dates
+        }
+    }
+}
+</script>
+<style lang="scss" module>
+    .box {
+        width: 96%;
+        height: calc(100% - 40px);
+        padding: 20px 2%;
+        display: flex;
+        :global {
+            .dv-decoration-10 {
+                width: 96%;
+                height: 5px;
+                margin: 15px 2%;
+            }
+            .dv-decoration-2 {
+                width:5px;
+                height:100%;
+            }
+        }
+        .left {
+            position: relative;
+            width: calc(20% - 32px);
+            height: 100%;
+            display: flex;
+            // flex-shrink: 0;
+            flex-direction: column;
+            background-color: rgba(6, 30, 93, 0.4);
+            .stat {
+                flex: 1;
+                height: 16.35%;
+                padding: 0 16px;
+                border-bottom: 5px solid rgb(6, 30, 93);
+                &:last-child {
+                    border-bottom: none;
+                }
+                .title {
+                    text-align: center;
+                    font-size: 24px;
+                    font-weight: bold;
+                    margin: 16px 0;
+                }
+                .stat-item {
+                    display: inline-block;
+                    width: 33%;
+                    .label{
+                        text-align: center;
+                        font-size: 16px;
+                    }
+                    .count {
+                        display: flex;
+                        align-items: center;
+                        justify-content: center;
+                        .flop {
+                            width: 60px;
+                            height: 40px;
+                            margin-left: -20px;
+                            font-size: 18px;
+                        }
+                        .unit {
+                            margin-left: 10px;
+                            box-sizing: border-box;
+                        }
+                    }
+                }
+            }
+        }
+        .chart {
+            height: 100%;
+            flex: 1;
+            margin: 20px 1%;
+            .chart-item {
+                height: 33%;
+                width: 100%;
+            }
+        }
+    }
+</style>

+ 86 - 2
src/views/business/qualityTarget/constants/option.js

@@ -31,7 +31,7 @@ const basicChart = {
         subtext: '',
         textStyle: {
             color: '#fff',
-            fontSize: 18,
+            fontSize: 24,
             fontWeight: '600'
         },
         subtextStyle: {
@@ -86,7 +86,7 @@ const basicChart = {
     },
     series: [{
         type: 'line',
-        name: '',
+        name: '合格率',
         data: [],
         markLine: {
             data: [
@@ -142,6 +142,31 @@ const basicChart = {
     }
 }
 
+export const colors = [
+    '#d20962',
+    '#f47721',
+    '#7ac143',
+    '#00a78e',
+    '#00bce4',
+    '#7d3f98',
+    '#037ef3',
+    '#f85a40',
+    '#00c16e',
+    '#12CBC4',
+    '#b4a996',
+    '#7552cc',
+    '#67809f',
+    '#f19066'
+]
+
+export function* getRandomColor (shuffledColors) {
+    let index = 0
+    while (index < shuffledColors.length) {
+        yield shuffledColors[index]
+        index++
+    }
+}
+
 export const monthChartOption = basicChart
 
 export const quarterChartOption = {
@@ -263,3 +288,62 @@ export const yearChartOption = {
         formatter: '指标详情<br/>{b}年度:{c}'
     }
 }
+
+export const lineChartOption = {
+    ...basicChart,
+    grid: {
+        top: '80px',
+        bottom: '30px',
+        left: '30px',
+        right: '30px'
+    }
+}
+
+export const barChartOption = {
+    ...basicChart,
+    grid: {
+        top: '80px',
+        bottom: '30px',
+        left: '30px',
+        right: '30px'
+    },
+    series: [
+        {
+            type: 'bar',
+            name: '中位数',
+            data: [],
+            barMaxWidth: '35px',
+            barStyle: {
+                fill: 'rgba(0, 186, 255, 0.4)'
+            },
+            itemStyle: {
+                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                    { offset: 0, color: "#83bff6" },
+                    { offset: 0.5, color: "#188df0" },
+                    { offset: 1, color: "#188df0" },
+                ])
+            },
+            emphasis: {
+                itemStyle: {
+                    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                        { offset: 0, color: "#2378f7" },
+                        { offset: 0.7, color: "#2378f7" },
+                        { offset: 1, color: "#83bff6" },
+                    ])
+                }
+            },
+            label: {
+                show: true,
+                position: 'top',
+                textStyle: {
+                    color: '#fff',
+                    fontSize: 14
+                },
+                formatter (params) {
+                    return params.value ? params.value : ''
+                }
+            }
+        },
+        ...basicChart.series
+    ]
+}