| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484 |
- import {
- defineComponent,
- nextTick,
- onMounted,
- PropType,
- reactive,
- ref,
- shallowReactive,
- watch
- } from 'vue'
- import styles from './index.module.less'
- import icon1 from '../../images/icon1.png'
- import iconArrow from '../../images/icon-arrow.png'
- import iconArrow1 from '../../images/icon-arrow1.png'
- import iconArrow11 from '../../images/icon-arrow1-1.png'
- import * as echarts from 'echarts/core'
- import {
- LineChart
- // LineSeriesOption
- } from 'echarts/charts'
- // import { PieChart } from 'echarts/charts'
- import {
- TitleComponent,
- // 组件类型的定义后缀都为 ComponentOption
- // TitleComponentOption,
- TooltipComponent,
- // TooltipComponentOption,
- GridComponent,
- // 数据集组件
- DatasetComponent,
- // DatasetComponentOption,
- // 内置数据转换器组件 (filter, sort)
- // TransformComponent,
- LegendComponent,
- ToolboxComponent,
- DataZoomComponent
- } from 'echarts/components'
- import { LabelLayout } from 'echarts/features'
- import { CanvasRenderer } from 'echarts/renderers'
- import { Button, DatetimePicker, Popup, Toast } from 'vant'
- import { formatterDatePicker } from '@/helpers/utils'
- import dayjs from 'dayjs'
- import { getTimeRange, TIME_TYPE } from '../../home-statistics'
- // 注册必须的组件
- echarts.use([
- TitleComponent,
- TooltipComponent,
- GridComponent,
- DatasetComponent,
- // TransformComponent,
- LabelLayout,
- // UniversalTransition,
- CanvasRenderer,
- // PieChart,
- ToolboxComponent,
- LegendComponent,
- DataZoomComponent,
- LineChart
- ])
- const lineChartOption = (xAxisData: any, seriesData: any) => {
- return {
- title: {
- text: '单位:次',
- textStyle: {
- color: '#777777',
- fontSize: 13,
- fontWeight: 400
- }
- },
- legend: { show: false },
- emphasis: { lineStyle: { width: 2 } },
- xAxis: {
- boundaryGap: false,
- data: xAxisData,
- type: 'category',
- axisLine: { lineStyle: { color: '#8C8C8C' } },
- lineStyle: { color: '#F2F2F2' }
- },
- color: [
- '#2DC7AA',
- '#FF6079'
- // '#2DC7AA',
- // '#FF602C',
- // '#91DD1C',
- // '#FFA92C',
- // '#BE7E2E',
- // '#1C96DD',
- // '#D22CFF',
- // '#FF3C3C',
- // '#1AEE3E',
- // '#00c9ff'
- ],
- series: [
- {
- lineStyle: { width: 1 },
- data: seriesData[0],
- symbol: 'circle',
- name: '浏览次数',
- type: 'line',
- emphasis: { lineStyle: { width: 1 } }
- },
- {
- lineStyle: { width: 1 },
- data: seriesData[1],
- symbol: 'circle',
- name: '购买次数',
- type: 'line',
- areaStyle: {
- color: {
- type: 'linear',
- x: 0,
- y: 0,
- x2: 0,
- y2: 1,
- colorStops: [
- {
- offset: 0,
- color: 'rgba(255, 96, 121, 0.23)'
- // 0% 处的颜色
- },
- {
- offset: 1,
- // 100% 处的颜色
- color: 'rgba(255, 96, 121, 0)'
- }
- ]
- }
- },
- emphasis: { lineStyle: { width: 1 } }
- }
- ],
- grid: {
- bottom: '3%',
- containLabel: true,
- left: '3%',
- right: '5%',
- top: '40'
- },
- tooltip: {
- trigger: 'axis',
- confine: true,
- formatter: function (params: any) {
- return params[0].name
- },
- backgroundColor: '#FF6079',
- borderWidth: 0,
- borderRadius: 24,
- padding: [1, 4],
- textStyle: {
- color: '#FFFFFF',
- fontSize: 12
- }
- },
- yAxis: {
- type: 'value',
- splitLine: {
- axisLine: { lineStyle: { color: '#8C8C8C' } },
- lineStyle: { color: ['#f2f2f2'], type: 'dashed' }
- }
- },
- dataZoom: [{ type: 'inside', throttle: 100 }],
- toolbox: { feature: { saveAsImage: { show: false } } }
- }
- }
- export default defineComponent({
- name: 'eChats-model',
- props: {
- obj: {
- type: Object,
- default: () => ({})
- },
- currentType: {
- type: String as PropType<TIME_TYPE>,
- default: 'MONTH'
- }
- },
- emits: ['confirm'],
- setup(props, { emit }) {
- const chartId = 'eChart' + Date.now()
- const statisticCounts = ref({
- browseCount: 0,
- buyCount: 0
- })
- const currentType = ref<TIME_TYPE>(props.currentType)
- const timeRange = getTimeRange(currentType.value)
- const searchStatus = ref(false)
- const forms = reactive({
- loading: false,
- dataShow: true,
- subjectId: '' as any, // 选择的声部
- subjectList: [] as any,
- startTimeStatus: false,
- endTimeMinDate: new Date(),
- endTimeMaxDate: dayjs(new Date()).add(1, 'year').toDate(),
- endTimeStatus: false,
- startTime: new Date(timeRange?.startTime || ''),
- startTimeStr: timeRange?.startTime || '',
- endTime: new Date(timeRange?.endTime || ''),
- endTimeStr: timeRange?.endTime || ''
- })
- const showTimeRange = shallowReactive({
- startTime: timeRange?.startTime || '',
- endTime: timeRange?.endTime || ''
- })
- let myChart: echarts.ECharts
- const _initData = () => {
- nextTick(() => {
- statisticCounts.value.browseCount = props.obj.browseCount || 0
- statisticCounts.value.buyCount = props.obj.buyCount || 0
- myChart.clear()
- lineChartOption &&
- myChart.setOption(
- lineChartOption(props.obj.xAxisData, props.obj.yAxisData)
- )
- myChart.on('highlight', function (params: any) {
- const batch = params.batch || []
- const options: any = myChart.getOption()
- batch.forEach((item: any) => {
- const batchIndex = item.dataIndex
- const browseCount = options.series[0].data[batchIndex]
- const buyCount = options.series[1].data[batchIndex]
- statisticCounts.value = {
- browseCount,
- buyCount
- }
- })
- })
- })
- }
- nextTick(() => {
- myChart = echarts.init(document.getElementById(chartId) as HTMLDivElement)
- _initData()
- })
- watch(
- () => props.obj,
- () => {
- _initData()
- },
- {
- deep: true
- }
- )
- watch(
- () => props.currentType,
- () => {
- currentType.value = props.currentType
- }
- )
- const onChangeTime = (type: TIME_TYPE) => {
- if (currentType.value === type) return
- currentType.value = type
- resetTime(type)
- // emit('confirm', currentType.value)
- }
- // 格式化
- const resetTime = (type: TIME_TYPE) => {
- const timeRang = getTimeRange(type)
- forms.startTime = new Date(timeRang?.startTime || '')
- forms.startTimeStr = timeRang?.startTime || ''
- forms.endTimeMinDate = dayjs(timeRang?.startTime || '').toDate()
- forms.endTimeMaxDate = dayjs(timeRang?.startTime || '')
- .add(1, 'year')
- .toDate()
- forms.endTime = new Date(timeRang?.endTime || '')
- forms.endTimeStr = timeRang?.endTime || ''
- }
- return () => (
- <div class={styles.eChartSection}>
- <div class={styles.homeHead}>
- <div class={styles.title}>
- <img src={icon1} />
- <span>浏览/购买</span>
- </div>
- <div class={styles.right}>
- <div
- class={[
- styles.showItem,
- searchStatus.value && styles.showItemActive
- ]}
- onClick={() => (searchStatus.value = true)}
- >
- <span>
- {showTimeRange.startTime}~{showTimeRange.endTime}
- </span>
- <img src={searchStatus.value ? iconArrow11 : iconArrow1} />
- </div>
- </div>
- </div>
- <div class={styles.eChartTitle}>
- <div class={styles.left}>
- <div class={styles.item} style="--color: #2DC7AA">
- <span class={styles.line}></span>
- <span class={styles.text}>浏览次数</span>
- <span class={styles.num}>
- {statisticCounts.value.browseCount}次
- </span>
- </div>
- <div class={styles.item} style="--color: #FF6079">
- <span class={styles.line}></span>
- <span class={styles.text}>购买次数</span>
- <span class={styles.num}>{statisticCounts.value.buyCount}次</span>
- </div>
- </div>
- </div>
- <div class={styles.eChart}>
- <div id={chartId} style="width: 100%; height: 100%;"></div>
- </div>
- <Popup
- v-model:show={searchStatus.value}
- closeable
- round
- position="bottom"
- teleport="body"
- >
- <div class={styles.popupContainer}>
- <div class={styles.popupTitle}>筛选</div>
- <div class={styles.popupSearchList}>
- <div class={styles.popupSection}>
- <div class={styles.title}>
- <span>时间</span>
- </div>
- <div class={styles.timeCount}>
- <p
- onClick={() => onChangeTime('MONTH')}
- class={currentType.value === 'MONTH' ? styles.active : ''}
- >
- 本月
- </p>
- <p
- onClick={() => onChangeTime('THREE_MONTH')}
- class={
- currentType.value === 'THREE_MONTH' ? styles.active : ''
- }
- >
- 近三个月
- </p>
- <p
- onClick={() => onChangeTime('HALF_YEAR')}
- class={
- currentType.value === 'HALF_YEAR' ? styles.active : ''
- }
- >
- 近半年
- </p>
- <p
- onClick={() => onChangeTime('YEAR')}
- class={currentType.value === 'YEAR' ? styles.active : ''}
- >
- 近一年
- </p>
- </div>
- <div class={styles.timeRang}>
- <p
- class={[
- styles.timeInput,
- forms.startTimeStr && styles.hasValue
- ]}
- onClick={() => (forms.startTimeStatus = true)}
- >
- {forms.startTimeStr || '起始时间'}
- </p>
- <p class={styles.timeUnit}></p>
- <p
- class={[
- styles.timeInput,
- forms.endTimeStr && styles.hasValue
- ]}
- onClick={() => (forms.endTimeStatus = true)}
- >
- {forms.endTimeStr || '终止时间'}
- </p>
- </div>
- </div>
- </div>
- <div class={styles.popupBottom}>
- <Button
- round
- block
- type="default"
- onClick={() => {
- currentType.value = props.currentType
- resetTime(props.currentType)
- }}
- >
- 重置
- </Button>
- <Button
- round
- block
- type="primary"
- onClick={() => {
- if(!forms.startTimeStr || !forms.endTimeStr) {
- Toast('请选择时间范围')
- return
- }
- emit('confirm', {
- startTime: forms.startTimeStr,
- endTime: forms.endTimeStr
- })
- // 显示的时间
- showTimeRange.startTime = forms.startTimeStr
- showTimeRange.endTime = forms.endTimeStr
- searchStatus.value = false
- }}
- >
- 确定
- </Button>
- </div>
- </div>
- </Popup>
- {/* 开始日期 */}
- <Popup
- v-model:show={forms.startTimeStatus}
- position="bottom"
- round
- class={'popupBottomSearch'}
- teleport={'body'}
- >
- <DatetimePicker
- v-model={forms.startTime}
- type="date"
- formatter={formatterDatePicker}
- onCancel={() => (forms.startTimeStatus = false)}
- onConfirm={(val: any) => {
- forms.startTime = val
- forms.startTimeStr = dayjs(val).format('YYYY-MM-DD')
- forms.startTimeStatus = false
- forms.endTime = null as any
- forms.endTimeStr = ''
- forms.endTimeMinDate = dayjs(val || new Date()).toDate()
- forms.endTimeMaxDate = dayjs(val || new Date())
- .add(1, 'year')
- .toDate()
- currentType.value = '' as any
- }}
- />
- </Popup>
- {/* 结束日期 */}
- <Popup
- v-model:show={forms.endTimeStatus}
- position="bottom"
- round
- class={'popupBottomSearch'}
- teleport={'body'}
- >
- <DatetimePicker
- v-model={forms.endTime}
- type="date"
- minDate={forms.endTimeMinDate}
- maxDate={forms.endTimeMaxDate}
- formatter={formatterDatePicker}
- onCancel={() => (forms.endTimeStatus = false)}
- onConfirm={(val: any) => {
- forms.endTime = val
- forms.endTimeStatus = false
- forms.endTimeStr = dayjs(val).format('YYYY-MM-DD')
- currentType.value = '' as any
- }}
- />
- </Popup>
- </div>
- )
- }
- })
|