|
@@ -1,77 +1,186 @@
|
|
|
-import { defineComponent, onMounted, ref } from 'vue'
|
|
|
+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 { postMessage } from '@/helpers/native-message'
|
|
|
+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 colors = [
|
|
|
- {
|
|
|
- color: '#FF8057',
|
|
|
- borderColor: 'rgba(255,128,87,0.5)',
|
|
|
- text: '达标率'
|
|
|
- },
|
|
|
- {
|
|
|
- color: '#2FC58D',
|
|
|
- borderColor: 'rgba(47,197,141,0.5)',
|
|
|
- text: '达标'
|
|
|
+ const activeData = reactive({
|
|
|
+ index: -1,
|
|
|
+ sum: {
|
|
|
+ /**达标率 */
|
|
|
+ practiceRate: 0,
|
|
|
+ /**达标人数 */
|
|
|
+ passNum: 0,
|
|
|
+ /**未达标人数 */
|
|
|
+ noPassNum: 0,
|
|
|
+ /**未会员 */
|
|
|
+ noMemberNum: 0
|
|
|
},
|
|
|
- {
|
|
|
- color: '#4A99FF',
|
|
|
- borderColor: 'rgba(74,153,255,0.5)',
|
|
|
- text: '未达标'
|
|
|
- },
|
|
|
- {
|
|
|
- color: '#9884BA',
|
|
|
- borderColor: 'rgba(152,132,186,0.5)',
|
|
|
- text: '非会员'
|
|
|
+ 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()
|
|
|
}
|
|
|
- ]
|
|
|
- const myChart = ref<echarts.ECharts>()
|
|
|
- const handleInit = () => {
|
|
|
- var chartDom = document.getElementById('subjectEcharts')!
|
|
|
- myChart.value = echarts.init(chartDom, undefined, {
|
|
|
- renderer: 'svg'
|
|
|
- })
|
|
|
- var option: EChartsOption
|
|
|
-
|
|
|
- option = {
|
|
|
+ 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',
|
|
|
- },
|
|
|
- dataset: {
|
|
|
- source: [['Email']]
|
|
|
+ axisPointer: {
|
|
|
+ type: 'line',
|
|
|
+ lineStyle: {
|
|
|
+ width: 40,
|
|
|
+ opacity: 0.5,
|
|
|
+ }
|
|
|
+ }
|
|
|
},
|
|
|
grid: {
|
|
|
- left: '3%',
|
|
|
- right: '3%',
|
|
|
- bottom: '3%',
|
|
|
+ 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: ['长笛', '单簧管', '萨克斯', '小号', '圆号', '上低音号', '打击乐'],
|
|
|
- axisPointer:{
|
|
|
- type: 'shadow'
|
|
|
- }
|
|
|
+ data: subjects.value
|
|
|
},
|
|
|
yAxis: [
|
|
|
{
|
|
|
type: 'value',
|
|
|
position: 'left',
|
|
|
- alignTicks: true,
|
|
|
axisLine: {
|
|
|
show: true,
|
|
|
lineStyle: {
|
|
|
- color: colors[2].color
|
|
|
+ color: '#999'
|
|
|
}
|
|
|
},
|
|
|
axisLabel: {
|
|
@@ -81,11 +190,10 @@ export default defineComponent({
|
|
|
{
|
|
|
type: 'value',
|
|
|
position: 'right',
|
|
|
- alignTicks: true,
|
|
|
axisLine: {
|
|
|
show: true,
|
|
|
lineStyle: {
|
|
|
- color: colors[0].color
|
|
|
+ color: '#999'
|
|
|
}
|
|
|
},
|
|
|
axisLabel: {
|
|
@@ -93,89 +201,87 @@ export default defineComponent({
|
|
|
}
|
|
|
}
|
|
|
],
|
|
|
- series: [
|
|
|
- {
|
|
|
- name: '达标率',
|
|
|
- type: 'line',
|
|
|
- data: [120, 132, 101, 134, 90, 230, 210]
|
|
|
- },
|
|
|
- {
|
|
|
- name: '达标',
|
|
|
- type: 'line',
|
|
|
- data: [150, 232, 201, 154, 190, 330, 410]
|
|
|
- },
|
|
|
- {
|
|
|
- name: '未达标',
|
|
|
- type: 'line',
|
|
|
- data: [320, 332, 301, 334, 390, 330, 320]
|
|
|
- },
|
|
|
- {
|
|
|
- name: '非会员',
|
|
|
- type: 'line',
|
|
|
- yAxisIndex: 1,
|
|
|
- data: [2.0, 2.2, 3.3, 4.5, 6.3, 10.2, 20.3, 23.4, 23.0, 16.5, 12.0, 6.2]
|
|
|
+ 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.value.setOption(option)
|
|
|
- console.log('🚀 ~ myChart:', myChart.value)
|
|
|
+ option && myChart.setOption(option)
|
|
|
+ myChart.on('highlight', function (params: any) {
|
|
|
+ activeData.index = params.batch[0].dataIndex
|
|
|
+ })
|
|
|
+ // console.log('🚀 ~ myChart:', myChart)
|
|
|
}
|
|
|
- const getThisWeek = async () => {
|
|
|
- postMessage(
|
|
|
- {
|
|
|
- api: 'setAccomanyEcharts'
|
|
|
- },
|
|
|
- (evt) => {
|
|
|
- console.log(evt?.content)
|
|
|
- }
|
|
|
- )
|
|
|
+ const handleAction = (index: number) => {
|
|
|
+ activeData.index = index
|
|
|
+ myChart?.dispatchAction({
|
|
|
+ type: 'showTip',
|
|
|
+ seriesIndex: 0,
|
|
|
+ dataIndex: index
|
|
|
+ })
|
|
|
}
|
|
|
- const action = () => {
|
|
|
- // myChart.value?.dispatchAction({
|
|
|
- // type: 'showTip',
|
|
|
- // name: '单簧管'
|
|
|
- // })
|
|
|
- myChart.value?.dispatchAction({
|
|
|
- type:'downplay',
|
|
|
- seriesIndex:[0,1],//两个图标同时展示
|
|
|
- dataIndex:0
|
|
|
- })
|
|
|
+ const changeLegend = (item: any) => {
|
|
|
+ myChart?.dispatchAction({
|
|
|
+ type: item.select ? 'legendUnSelect' : 'legendSelect',
|
|
|
+ // 图例名称
|
|
|
+ name: item.text
|
|
|
+ })
|
|
|
+ item.select = !item.select
|
|
|
}
|
|
|
onMounted(() => {
|
|
|
- getThisWeek()
|
|
|
- handleInit()
|
|
|
+ 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}>
|
|
|
+ <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={80} size={80} color="#FF8057" strokeWidth={6} duration={3000} />
|
|
|
+ <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' }}>348</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>348</span>
|
|
|
+ <span>{activeData.sum.noPassNum}</span>
|
|
|
</div>
|
|
|
<div class={styles.itemTitle}>未达标人数</div>
|
|
|
</div>
|
|
|
<div class={styles.item}>
|
|
|
<div class={styles.itemNum}>
|
|
|
- <span>348</span>
|
|
|
+ <span>{activeData.sum.noMemberNum}</span>
|
|
|
</div>
|
|
|
<div class={styles.itemTitle}>非会员人数</div>
|
|
|
</div>
|
|
@@ -190,13 +296,14 @@ export default defineComponent({
|
|
|
<div>声部情况</div>
|
|
|
</div>
|
|
|
<div class={styles.headRight}>
|
|
|
- {colors.map((c) => (
|
|
|
+ {activeData.colors.map((c) => (
|
|
|
<div
|
|
|
- style={{ color: c.color, borderColor: c.borderColor }}
|
|
|
- onClick={() => {
|
|
|
- console.log(myChart.value)
|
|
|
- action()
|
|
|
- }}
|
|
|
+ style={
|
|
|
+ c.select
|
|
|
+ ? { color: '#fff', borderColor: c.color, backgroundColor: c.color }
|
|
|
+ : { color: c.color, borderColor: c.borderColor }
|
|
|
+ }
|
|
|
+ onClick={() => changeLegend(c)}
|
|
|
>
|
|
|
{c.text}
|
|
|
</div>
|
|
@@ -205,41 +312,34 @@ export default defineComponent({
|
|
|
</div>
|
|
|
|
|
|
<div id="subjectEcharts" class={styles.echartsMain}></div>
|
|
|
+ {!activeData.practiceThisWeeks.length && <div class={styles.emtry}>暂无联系记录</div>}
|
|
|
</div>
|
|
|
|
|
|
<div class={[styles.container, styles.subjectWrap]}>
|
|
|
- {new Array(8).fill(1).map((item: any, index: number) => (
|
|
|
- <div class={[styles.listItem, index == 3 ? styles.listItemActive : '']}>
|
|
|
+ {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}>长笛</div>
|
|
|
+ <div class={styles.subjectName}>{item.subjectName}</div>
|
|
|
<div class={styles.subjectType}>声部</div>
|
|
|
</div>
|
|
|
<div class={styles.listitems}>
|
|
|
- <div class={styles.item}>
|
|
|
- <div class={styles.itemNum}>
|
|
|
- <span style={{ color: colors[0].color }}>348</span>
|
|
|
- </div>
|
|
|
- <div class={styles.itemTitle}>达标率</div>
|
|
|
- </div>
|
|
|
- <div class={styles.item}>
|
|
|
- <div class={styles.itemNum}>
|
|
|
- <span style={{ color: colors[1].color }}>348</span>
|
|
|
- </div>
|
|
|
- <div class={styles.itemTitle}>达标人数</div>
|
|
|
- </div>
|
|
|
- <div class={styles.item}>
|
|
|
- <div class={styles.itemNum}>
|
|
|
- <span style={{ color: colors[2].color }}>348</span>
|
|
|
- </div>
|
|
|
- <div class={styles.itemTitle}>未达标人数</div>
|
|
|
- </div>
|
|
|
- <div class={styles.item}>
|
|
|
- <div class={styles.itemNum}>
|
|
|
- <span style={{ color: colors[3].color }}>348</span>
|
|
|
- </div>
|
|
|
- <div class={styles.itemTitle}>非会员人数</div>
|
|
|
- </div>
|
|
|
+ {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>
|
|
|
))}
|