ChartItem.vue 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. <template>
  2. <div class="cart-item">
  3. <slot name="title" />
  4. <v-chart :option="option" :init-options="{ height: 400 }" autoresize style="width: 100%; height: 100%" />
  5. <!-- <el-empty :image="emptyImg" v-show="!option.dataset.some((item) => item.source && item.source.length > 0)">
  6. <template v-slot:description>&nbsp;</template>
  7. </el-empty> -->
  8. </div>
  9. </template>
  10. <script lang="ts">
  11. import { Vue, Component, Prop, Watch } from 'vue-property-decorator'
  12. import { IStatisticsData } from '../api/common'
  13. import emptyImg from '@/assets/icon/null.png'
  14. import { IPointTarget } from '../../configuration/api/common'
  15. import moment from 'moment'
  16. @Component({ name: 'ChartItem' })
  17. export default class ChartItem extends Vue {
  18. @Prop({ type: String }) title!: string
  19. @Prop({ type: String }) itemKey!: keyof IStatisticsData['siteAndIndicateVo']
  20. @Prop({ type: Array, default: () => [] }) data!: IStatisticsData[]
  21. @Prop({ type: Array, default: () => [] }) standards!: IPointTarget['showVos']
  22. @Watch('data', { immediate: true })
  23. log(val) {
  24. this.count++
  25. console.log(this.count, this.itemKey, val, moment().format('YYYY-MM-DD HH:mm:ss'))
  26. }
  27. emptyImg = emptyImg
  28. count = 0
  29. getCodeName(code) {
  30. const { targetName } = this.standards.find((item) => item.targetCode === code) || {}
  31. return targetName || code
  32. }
  33. get option() {
  34. const dataset = this.data.map(({ checkCode, siteAndIndicateVo: { [this.itemKey]: items } }: IStatisticsData) => ({
  35. id: checkCode,
  36. source: items || []
  37. }))
  38. const series = this.data
  39. .map(({ checkCode }, index) => {
  40. return [
  41. { name: 'maxValue', displayName: '最大值' },
  42. { name: 'avgValue', displayName: '平均值' },
  43. { name: 'minValue', displayName: '最小值' }
  44. ].map((item, typeIndex) => {
  45. return {
  46. name: `${this.getCodeName(checkCode)}-${item.displayName}`,
  47. type: 'line',
  48. symbol: { '0': 'emptyCircle', '1': 'rect', '2': 'triangle' }[String(typeIndex)],
  49. smooth: true,
  50. dimensions: ['xposition', item],
  51. datasetIndex: index
  52. }
  53. })
  54. })
  55. .flat()
  56. return {
  57. tooltip: { trigger: 'axis', valueFormatter: (value) => Math.floor(Number(value) * 100) / 100 },
  58. calculable: true,
  59. xAxis: [
  60. {
  61. type: 'category',
  62. boundaryGap: false,
  63. data: [
  64. ...new Set(dataset.map((item) => item.source.map((item: { xposition: string }) => item.xposition)).flat())
  65. ].sort((a, b) => {
  66. const reg = /(?<=\d{4}年)(\d)(?=月)/
  67. const left = a.replace(reg, `0$1`)
  68. const right = b.replace(reg, `0$1`)
  69. return left.localeCompare(right)
  70. })
  71. }
  72. ],
  73. yAxis: [{ type: 'value', min: ({ min }) => min }],
  74. dataZoom: dataset.some(({ source }) => source.length > 100) && [
  75. { type: 'inside', start: 0, end: 100 },
  76. { start: 0, end: 100 }
  77. ],
  78. legend: { show: true, type: 'scroll', width: '80%' },
  79. grid: { top: 45, left: 0, right: 45, bottom: 30, containLabel: true },
  80. toolbox: {
  81. show: true,
  82. feature: { saveAsImage: { show: true } },
  83. right: 0
  84. },
  85. dataset,
  86. series
  87. }
  88. }
  89. }
  90. </script>
  91. <style lang="scss"></style>