| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353 |
- import { computed, defineComponent, onBeforeUnmount, onMounted, reactive, ref } from 'vue'
- import styles from './index.module.less'
- import CircleProgress from './component/CircleProgress'
- import iconBackup from './image/icon-backup.png'
- import iconEnsemble from './image/icon-ensemble.png'
- import * as echarts from 'echarts'
- import { listenerMessage, postMessage, removeListenerMessage } from '@/helpers/native-message'
- type EChartsOption = echarts.EChartsOption
- interface ISubjectItem {
- /** 声部名称 */
- subjectName: string
- /**达标率 */
- practiceRate: number
- /** 达标人数 */
- passNum: number
- /** 未达标人数 */
- noPassNum: number
- /** 非会员 */
- noMemberNum: number
- }
- const symbolData: any = {
- type: 'line',
- symbol: 'circle',
- symbolSize: 6,
- triggerLineEvent: true,
- stack: 'Total'
- }
- export default defineComponent({
- name: 'subject-echarts',
- setup() {
- const activeData = reactive({
- index: -1,
- sum: {
- /**达标率 */
- practiceRate: 0,
- /**达标人数 */
- passNum: 0,
- /**未达标人数 */
- noPassNum: 0,
- /**未会员 */
- noMemberNum: 0
- },
- practiceThisWeeks: [] as ISubjectItem[],
- colors: [
- {
- color: '#FF8057',
- borderColor: 'rgba(255,128,87,0.5)',
- text: '达标率',
- select: true
- },
- {
- color: '#2FC58D',
- borderColor: 'rgba(47,197,141,0.5)',
- text: '达标',
- select: true
- },
- {
- color: '#4A99FF',
- borderColor: 'rgba(74,153,255,0.5)',
- text: '未达标',
- select: true
- },
- {
- color: '#9884BA',
- borderColor: 'rgba(152,132,186,0.5)',
- text: '非会员',
- select: true
- }
- ]
- })
- const subjects = computed(() => {
- return activeData.practiceThisWeeks.map((n) => n.subjectName)
- })
- let myChart: echarts.ECharts
- const handleInit = (data: any) => {
- const { content } = data
- if (!content) return
- if (myChart){
- myChart.clear()
- }
- activeData.sum = content.sum || {}
- activeData.practiceThisWeeks =
- content.practiceThisWeeks
- // .concat(
- // ...[
- // {
- // memberNum: 1,
- // noMemberNum: 10,
- // noPassNum: 12,
- // passNum: 30,
- // practiceRate: 20,
- // subjectName: '单簧管',
- // trainingNum: 0
- // },
- // {
- // memberNum: 1,
- // noMemberNum: 20,
- // noPassNum: 31,
- // passNum: 10,
- // practiceRate: 30,
- // subjectName: '萨克斯',
- // trainingNum: 0
- // },
- // {
- // memberNum: 1,
- // noMemberNum: 10,
- // noPassNum: 16,
- // passNum: 40,
- // practiceRate: 20,
- // subjectName: '小号',
- // trainingNum: 0
- // },
- // {
- // memberNum: 1,
- // noMemberNum: 10,
- // noPassNum: 16,
- // passNum: 40,
- // practiceRate: 20,
- // subjectName: '小号',
- // trainingNum: 0
- // }
- // ]
- // )
- || []
- const chartDom = document.getElementById('subjectEcharts')!
- myChart = echarts.init(chartDom)
- const option: EChartsOption = {
- tooltip: {
- trigger: 'axis',
- showContent: false,
- axisPointer: {
- type: 'line',
- lineStyle: {
- width: 40,
- opacity: 0.5,
- cap: 'square'
- }
- }
- },
- grid: {
- left: 5,
- top: 5,
- right: 5,
- bottom: 5,
- containLabel: true
- },
- legend: {
- type: 'scroll',
- right: 12,
- itemGap: 0,
- itemWidth: 2,
- itemStyle: {
- opacity: 0
- },
- lineStyle: {
- width: 0,
- opacity: 0
- },
- textStyle: {
- opacity: 0
- }
- },
- xAxis: {
- type: 'category',
- axisLabel: {
- interval: 0,
- color: '#333',
- fontSize: 9
- },
- axisTick: {
- show: false
- },
- boundaryGap: false,
- data: subjects.value
- },
- yAxis: [
- {
- type: 'value',
- position: 'left',
- axisLine: {
- show: true,
- lineStyle: {
- color: '#999'
- }
- },
- axisLabel: {
- formatter: '{value}'
- }
- },
- {
- type: 'value',
- position: 'right',
- axisLine: {
- show: true,
- lineStyle: {
- color: '#999'
- }
- },
- axisLabel: {
- formatter: '{value} %'
- }
- }
- ],
- series: ['practiceRate', 'passNum', 'noPassNum', 'noMemberNum'].map(
- (key: string, index: number) => {
- return {
- name: activeData.colors[index].text,
- color: activeData.colors[index].color,
- ...symbolData,
- yAxisIndex: index === 0 ? 1 : 0,
- data: activeData.practiceThisWeeks.map((n) => n[key])
- }
- }
- )
- }
- option && myChart.setOption(option)
- myChart.on('highlight', function (params: any) {
- console.log("🚀 ~ params:", params)
- activeData.index = params.batch[0].dataIndex
- })
- // console.log('🚀 ~ myChart:', myChart)
- }
- const handleAction = (index: number) => {
- activeData.index = index
- myChart?.dispatchAction({
- type: 'showTip',
- seriesIndex: 0,
- dataIndex: index
- })
- }
- const changeLegend = (item: any) => {
- myChart?.dispatchAction({
- type: item.select ? 'legendUnSelect' : 'legendSelect',
- // 图例名称
- name: item.text
- })
- item.select = !item.select
- }
- onMounted(() => {
- // handleInit({ content: { practiceThisWeeks: [], sum: {} } })
- listenerMessage('setAccomanyEcharts', handleInit)
- postMessage({
- api: 'setAccomanyEcharts'
- })
- })
- onBeforeUnmount(() => {
- removeListenerMessage('setAccomanyEcharts', handleInit)
- })
- return () => (
- <div class={styles.subjectEcharts}>
- <div class={[styles.container, styles.ensemble]}>
- <div class={styles.head}>
- <div class={styles.headLeft} onClick={() => handleInit({ content: { practiceThisWeeks: [], sum: {} } })}>
- <img class={styles.icon} src={iconEnsemble} />
- <div>总体情况</div>
- </div>
- </div>
- <div class={styles.content}>
- <CircleProgress
- value={activeData.sum.practiceRate}
- size={80}
- color="#FF8057"
- strokeWidth={6}
- duration={3000}
- />
- <div class={styles.items}>
- <div class={styles.item}>
- <div class={styles.itemNum}>
- <span class={styles.rect}></span>
- <span style={{ color: '#FF8057' }}>{activeData.sum.passNum}</span>
- </div>
- <div class={styles.itemTitle}>达标人数</div>
- </div>
- <div class={[styles.item, styles.line]}>
- <div class={styles.itemNum}>
- <span class={styles.rect} style={{ background: '#FFE7DF' }}></span>
- <span>{activeData.sum.noPassNum}</span>
- </div>
- <div class={styles.itemTitle}>未达标人数</div>
- </div>
- <div class={styles.item}>
- <div class={styles.itemNum}>
- <span>{activeData.sum.noMemberNum}</span>
- </div>
- <div class={styles.itemTitle}>非会员人数</div>
- </div>
- </div>
- </div>
- </div>
- <div class={[styles.container, styles.ensemble]}>
- <div class={styles.head}>
- <div class={styles.headLeft}>
- <img class={styles.icon} src={iconBackup} />
- <div>声部情况</div>
- </div>
- <div class={styles.headRight}>
- {activeData.colors.map((c) => (
- <div
- style={
- c.select
- ? { color: '#fff', borderColor: c.color, backgroundColor: c.color }
- : { color: c.color, borderColor: c.borderColor }
- }
- onClick={() => changeLegend(c)}
- >
- {c.text}
- </div>
- ))}
- </div>
- </div>
- <div id="subjectEcharts" class={styles.echartsMain}></div>
- {!activeData.practiceThisWeeks.length && <div class={styles.emtry}>暂无练习记录</div>}
- </div>
- <div class={[styles.container, styles.subjectWrap]}>
- {activeData.practiceThisWeeks.map((item, index: number) => (
- <div
- class={[styles.listItem, index === activeData.index ? styles.listItemActive : '']}
- onClick={() => handleAction(index)}
- >
- <div class={styles.dot}></div>
- <div class={styles.itemLeft}>
- <div class={styles.subjectName}>{item.subjectName}</div>
- <div class={styles.subjectType}>声部</div>
- </div>
- <div class={styles.listitems}>
- {activeData.colors.map((c, index: number) => {
- return (
- <div class={styles.item}>
- <div class={styles.itemNum}>
- <span style={{ color: c.color }}>{item.practiceRate}</span>
- </div>
- <div class={styles.itemTitle}>
- {c.text}
- {index === 0 ? '' : '人数'}
- </div>
- </div>
- )
- })}
- </div>
- </div>
- ))}
- </div>
- </div>
- )
- }
- })
|