|
@@ -4,7 +4,15 @@ dayjs.extend(isBetween)
|
|
|
import { List, Image, Calendar, Cell } from 'vant'
|
|
|
import OFullRefresh from '@/components/the-full-refresh'
|
|
|
import DetailItem from './modals/detail-item'
|
|
|
-import { defineComponent, onMounted, reactive, ref, computed } from 'vue'
|
|
|
+import {
|
|
|
+ defineComponent,
|
|
|
+ onMounted,
|
|
|
+ reactive,
|
|
|
+ ref,
|
|
|
+ computed,
|
|
|
+ markRaw,
|
|
|
+ nextTick
|
|
|
+} from 'vue'
|
|
|
import { useRoute } from 'vue-router'
|
|
|
import styles from './exercis-detail.module.less'
|
|
|
import request from '@/helpers/request'
|
|
@@ -16,6 +24,66 @@ import bgImg from '../images/bg-image.png'
|
|
|
import iconStudent from '@common/images/icon_student.png'
|
|
|
import iconLogo from '../member-center/images/icon-logo-default.png'
|
|
|
import iconLogoActive from '../member-center/images/icon-logo.png'
|
|
|
+import iconSubject from './images/icon-subject.png'
|
|
|
+import iconTrainTitle from './images/train-title.png'
|
|
|
+
|
|
|
+import * as echarts from 'echarts/core'
|
|
|
+import {
|
|
|
+ BarChart,
|
|
|
+ // 系列类型的定义后缀都为 SeriesOption
|
|
|
+ BarSeriesOption,
|
|
|
+ LineChart,
|
|
|
+ LineSeriesOption
|
|
|
+} from 'echarts/charts'
|
|
|
+import { PieChart } from 'echarts/charts'
|
|
|
+import {
|
|
|
+ TitleComponent,
|
|
|
+ // 组件类型的定义后缀都为 ComponentOption
|
|
|
+ TitleComponentOption,
|
|
|
+ TooltipComponent,
|
|
|
+ TooltipComponentOption,
|
|
|
+ GridComponent,
|
|
|
+ GridComponentOption,
|
|
|
+ // 数据集组件
|
|
|
+ DatasetComponent,
|
|
|
+ DatasetComponentOption,
|
|
|
+ // 内置数据转换器组件 (filter, sort)
|
|
|
+ TransformComponent,
|
|
|
+ LegendComponent,
|
|
|
+ ToolboxComponent,
|
|
|
+ DataZoomComponent
|
|
|
+} from 'echarts/components'
|
|
|
+import { LabelLayout, UniversalTransition } from 'echarts/features'
|
|
|
+import { CanvasRenderer } from 'echarts/renderers'
|
|
|
+import { lineChartOption } from './echats'
|
|
|
+
|
|
|
+// 通过 ComposeOption 来组合出一个只有必须组件和图表的 Option 类型
|
|
|
+type ECOption = echarts.ComposeOption<
|
|
|
+ | BarSeriesOption
|
|
|
+ | LineSeriesOption
|
|
|
+ | TitleComponentOption
|
|
|
+ | TooltipComponentOption
|
|
|
+ | GridComponentOption
|
|
|
+ | DatasetComponentOption
|
|
|
+>
|
|
|
+
|
|
|
+// 注册必须的组件
|
|
|
+echarts.use([
|
|
|
+ TitleComponent,
|
|
|
+ TooltipComponent,
|
|
|
+ GridComponent,
|
|
|
+ DatasetComponent,
|
|
|
+ TransformComponent,
|
|
|
+ BarChart,
|
|
|
+ LabelLayout,
|
|
|
+ UniversalTransition,
|
|
|
+ CanvasRenderer,
|
|
|
+ PieChart,
|
|
|
+ ToolboxComponent,
|
|
|
+ LegendComponent,
|
|
|
+ DataZoomComponent,
|
|
|
+ LineChart
|
|
|
+])
|
|
|
|
|
|
export default defineComponent({
|
|
|
name: 'exercis-detail',
|
|
@@ -31,9 +99,17 @@ export default defineComponent({
|
|
|
userTrainOverView: {
|
|
|
trainDays: 0,
|
|
|
trainNum: 0,
|
|
|
- trainTime: 0
|
|
|
- }
|
|
|
+ trainTime: 0,
|
|
|
+ avgTrainTime: 0
|
|
|
+ },
|
|
|
+ userTrainChartData: [] as any,
|
|
|
+ myChart: null as any
|
|
|
})
|
|
|
+ const qualifiedFlag = ref(true)
|
|
|
+ const unqualifiedFlag = ref(true)
|
|
|
+
|
|
|
+ // const chartRef = ref<HTMLDivElement | null>(null)
|
|
|
+ // const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>)
|
|
|
|
|
|
const userInfo = computed(() => {
|
|
|
const users = baseState.user.data
|
|
@@ -49,8 +125,7 @@ export default defineComponent({
|
|
|
}
|
|
|
})
|
|
|
const forms = reactive({
|
|
|
- practiceMonth: dayjs().day(1).format('YYYYMMDD'),
|
|
|
- startTime: '2023-09',
|
|
|
+ startTime: dayjs().day(1).format('YYYY-MM-DD'),
|
|
|
endTime: dayjs().day(7).format('YYYY-MM-DD'),
|
|
|
page: 1,
|
|
|
rows: 20
|
|
@@ -72,7 +147,7 @@ export default defineComponent({
|
|
|
}
|
|
|
try {
|
|
|
const { data } = await request.get(
|
|
|
- `/api-student/sysMusicRecord/studentTrainData`,
|
|
|
+ `/api-student/sysMusicRecord/studentTrainDataByWeek`,
|
|
|
{
|
|
|
params: { ...forms }
|
|
|
}
|
|
@@ -85,7 +160,7 @@ export default defineComponent({
|
|
|
if (list.value.length > 0 && data.detail.pageNo === 1) {
|
|
|
return
|
|
|
}
|
|
|
-
|
|
|
+ state.userTrainChartData = data.userTrainChartData || []
|
|
|
list.value = list.value.concat(data.detail.rows || [])
|
|
|
forms.page = data.detail.pageNo + 1
|
|
|
showContact.value = list.value.length > 0
|
|
@@ -96,21 +171,39 @@ export default defineComponent({
|
|
|
finished.value = true
|
|
|
}
|
|
|
state.isClick = false
|
|
|
- }
|
|
|
|
|
|
- onMounted(async () => {
|
|
|
- await getList()
|
|
|
- })
|
|
|
+ // if (showContact.value) {
|
|
|
+ nextTick(() => {
|
|
|
+ if (document.getElementById('exerciseWeek')) {
|
|
|
+ state.myChart = markRaw(
|
|
|
+ echarts.init(
|
|
|
+ document.getElementById('exerciseWeek') as HTMLDivElement
|
|
|
+ )
|
|
|
+ )
|
|
|
|
|
|
- const checkTimer = (val: any) => {
|
|
|
- // forms.practiceMonth = val.selectedValues[0] + val.selectedValues[1]
|
|
|
- // state.practiceMonthName =
|
|
|
- // val.selectedValues[0] + '年' + val.selectedValues[1] + '月'
|
|
|
- state.showPopoverTime = false
|
|
|
- refreshing.value = true
|
|
|
- getList()
|
|
|
- }
|
|
|
+ const cloudTime: any = []
|
|
|
+ const cloudNum: any = []
|
|
|
+ state.userTrainChartData.forEach((data: any) => {
|
|
|
+ const indexData = data.indexMonthData || []
|
|
|
+ if (data.dataType === 'CLOUD_STUDY_TRAIN_TIME') {
|
|
|
+ indexData.forEach((d: any) => {
|
|
|
+ cloudTime.push(d.totalNum)
|
|
|
+ })
|
|
|
+ } else if (data.dataType === 'CLOUD_STUDY_TRAIN_NUM') {
|
|
|
+ indexData.forEach((d: any) => {
|
|
|
+ cloudNum.push(d.totalNum)
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ lineChartOption.series[0].data = cloudTime
|
|
|
+ lineChartOption.series[1].data = cloudNum
|
|
|
|
|
|
+ state.myChart.clear()
|
|
|
+ state.myChart.setOption(lineChartOption)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ // }
|
|
|
+ }
|
|
|
const onRefresh = () => {
|
|
|
finished.value = false
|
|
|
// 重新加载数据
|
|
@@ -119,6 +212,10 @@ export default defineComponent({
|
|
|
getList()
|
|
|
}
|
|
|
|
|
|
+ onMounted(async () => {
|
|
|
+ await getList()
|
|
|
+ })
|
|
|
+
|
|
|
return () => (
|
|
|
<div class={[styles.exercisContainer]}>
|
|
|
<div class={styles.topWrap}>
|
|
@@ -131,6 +228,7 @@ export default defineComponent({
|
|
|
<Cell
|
|
|
class={styles.userMember}
|
|
|
labelClass={styles.timeRemaining}
|
|
|
+ border={false}
|
|
|
v-slots={{
|
|
|
icon: () => (
|
|
|
<div class={styles.userImgSection}>
|
|
@@ -150,64 +248,110 @@ export default defineComponent({
|
|
|
/>
|
|
|
</div>
|
|
|
),
|
|
|
- label: () => <div class={styles.subjectName}></div>
|
|
|
+ label: () => (
|
|
|
+ <div class={styles.subjectName}>
|
|
|
+ <span class={styles.subjectTag}>
|
|
|
+ <img src={iconSubject} class={styles.iconSubject} />
|
|
|
+ 口风琴
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ )
|
|
|
}}
|
|
|
></Cell>
|
|
|
+
|
|
|
+ <div class={styles.itemBottom}>
|
|
|
+ <div class={styles.itemBottomDot}>
|
|
|
+ <p class={styles.dotMain}>
|
|
|
+ {state.userTrainOverView.trainTime || 0}
|
|
|
+ <span>分钟</span>{' '}
|
|
|
+ </p>
|
|
|
+ <p class={styles.dotSub}> 累计练习时长</p>
|
|
|
+ </div>
|
|
|
+ <div class={styles.itemBottomDot}>
|
|
|
+ <p class={styles.dotMain}>
|
|
|
+ {state.userTrainOverView.trainDays || 0}
|
|
|
+ <span>天</span>{' '}
|
|
|
+ </p>
|
|
|
+ <p class={styles.dotSub}>累计练习天数 </p>
|
|
|
+ </div>
|
|
|
+ <div class={styles.itemBottomDot}>
|
|
|
+ <p class={styles.dotMain}>
|
|
|
+ {state.userTrainOverView.avgTrainTime || 0}
|
|
|
+ <span>分钟</span>{' '}
|
|
|
+ </p>
|
|
|
+ <p class={styles.dotSub}>平均训练时长 </p>
|
|
|
+ </div>
|
|
|
+ <div class={styles.itemBottomDot}>
|
|
|
+ <p class={styles.dotMain}>
|
|
|
+ {state.userTrainOverView.trainNum || 0}
|
|
|
+ <span>次</span>{' '}
|
|
|
+ </p>
|
|
|
+ <p class={styles.dotSub}>累计训练次数 </p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</TheSticky>
|
|
|
</div>
|
|
|
<img class={styles.bgImg} src={bgImg} />
|
|
|
- {/* <div class={styles.topInfoRight}>
|
|
|
- <div class={styles.infoDay}>
|
|
|
- <p class={styles.infoDayMain}>
|
|
|
- {infoDetail.value.practiceDays
|
|
|
- ? infoDetail.value.practiceDays
|
|
|
- : 0}
|
|
|
- </p>
|
|
|
- <p class={styles.infoDaysub}>
|
|
|
- <img src={iconDays} />
|
|
|
- 练习天数(天)
|
|
|
- </p>
|
|
|
- </div>
|
|
|
- <div class={styles.infoTime}>
|
|
|
- <p class={styles.infoDayMain}>
|
|
|
- {infoDetail.value.practiceTimes
|
|
|
- ? Math.floor(infoDetail.value.practiceTimes / 60)
|
|
|
- : 0}
|
|
|
|
|
|
- </p>
|
|
|
- <p class={styles.infoDaysub}>
|
|
|
- <img src={iconClock} />
|
|
|
- 练习时长(分钟)
|
|
|
- </p>
|
|
|
- </div>
|
|
|
- </div> */}
|
|
|
- {/* <CellGroup inset>
|
|
|
- <Cell
|
|
|
- class={styles.select}
|
|
|
- center
|
|
|
- isLink
|
|
|
+ <div class={styles.trainWeek}>
|
|
|
+ <div class={styles.trainTitle}>
|
|
|
+ <img src={iconTrainTitle} />
|
|
|
+
|
|
|
+ <span
|
|
|
+ class={styles.timeRange}
|
|
|
onClick={() => (state.showPopoverTime = true)}
|
|
|
>
|
|
|
- {{
|
|
|
- // icon: () => <img class={styles.icon} src={iconData} />,
|
|
|
- title: () => (
|
|
|
- <div class="van-ellipsis">{state.practiceMonthName}</div>
|
|
|
- )
|
|
|
+ {dayjs(forms.startTime).format('YYYY-MM-DD')}至
|
|
|
+ {dayjs(forms.endTime).format('YYYY-MM-DD')}
|
|
|
+ <i class={styles.iconArrow}></i>
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ <div class={styles.TrainDataTopRight}>
|
|
|
+ <div
|
|
|
+ onClick={() => {
|
|
|
+ qualifiedFlag.value = !qualifiedFlag.value
|
|
|
+ lineChartOption.legend.selected['训练时长'] =
|
|
|
+ qualifiedFlag.value
|
|
|
+ state.myChart.setOption(lineChartOption)
|
|
|
}}
|
|
|
- </Cell>
|
|
|
- </CellGroup>
|
|
|
- */}
|
|
|
+ class={[
|
|
|
+ styles.DataTopRightItem,
|
|
|
+ qualifiedFlag.value ? '' : styles.DataTopRightItemDis
|
|
|
+ ]}
|
|
|
+ >
|
|
|
+ <div class={styles.DataTopRightDot}></div>
|
|
|
+ <p>训练时长</p>
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ onClick={() => {
|
|
|
+ unqualifiedFlag.value = !unqualifiedFlag.value
|
|
|
+ lineChartOption.legend.selected['使用次数'] =
|
|
|
+ unqualifiedFlag.value
|
|
|
+ state.myChart.setOption(lineChartOption)
|
|
|
+ }}
|
|
|
+ class={[
|
|
|
+ styles.DataTopRightItem,
|
|
|
+ unqualifiedFlag.value ? '' : styles.DataTopRightItemDis
|
|
|
+ ]}
|
|
|
+ >
|
|
|
+ <div class={[styles.DataTopRightDot, styles.red]}></div>
|
|
|
+ <p>使用次数</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div id="exerciseWeek" class={styles.exerciseWeek}></div>
|
|
|
+ </div>
|
|
|
{showContact.value ? (
|
|
|
<OFullRefresh
|
|
|
v-model:modelValue={refreshing.value}
|
|
|
onRefresh={onRefresh}
|
|
|
- style={{ minHeight: `calc(100vh - var(--header-height))` }}
|
|
|
+ class={styles.fullRefresh}
|
|
|
>
|
|
|
<List
|
|
|
loading-text=" "
|
|
|
finished={finished.value}
|
|
|
finished-text=" "
|
|
|
onLoad={getList}
|
|
|
+ style={{ overflow: 'hidden' }}
|
|
|
>
|
|
|
{list.value.map((item: any) => (
|
|
|
<DetailItem item={item} />
|
|
@@ -216,13 +360,18 @@ export default defineComponent({
|
|
|
</OFullRefresh>
|
|
|
) : (
|
|
|
<div
|
|
|
- style={{
|
|
|
- height: `calc(100vh - var(--header-height))`,
|
|
|
- display: 'flex',
|
|
|
- alignItems: 'center'
|
|
|
- }}
|
|
|
+ // style={{
|
|
|
+ // height: `calc(100vh - var(--header-height))`,
|
|
|
+ // display: 'flex',
|
|
|
+ // alignItems: 'center'
|
|
|
+ // }}
|
|
|
+ class={styles.emptyContainer}
|
|
|
>
|
|
|
- <ColResult tips="暂无学练统计" btnStatus={false} />
|
|
|
+ <ColResult
|
|
|
+ tips="暂无学练统计"
|
|
|
+ classImgSize="SMALL"
|
|
|
+ btnStatus={false}
|
|
|
+ />
|
|
|
</div>
|
|
|
)}
|
|
|
|
|
@@ -235,44 +384,46 @@ export default defineComponent({
|
|
|
maxRange={7}
|
|
|
minDate={new Date('2023-02-27')}
|
|
|
defaultDate={[
|
|
|
- dayjs(forms.practiceMonth).toDate(),
|
|
|
+ dayjs(forms.startTime).toDate(),
|
|
|
dayjs(forms.endTime).toDate()
|
|
|
]}
|
|
|
style={{
|
|
|
height: '70%'
|
|
|
}}
|
|
|
onSelect={(item: any) => {
|
|
|
- forms.practiceMonth = ''
|
|
|
+ forms.startTime = ''
|
|
|
forms.endTime = ''
|
|
|
if (
|
|
|
!dayjs(item[0]).isBetween(
|
|
|
- dayjs(forms.practiceMonth),
|
|
|
+ dayjs(forms.startTime),
|
|
|
dayjs(forms.endTime)
|
|
|
)
|
|
|
) {
|
|
|
const week = dayjs(item[0]).day()
|
|
|
if (week === 0) {
|
|
|
// 星期天
|
|
|
- forms.practiceMonth = dayjs(item[0])
|
|
|
+ forms.startTime = dayjs(item[0])
|
|
|
.subtract(6, 'day')
|
|
|
- .format('YYYYMMDD')
|
|
|
+ .format('YYYY-MM-DD')
|
|
|
forms.endTime = dayjs(item[0]).format('YYYY-MM-DD')
|
|
|
} else if (week === 1) {
|
|
|
// 星期一
|
|
|
- forms.practiceMonth = dayjs(item[0]).format('YYYYMMDD')
|
|
|
+ forms.startTime = dayjs(item[0]).format('YYYY-MM-DD')
|
|
|
forms.endTime = dayjs(item[0])
|
|
|
.add(6, 'day')
|
|
|
.format('YYYY-MM-DD')
|
|
|
} else {
|
|
|
- forms.practiceMonth = dayjs(item[0])
|
|
|
+ forms.startTime = dayjs(item[0])
|
|
|
.subtract(week - 1, 'day')
|
|
|
- .format('YYYYMMDD')
|
|
|
+ .format('YYYY-MM-DD')
|
|
|
forms.endTime = dayjs(item[0])
|
|
|
.add(7 - week, 'day')
|
|
|
.format('YYYY-MM-DD')
|
|
|
}
|
|
|
}
|
|
|
state.showPopoverTime = false
|
|
|
+ refreshing.value = true
|
|
|
+ getList()
|
|
|
}}
|
|
|
/>
|
|
|
</div>
|