|  | @@ -0,0 +1,167 @@
 | 
	
		
			
				|  |  | +<template>
 | 
	
		
			
				|  |  | +  <div class="fx-row fx-bet-cen">
 | 
	
		
			
				|  |  | +    <div class="fx-1">
 | 
	
		
			
				|  |  | +      <mx-chart :options="chartOptions" :height="'450px'"></mx-chart>
 | 
	
		
			
				|  |  | +    </div>
 | 
	
		
			
				|  |  | +    <div>
 | 
	
		
			
				|  |  | +      <mx-chart></mx-chart>
 | 
	
		
			
				|  |  | +    </div>
 | 
	
		
			
				|  |  | +  </div>
 | 
	
		
			
				|  |  | +</template>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +<script>
 | 
	
		
			
				|  |  | +import MxChart from '@/components/MxChart/index'
 | 
	
		
			
				|  |  | +import config from '@/common/mx-config'
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +export default {
 | 
	
		
			
				|  |  | +  name: 'elective-generation-charts',
 | 
	
		
			
				|  |  | +  components: { MxChart },
 | 
	
		
			
				|  |  | +  props: ['chartBinding'],
 | 
	
		
			
				|  |  | +  computed: {
 | 
	
		
			
				|  |  | +    chartOptions() {
 | 
	
		
			
				|  |  | +      const options = this.chartBinding.generation.options
 | 
	
		
			
				|  |  | +      let data = this.chartBinding.chartData?.accumulates
 | 
	
		
			
				|  |  | +      let generation = this.chartBinding.chartData?.generation
 | 
	
		
			
				|  |  | +      let desc = '录取超缺数量'
 | 
	
		
			
				|  |  | +      if (this.chartBinding.generation.active == options.primary.value) {
 | 
	
		
			
				|  |  | +        generation = options.primary.value // force override primary chart data
 | 
	
		
			
				|  |  | +        data = this.chartBinding.generation.summary.find(item => item.generation == generation)?.categories
 | 
	
		
			
				|  |  | +        desc = '报名超缺数量'
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      if (!data?.length) return {}
 | 
	
		
			
				|  |  | +      const currentOpt = Object.values(options).find(opt => opt.value == generation)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      // xAxis data - round groups
 | 
	
		
			
				|  |  | +      const roundGroups = this.chartBinding.generation.roundGroups
 | 
	
		
			
				|  |  | +      const xAxis = roundGroups.map(rg => rg.groupName)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      // yAxis data
 | 
	
		
			
				|  |  | +      let series = []
 | 
	
		
			
				|  |  | +      if (generation == options.primary.value) {
 | 
	
		
			
				|  |  | +        // 初选报名需要单独处理
 | 
	
		
			
				|  |  | +        const multiplePreference = data.length > 1
 | 
	
		
			
				|  |  | +        const preferenceSeries = data.map((single, idx) => {
 | 
	
		
			
				|  |  | +          const prefix = multiplePreference ? `第${idx + 1}志愿/` : ''
 | 
	
		
			
				|  |  | +          const stackName = 'preference_' + idx
 | 
	
		
			
				|  |  | +          return this.barSeriesMissingAndOverFactory(
 | 
	
		
			
				|  |  | +            roundGroups,
 | 
	
		
			
				|  |  | +            rg => rg.expectedCount * 1,
 | 
	
		
			
				|  |  | +            rg => (single.find(item => item.category == 'actualCount')?.values
 | 
	
		
			
				|  |  | +              .find(item => item.groupId == rg.groupId)?.value || 0) * 1,
 | 
	
		
			
				|  |  | +            stackName,
 | 
	
		
			
				|  |  | +            [prefix + '报名人数', , prefix + '缺少人数', prefix + '超出人数']
 | 
	
		
			
				|  |  | +          )
 | 
	
		
			
				|  |  | +        })
 | 
	
		
			
				|  |  | +        series = preferenceSeries.reduce((prev, cur) => prev.concat(cur), [])
 | 
	
		
			
				|  |  | +      } else {
 | 
	
		
			
				|  |  | +        // 本来是创建3条线:基础线,缺少线,超出线,但图表的提示展示不方便
 | 
	
		
			
				|  |  | +        // 所以这里创建4条线:期望线,实际线,缺少线,超出线。(期望线,实际线保持相同颜色)
 | 
	
		
			
				|  |  | +        series = this.barSeriesMissingAndOverFactory(
 | 
	
		
			
				|  |  | +          roundGroups,
 | 
	
		
			
				|  |  | +          rg => rg.expectedCount * 1,
 | 
	
		
			
				|  |  | +          rg => {
 | 
	
		
			
				|  |  | +            const approvedCount = data.find(item => item.category == 'approvedCount')?.values
 | 
	
		
			
				|  |  | +              .find(item => item.groupId == rg.groupId)?.value || 0
 | 
	
		
			
				|  |  | +            const forcedCount = data.find(item => item.category == 'forcedCount')?.values
 | 
	
		
			
				|  |  | +              .find(item => item.groupId == rg.groupId)?.value || 0
 | 
	
		
			
				|  |  | +            const enrollCount = approvedCount * 1 + forcedCount * 1
 | 
	
		
			
				|  |  | +            return enrollCount
 | 
	
		
			
				|  |  | +          },
 | 
	
		
			
				|  |  | +          'Indicator',
 | 
	
		
			
				|  |  | +          []
 | 
	
		
			
				|  |  | +        )
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      return this.barOptionFactory('组合统计/' + currentOpt.title, desc, xAxis, series)
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  },
 | 
	
		
			
				|  |  | +  methods: {
 | 
	
		
			
				|  |  | +    barOptionFactory(title, subTitle, xAxis, series) {
 | 
	
		
			
				|  |  | +      return {
 | 
	
		
			
				|  |  | +        title: {
 | 
	
		
			
				|  |  | +          text: title,
 | 
	
		
			
				|  |  | +          subtext: subTitle,
 | 
	
		
			
				|  |  | +          left: 'center'
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  | +        xAxis: {
 | 
	
		
			
				|  |  | +          type: 'category',
 | 
	
		
			
				|  |  | +          data: xAxis
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  | +        yAxis: {
 | 
	
		
			
				|  |  | +          type: 'value'
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  | +        series: series,
 | 
	
		
			
				|  |  | +        tooltip: {
 | 
	
		
			
				|  |  | +          trigger: 'item'
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +    barSeriesMissingAndOverFactory(sourceArr, baseGetter, actualGetter, stackName, lineNames) {
 | 
	
		
			
				|  |  | +      // 本来是创建3条线:基础线,缺少线,超出线,但图表的提示展示不方便
 | 
	
		
			
				|  |  | +      // 所以这里创建4条线:期望线,实际线,缺少线,超出线。(期望线,实际线保持相同颜色)
 | 
	
		
			
				|  |  | +      const series = []
 | 
	
		
			
				|  |  | +      const commonDefines = {
 | 
	
		
			
				|  |  | +        type: 'bar',
 | 
	
		
			
				|  |  | +        stack: stackName,
 | 
	
		
			
				|  |  | +        emphasis: {
 | 
	
		
			
				|  |  | +          focus: 'series',
 | 
	
		
			
				|  |  | +          itemStyle: {
 | 
	
		
			
				|  |  | +            shadowBlur: 10,
 | 
	
		
			
				|  |  | +            shadowOffsetX: 0,
 | 
	
		
			
				|  |  | +            shadowColor: 'rgba(0, 0, 0, 0.5)'
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      const actualLine = {
 | 
	
		
			
				|  |  | +        ...commonDefines,
 | 
	
		
			
				|  |  | +        name: lineNames[0] || '录取人数',
 | 
	
		
			
				|  |  | +        data: []
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      const expectedLine = {
 | 
	
		
			
				|  |  | +        ...commonDefines,
 | 
	
		
			
				|  |  | +        name: lineNames[1] || '设置人数',
 | 
	
		
			
				|  |  | +        data: []
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      const missingLine = {
 | 
	
		
			
				|  |  | +        ...commonDefines,
 | 
	
		
			
				|  |  | +        name: lineNames[2] || '缺少人数',
 | 
	
		
			
				|  |  | +        data: []
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      const overLine = {
 | 
	
		
			
				|  |  | +        ...commonDefines,
 | 
	
		
			
				|  |  | +        name: lineNames[3] || '超出人数',
 | 
	
		
			
				|  |  | +        data: []
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      sourceArr.forEach(item => {
 | 
	
		
			
				|  |  | +        const settingCount = baseGetter(item)
 | 
	
		
			
				|  |  | +        const enrollCount = actualGetter(item)
 | 
	
		
			
				|  |  | +        if (settingCount <= 0 || settingCount == enrollCount) {
 | 
	
		
			
				|  |  | +          expectedLine.data.push(0)
 | 
	
		
			
				|  |  | +          actualLine.data.push({ value: enrollCount, itemStyle: { color: config.color.primary_report } })
 | 
	
		
			
				|  |  | +          missingLine.data.push(0)
 | 
	
		
			
				|  |  | +          overLine.data.push(0)
 | 
	
		
			
				|  |  | +        } else {
 | 
	
		
			
				|  |  | +          const subCount = Math.abs(settingCount - enrollCount)
 | 
	
		
			
				|  |  | +          const baseCount = Math.min(settingCount, enrollCount)
 | 
	
		
			
				|  |  | +          if (enrollCount > settingCount) {
 | 
	
		
			
				|  |  | +            expectedLine.data.push({ value: baseCount, itemStyle: { color: config.color.primary_report } })
 | 
	
		
			
				|  |  | +            actualLine.data.push(0)
 | 
	
		
			
				|  |  | +            missingLine.data.push(0)
 | 
	
		
			
				|  |  | +            overLine.data.push({ value: subCount, itemStyle: { color: config.color.error } })
 | 
	
		
			
				|  |  | +          } else {
 | 
	
		
			
				|  |  | +            expectedLine.data.push(0)
 | 
	
		
			
				|  |  | +            actualLine.data.push({ value: baseCount, itemStyle: { color: config.color.primary_report } })
 | 
	
		
			
				|  |  | +            missingLine.data.push({ value: subCount, itemStyle: { color: config.color.yellow_report } })
 | 
	
		
			
				|  |  | +            overLine.data.push(0)
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      })
 | 
	
		
			
				|  |  | +      series.push(actualLine, expectedLine, missingLine, overLine)
 | 
	
		
			
				|  |  | +      return series
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +</script>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +<style scoped>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +</style>
 |