|
@@ -1,461 +1,479 @@
|
|
|
-import { Ref, defineComponent, onMounted, reactive, ref } from 'vue';
|
|
|
-import styles from '../index.module.less';
|
|
|
-import {
|
|
|
- NButton,
|
|
|
- NDataTable,
|
|
|
- NForm,
|
|
|
- NFormItem,
|
|
|
- NNumberAnimation,
|
|
|
- NSpace
|
|
|
-} from 'naive-ui';
|
|
|
-import numeral from 'numeral';
|
|
|
-import { useECharts } from '@/hooks/web/useECharts';
|
|
|
-import Pagination from '/src/components/pagination';
|
|
|
-import { getTrainingStat } from '../api';
|
|
|
-import { getTrainingStatList } from '@/views/classList/api';
|
|
|
-import {
|
|
|
- getNowDateAndMonday,
|
|
|
- getNowDateAndSunday,
|
|
|
- getTimes,
|
|
|
- getMinutes,
|
|
|
- getSecend,
|
|
|
- getHours,
|
|
|
- getLastMinutes,
|
|
|
- formateSeconds,
|
|
|
- getChatMinutes
|
|
|
-} from '/src/utils/dateFormat';
|
|
|
-import CDatePicker from '/src/components/CDatePicker';
|
|
|
-import TheEmpty from '/src/components/TheEmpty';
|
|
|
-import { initCache, setCache } from '/src/hooks/use-async';
|
|
|
-import { useRoute } from 'vue-router';
|
|
|
-export default defineComponent({
|
|
|
- name: 'student-practiceData',
|
|
|
- props: {
|
|
|
- studentId: {
|
|
|
- type: String,
|
|
|
- default: ''
|
|
|
- },
|
|
|
- classGroupId: {
|
|
|
- type: String,
|
|
|
- default: ''
|
|
|
- }
|
|
|
- },
|
|
|
- setup(props) {
|
|
|
- const route = useRoute()
|
|
|
- const chartRef = ref<HTMLDivElement | null>(null);
|
|
|
- const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
|
|
|
- const practiceFlag = ref(true);
|
|
|
- const payForm = reactive({
|
|
|
- height: '360px',
|
|
|
- width: '100%',
|
|
|
- practiceDurationAvg: 0,
|
|
|
- practiceDays: 0,
|
|
|
- practiceDurationTotal: 0,
|
|
|
- dateList: [],
|
|
|
- timeList: []
|
|
|
- });
|
|
|
-
|
|
|
- const state = reactive({
|
|
|
- loading: false,
|
|
|
- dayFlag: true,
|
|
|
- pagination: {
|
|
|
- page: 1,
|
|
|
- rows: 10,
|
|
|
- pageTotal: 4
|
|
|
- },
|
|
|
- tableList: [] as any,
|
|
|
- goCourseVisiable: false
|
|
|
- });
|
|
|
- const timer = ref<[number, number]>([
|
|
|
- getNowDateAndMonday(new Date().getTime()),
|
|
|
- getNowDateAndSunday(new Date().getTime())
|
|
|
- ]);
|
|
|
- const columns = () => {
|
|
|
- return [
|
|
|
- {
|
|
|
- title: '日期',
|
|
|
- key: 'date'
|
|
|
- },
|
|
|
- {
|
|
|
- title: '学练时长',
|
|
|
- key: 'practiceDuration',
|
|
|
- render(row: any) {
|
|
|
- return (
|
|
|
- <>
|
|
|
- {' '}
|
|
|
- <>
|
|
|
- {row.practiceDuration
|
|
|
- ? formateSeconds(row.practiceDuration, 1)
|
|
|
- : 0 + '分钟'}
|
|
|
- </>
|
|
|
- </>
|
|
|
- );
|
|
|
- }
|
|
|
- }
|
|
|
- ];
|
|
|
- };
|
|
|
- const getList = async () => {
|
|
|
- try {
|
|
|
- const res = await getTrainingStatList({
|
|
|
- page: 1,
|
|
|
- rows: 999,
|
|
|
- dayFlag: state.dayFlag,
|
|
|
- studentId: props.studentId,
|
|
|
- classGroupId: props.classGroupId,
|
|
|
- ...getTimes(timer.value, ['startTime', 'endTime'], 'YYYY-MM-DD')
|
|
|
- });
|
|
|
- state.tableList = res.data.rows;
|
|
|
- } catch (e) {
|
|
|
- console.log(e);
|
|
|
- }
|
|
|
- };
|
|
|
- const setChart = () => {
|
|
|
- setOptions({
|
|
|
- tooltip: {
|
|
|
- trigger: 'axis',
|
|
|
- axisPointer: {
|
|
|
- type: 'shadow'
|
|
|
- }
|
|
|
- },
|
|
|
- legend: {
|
|
|
- show: false,
|
|
|
- selected: {
|
|
|
- //在这里设置默认展示就ok了
|
|
|
- '学练时长(分钟)': practiceFlag.value
|
|
|
- }
|
|
|
- },
|
|
|
- xAxis: {
|
|
|
- type: 'category',
|
|
|
- boundaryGap: true,
|
|
|
- axisLabel: {
|
|
|
- show: true
|
|
|
- // interval: 0
|
|
|
- },
|
|
|
- data: payForm.dateList
|
|
|
- },
|
|
|
- yAxis: [
|
|
|
- {
|
|
|
- type: 'value',
|
|
|
- axisLabel: {
|
|
|
- formatter: (value: any) => {
|
|
|
- return (value) + 'min';
|
|
|
- }
|
|
|
- },
|
|
|
- axisTick: {
|
|
|
- show: false
|
|
|
- },
|
|
|
- splitArea: {
|
|
|
- show: false,
|
|
|
- areaStyle: {
|
|
|
- color: ['rgba(255,255,255,0.2)']
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- ],
|
|
|
- grid: {
|
|
|
- left: '1%',
|
|
|
- right: '1%',
|
|
|
- top: '2%',
|
|
|
- bottom: 0,
|
|
|
- containLabel: true
|
|
|
- },
|
|
|
- series: [
|
|
|
- {
|
|
|
- // smooth: true,
|
|
|
- data: payForm.timeList,
|
|
|
- type: 'bar',
|
|
|
- barWidth: '48px',
|
|
|
- stack: 'total',
|
|
|
-
|
|
|
- itemStyle: {
|
|
|
- normal: {
|
|
|
- //这里设置柱形图圆角 [左上角,右上角,右下角,左下角]
|
|
|
- barBorderRadius: [8, 8, 0, 0],
|
|
|
- color: '#D5E9FF'
|
|
|
- },
|
|
|
- emphasis: {
|
|
|
- focus: 'series',
|
|
|
- color: '#3583FA' //hover时改变柱子颜色
|
|
|
- // borderWidth: 4,
|
|
|
- // borderColor: 'rgba(213, 233, 255,.4)',
|
|
|
- // borderType: 'solid'
|
|
|
- }
|
|
|
- } as any
|
|
|
- }
|
|
|
- ],
|
|
|
-
|
|
|
- formatter: (item: any) => {
|
|
|
- if (Array.isArray(item)) {
|
|
|
- return [
|
|
|
- item[0].axisValueLabel,
|
|
|
- ...item.map((d: any) => {
|
|
|
- let str = formateSeconds(d.value[2], 1)
|
|
|
- return `<br/>${d.marker}<span style="margin-top:10px;margin-left:5px;font-size: 13px;font-weight: 500;
|
|
|
- color: #131415;font-weight: 600;
|
|
|
- margin-top:12px
|
|
|
- line-height: 18px;">学练时长: ${str} </span>`;
|
|
|
- })
|
|
|
- ].join('');
|
|
|
- } else {
|
|
|
- return item;
|
|
|
- }
|
|
|
- }
|
|
|
- // dataZoom: [
|
|
|
- // {
|
|
|
- // type: 'slider',
|
|
|
- // start: 5,
|
|
|
- // end: 100,
|
|
|
- // filterMode: 'empty'
|
|
|
- // }
|
|
|
- // ]
|
|
|
- });
|
|
|
- };
|
|
|
-
|
|
|
- const getChartDetail = async () => {
|
|
|
- try {
|
|
|
- const res = await getTrainingStat({
|
|
|
- studentId: props.studentId,
|
|
|
- dayFlag: state.dayFlag,
|
|
|
- classGroupId: props.classGroupId,
|
|
|
- ...getTimes(timer.value, ['startTime', 'endTime'], 'YYYY-MM-DD')
|
|
|
- });
|
|
|
- payForm.practiceDays = res.data.practiceDays;
|
|
|
- payForm.practiceDurationAvg = res.data.practiceDurationAvg;
|
|
|
- payForm.practiceDurationTotal = res.data.practiceDurationTotal;
|
|
|
- payForm.dateList = res.data.trainingStatDetailList.map((item: any) => {
|
|
|
- return item.date;
|
|
|
- });
|
|
|
-
|
|
|
- payForm.timeList = res.data.trainingStatDetailList.map((item: any, index: number) => {
|
|
|
- return [index, getChatMinutes(item.practiceDuration), item.practiceDuration];
|
|
|
- });
|
|
|
-
|
|
|
- setChart();
|
|
|
- } catch (e) {
|
|
|
- console.log(e);
|
|
|
- }
|
|
|
- };
|
|
|
- const search = () => {
|
|
|
- state.pagination.page = 1;
|
|
|
- getChartDetail();
|
|
|
- getList();
|
|
|
- setCache({
|
|
|
- current: { timer: timer.value },
|
|
|
- saveKey: 'classStudentRecordPracticeData'
|
|
|
- });
|
|
|
- };
|
|
|
- const onReset = () => {
|
|
|
- if(route.query.times) {
|
|
|
- timer.value = JSON.parse(route.query.times as any)
|
|
|
- } else {
|
|
|
- timer.value = [
|
|
|
- getNowDateAndMonday(new Date().getTime()),
|
|
|
- getNowDateAndSunday(new Date().getTime())
|
|
|
- ];
|
|
|
- }
|
|
|
-
|
|
|
- search();
|
|
|
- getList();
|
|
|
- setCache({
|
|
|
- current: { timer: timer.value },
|
|
|
- saveKey: 'classStudentRecordPracticeData'
|
|
|
- });
|
|
|
- };
|
|
|
- initCache({
|
|
|
- current: { timer: timer.value },
|
|
|
- saveKey: 'classStudentRecordPracticeData',
|
|
|
- callBack: (active: any) => {
|
|
|
- timer.value = active.timer;
|
|
|
- }
|
|
|
- });
|
|
|
- onMounted(() => {
|
|
|
- if(route.query.times) {
|
|
|
- timer.value = JSON.parse(route.query.times as any)
|
|
|
- }
|
|
|
- getChartDetail();
|
|
|
- getList();
|
|
|
- });
|
|
|
- return () => (
|
|
|
- <>
|
|
|
- <NSpace justify="space-between">
|
|
|
- <NForm label-placement="left" inline>
|
|
|
- <NFormItem>
|
|
|
- <CDatePicker
|
|
|
- v-model:value={timer.value}
|
|
|
- separator={'至'}
|
|
|
- type="daterange"
|
|
|
- timerValue={timer.value}></CDatePicker>
|
|
|
- </NFormItem>
|
|
|
-
|
|
|
- <NFormItem>
|
|
|
- <NSpace justify="end">
|
|
|
- <NButton type="primary" class="searchBtn" onClick={search}>
|
|
|
- 搜索
|
|
|
- </NButton>
|
|
|
- <NButton type="primary" ghost class="resetBtn" onClick={onReset}>
|
|
|
- 重置
|
|
|
- </NButton>
|
|
|
- </NSpace>
|
|
|
- </NFormItem>
|
|
|
- </NForm>
|
|
|
- <NSpace>
|
|
|
- <NButton type="primary" class={state.dayFlag ? "searchDate" : "searchDateDefault"} onClick={() =>{
|
|
|
- state.dayFlag = true;
|
|
|
- search()
|
|
|
- }}>按天</NButton>
|
|
|
- <NButton type="primary" class={state.dayFlag ? "searchDateDefault" : "searchDate"} onClick={() =>{
|
|
|
- state.dayFlag = false;
|
|
|
- search()
|
|
|
- }}>按月</NButton>
|
|
|
- </NSpace>
|
|
|
- </NSpace>
|
|
|
- <div class={[styles.homeTrainData, styles.homeTrainDataPractice]}>
|
|
|
- <div class={styles.TrainDataTop}>
|
|
|
- <div class={styles.TrainDataTopLeft}>
|
|
|
- <div class={styles.TrainDataItem}>
|
|
|
- <p class={styles.TrainDataItemTitle}>
|
|
|
- {getHours(payForm.practiceDurationTotal) > 0 ? (
|
|
|
- <div>
|
|
|
- <span>
|
|
|
- <NNumberAnimation
|
|
|
- from={0}
|
|
|
- to={getHours(
|
|
|
- payForm.practiceDurationTotal
|
|
|
- )}></NNumberAnimation>
|
|
|
- </span>
|
|
|
- <i style={{ width: '4px', display: 'inline-block' }}></i>
|
|
|
- 时
|
|
|
- <i style={{ width: '4px', display: 'inline-block' }}></i>
|
|
|
- </div>
|
|
|
- ) : null}
|
|
|
- {getHours(payForm.practiceDurationAvg) > 0 || getLastMinutes(payForm.practiceDurationTotal) > 0 ? (
|
|
|
- <div>
|
|
|
- <span>
|
|
|
- <NNumberAnimation
|
|
|
- from={0}
|
|
|
- to={getLastMinutes(
|
|
|
- payForm.practiceDurationTotal
|
|
|
- )}></NNumberAnimation>
|
|
|
- </span>
|
|
|
- <i style={{ width: '4px', display: 'inline-block' }}></i>
|
|
|
- 分
|
|
|
- <i style={{ width: '4px', display: 'inline-block' }}></i>
|
|
|
- </div>
|
|
|
- ) : null}
|
|
|
- <div>
|
|
|
- <span>
|
|
|
- <NNumberAnimation
|
|
|
- from={0}
|
|
|
- to={getSecend(
|
|
|
- payForm.practiceDurationTotal
|
|
|
- )}></NNumberAnimation>
|
|
|
- </span>
|
|
|
- <i style={{ width: '4px', display: 'inline-block' }}></i>秒
|
|
|
- </div>
|
|
|
- </p>
|
|
|
- <p class={styles.TrainDataItemsubTitle}>累计练习时长</p>
|
|
|
- </div>
|
|
|
- <div class={styles.TrainDataItem}>
|
|
|
- <p class={styles.TrainDataItemTitle}>
|
|
|
- {getHours(payForm.practiceDurationAvg) > 0 ? (
|
|
|
- <div>
|
|
|
- <span>
|
|
|
- <NNumberAnimation
|
|
|
- from={0}
|
|
|
- to={getHours(
|
|
|
- payForm.practiceDurationAvg
|
|
|
- )}></NNumberAnimation>
|
|
|
- </span>
|
|
|
- <i style={{ width: '4px', display: 'inline-block' }}></i>
|
|
|
- 时
|
|
|
- <i style={{ width: '4px', display: 'inline-block' }}></i>
|
|
|
- </div>
|
|
|
- ) : null}
|
|
|
- {getHours(payForm.practiceDurationAvg) > 0 || getLastMinutes(payForm.practiceDurationAvg) > 0 ? (
|
|
|
- <div>
|
|
|
- <span>
|
|
|
- <NNumberAnimation
|
|
|
- from={0}
|
|
|
- to={getLastMinutes(
|
|
|
- payForm.practiceDurationAvg
|
|
|
- )}></NNumberAnimation>
|
|
|
- </span>
|
|
|
- <i style={{ width: '4px', display: 'inline-block' }}></i>
|
|
|
- 分
|
|
|
- <i style={{ width: '4px', display: 'inline-block' }}></i>
|
|
|
- </div>
|
|
|
- ) : null}
|
|
|
- <div>
|
|
|
- <span>
|
|
|
- <NNumberAnimation
|
|
|
- from={0}
|
|
|
- to={getSecend(
|
|
|
- payForm.practiceDurationAvg
|
|
|
- )}></NNumberAnimation>
|
|
|
- </span>
|
|
|
- <i style={{ width: '4px', display: 'inline-block' }}></i>秒
|
|
|
- </div>
|
|
|
- </p>
|
|
|
- <p class={styles.TrainDataItemsubTitle}>平均每天练习时长</p>
|
|
|
- </div>
|
|
|
- <div class={styles.TrainDataItem}>
|
|
|
- <p class={styles.TrainDataItemTitle}>
|
|
|
- <div>
|
|
|
- <span>
|
|
|
- <NNumberAnimation
|
|
|
- from={0}
|
|
|
- to={payForm.practiceDays}></NNumberAnimation>
|
|
|
- </span>
|
|
|
- <i style={{ width: '4px', display: 'inline-block' }}></i>天
|
|
|
- </div>
|
|
|
- </p>
|
|
|
- <p class={styles.TrainDataItemsubTitle}>练习天数</p>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class={styles.TrainDataTopRight}>
|
|
|
- <div
|
|
|
- // onClick={() => {
|
|
|
- // practiceFlag.value = !practiceFlag.value;
|
|
|
- // setChart();
|
|
|
- // }}
|
|
|
- class={[
|
|
|
- styles.DataTopRightItem,
|
|
|
- practiceFlag.value ? '' : styles.DataTopRightItemDis
|
|
|
- ]}>
|
|
|
- <div
|
|
|
- class={[
|
|
|
- styles.DataTopRightDot,
|
|
|
- styles.DataTopRightDotBlue
|
|
|
- ]}></div>
|
|
|
- <p>学练时长(分钟)</p>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class={styles.chatrs}>
|
|
|
- <div
|
|
|
- ref={chartRef}
|
|
|
- style={{ height: payForm.height, width: payForm.width }}></div>
|
|
|
- </div>
|
|
|
- <div class={[styles.tableWrap, styles.tableWrapEcharts]}>
|
|
|
- <NDataTable
|
|
|
- v-slots={{
|
|
|
- empty: () => <TheEmpty></TheEmpty>
|
|
|
- }}
|
|
|
- class={styles.classTable}
|
|
|
- loading={state.loading}
|
|
|
- columns={columns()}
|
|
|
- data={state.tableList}></NDataTable>
|
|
|
- {/* <Pagination
|
|
|
- v-model:page={state.pagination.page}
|
|
|
- v-model:pageSize={state.pagination.rows}
|
|
|
- v-model:pageTotal={state.pagination.pageTotal}
|
|
|
- onList={getList}
|
|
|
- sync
|
|
|
- saveKey="orchestraRegistration-key"
|
|
|
- /> */}
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </>
|
|
|
- );
|
|
|
- }
|
|
|
-});
|
|
|
+import { Ref, defineComponent, onMounted, reactive, ref } from 'vue';
|
|
|
+import styles from '../index.module.less';
|
|
|
+import {
|
|
|
+ NButton,
|
|
|
+ NDataTable,
|
|
|
+ NForm,
|
|
|
+ NFormItem,
|
|
|
+ NNumberAnimation,
|
|
|
+ NSpace
|
|
|
+} from 'naive-ui';
|
|
|
+import numeral from 'numeral';
|
|
|
+import { useECharts } from '@/hooks/web/useECharts';
|
|
|
+import Pagination from '/src/components/pagination';
|
|
|
+import { getTrainingStat } from '../api';
|
|
|
+import { getTrainingStatList } from '@/views/classList/api';
|
|
|
+import {
|
|
|
+ getNowDateAndMonday,
|
|
|
+ getNowDateAndSunday,
|
|
|
+ getTimes,
|
|
|
+ getMinutes,
|
|
|
+ getSecend,
|
|
|
+ getHours,
|
|
|
+ getLastMinutes,
|
|
|
+ formateSeconds,
|
|
|
+ getChatMinutes
|
|
|
+} from '/src/utils/dateFormat';
|
|
|
+import CDatePicker from '/src/components/CDatePicker';
|
|
|
+import TheEmpty from '/src/components/TheEmpty';
|
|
|
+import { initCache, setCache } from '/src/hooks/use-async';
|
|
|
+import { useRoute } from 'vue-router';
|
|
|
+export default defineComponent({
|
|
|
+ name: 'student-practiceData',
|
|
|
+ props: {
|
|
|
+ studentId: {
|
|
|
+ type: String,
|
|
|
+ default: ''
|
|
|
+ },
|
|
|
+ classGroupId: {
|
|
|
+ type: String,
|
|
|
+ default: ''
|
|
|
+ }
|
|
|
+ },
|
|
|
+ setup(props) {
|
|
|
+ const route = useRoute()
|
|
|
+ const chartRef = ref<HTMLDivElement | null>(null);
|
|
|
+ const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
|
|
|
+ const practiceFlag = ref(true);
|
|
|
+ const payForm = reactive({
|
|
|
+ height: '360px',
|
|
|
+ width: '100%',
|
|
|
+ practiceDurationAvg: 0,
|
|
|
+ practiceDays: 0,
|
|
|
+ practiceDurationTotal: 0,
|
|
|
+ dateList: [],
|
|
|
+ timeList: []
|
|
|
+ });
|
|
|
+
|
|
|
+ const state = reactive({
|
|
|
+ loading: false,
|
|
|
+ dayFlag: true,
|
|
|
+ pagination: {
|
|
|
+ page: 1,
|
|
|
+ rows: 10,
|
|
|
+ pageTotal: 4
|
|
|
+ },
|
|
|
+ tableList: [] as any,
|
|
|
+ goCourseVisiable: false
|
|
|
+ });
|
|
|
+ const timer = ref<[number, number]>([
|
|
|
+ getNowDateAndMonday(new Date().getTime()),
|
|
|
+ getNowDateAndSunday(new Date().getTime())
|
|
|
+ ]);
|
|
|
+ const columns = () => {
|
|
|
+ return [
|
|
|
+ {
|
|
|
+ title: '日期',
|
|
|
+ key: 'date'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '学练时长',
|
|
|
+ key: 'practiceDuration',
|
|
|
+ render(row: any) {
|
|
|
+ return (
|
|
|
+ <>
|
|
|
+ {' '}
|
|
|
+ <>
|
|
|
+ {row.practiceDuration
|
|
|
+ ? formateSeconds(row.practiceDuration, 1)
|
|
|
+ : 0 + '分钟'}
|
|
|
+ </>
|
|
|
+ </>
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ];
|
|
|
+ };
|
|
|
+ const getList = async () => {
|
|
|
+ try {
|
|
|
+ const res = await getTrainingStatList({
|
|
|
+ page: 1,
|
|
|
+ rows: 999,
|
|
|
+ dayFlag: state.dayFlag,
|
|
|
+ studentId: props.studentId,
|
|
|
+ classGroupId: props.classGroupId,
|
|
|
+ ...getTimes(timer.value, ['startTime', 'endTime'], 'YYYY-MM-DD')
|
|
|
+ });
|
|
|
+ state.tableList = res.data.rows;
|
|
|
+ } catch (e) {
|
|
|
+ console.log(e);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ const setChart = () => {
|
|
|
+ setOptions({
|
|
|
+ tooltip: {
|
|
|
+ trigger: 'axis',
|
|
|
+ axisPointer: {
|
|
|
+ type: 'shadow'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ legend: {
|
|
|
+ show: false,
|
|
|
+ selected: {
|
|
|
+ //在这里设置默认展示就ok了
|
|
|
+ '学练时长(分钟)': practiceFlag.value
|
|
|
+ }
|
|
|
+ },
|
|
|
+ xAxis: {
|
|
|
+ type: 'category',
|
|
|
+ boundaryGap: true,
|
|
|
+ axisLabel: {
|
|
|
+ show: true
|
|
|
+ // interval: 0
|
|
|
+ },
|
|
|
+ data: payForm.dateList
|
|
|
+ },
|
|
|
+ yAxis: [
|
|
|
+ {
|
|
|
+ type: 'value',
|
|
|
+ axisLabel: {
|
|
|
+ formatter: (value: any) => {
|
|
|
+ return (value) + 'min';
|
|
|
+ }
|
|
|
+ },
|
|
|
+ axisTick: {
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ splitArea: {
|
|
|
+ show: false,
|
|
|
+ areaStyle: {
|
|
|
+ color: ['rgba(255,255,255,0.2)']
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ grid: {
|
|
|
+ left: '1%',
|
|
|
+ right: '1%',
|
|
|
+ top: '2%',
|
|
|
+ bottom: 0,
|
|
|
+ containLabel: true
|
|
|
+ },
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ // smooth: true,
|
|
|
+ data: payForm.timeList,
|
|
|
+ type: 'line',
|
|
|
+ // name: '达标人数',
|
|
|
+ symbolSize: 10,
|
|
|
+ symbol: 'circle',
|
|
|
+ smooth: true,
|
|
|
+ itemStyle: {
|
|
|
+ color: '#198CFE',
|
|
|
+ borderColor: '#fff',
|
|
|
+ borderWidth: 3
|
|
|
+ },
|
|
|
+ lineStyle: {
|
|
|
+ width: 2 //设置线条粗细
|
|
|
+ },
|
|
|
+ areaStyle: {
|
|
|
+ color: {
|
|
|
+ type: 'linear',
|
|
|
+ x: 0,
|
|
|
+ y: 0,
|
|
|
+ x2: 0,
|
|
|
+ y2: 1,
|
|
|
+ colorStops: [
|
|
|
+ {
|
|
|
+ offset: 0,
|
|
|
+ color: 'rgba(212, 231, 255, 1)'
|
|
|
+ // 0% 处的颜色
|
|
|
+ },
|
|
|
+ {
|
|
|
+ offset: 1,
|
|
|
+ color: 'rgba(221, 235, 254, 0)' // 100% 处的颜色
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ },
|
|
|
+ emphasis: {
|
|
|
+ disabled: true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ],
|
|
|
+
|
|
|
+ formatter: (item: any) => {
|
|
|
+ if (Array.isArray(item)) {
|
|
|
+ return [
|
|
|
+ item[0].axisValueLabel,
|
|
|
+ ...item.map((d: any) => {
|
|
|
+ let str = formateSeconds(d.value[2], 1)
|
|
|
+ return `<br/>${d.marker}<span style="margin-top:10px;margin-left:5px;font-size: 13px;font-weight: 500;
|
|
|
+ color: #131415;font-weight: 600;
|
|
|
+ margin-top:12px
|
|
|
+ line-height: 18px;">学练时长: ${str} </span>`;
|
|
|
+ })
|
|
|
+ ].join('');
|
|
|
+ } else {
|
|
|
+ return item;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // dataZoom: [
|
|
|
+ // {
|
|
|
+ // type: 'slider',
|
|
|
+ // start: 5,
|
|
|
+ // end: 100,
|
|
|
+ // filterMode: 'empty'
|
|
|
+ // }
|
|
|
+ // ]
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ const getChartDetail = async () => {
|
|
|
+ try {
|
|
|
+ const res = await getTrainingStat({
|
|
|
+ studentId: props.studentId,
|
|
|
+ dayFlag: state.dayFlag,
|
|
|
+ classGroupId: props.classGroupId,
|
|
|
+ ...getTimes(timer.value, ['startTime', 'endTime'], 'YYYY-MM-DD')
|
|
|
+ });
|
|
|
+ payForm.practiceDays = res.data.practiceDays;
|
|
|
+ payForm.practiceDurationAvg = res.data.practiceDurationAvg;
|
|
|
+ payForm.practiceDurationTotal = res.data.practiceDurationTotal;
|
|
|
+ payForm.dateList = res.data.trainingStatDetailList.map((item: any) => {
|
|
|
+ return item.date;
|
|
|
+ });
|
|
|
+
|
|
|
+ payForm.timeList = res.data.trainingStatDetailList.map((item: any, index: number) => {
|
|
|
+ return [index, getChatMinutes(item.practiceDuration), item.practiceDuration];
|
|
|
+ });
|
|
|
+
|
|
|
+ setChart();
|
|
|
+ } catch (e) {
|
|
|
+ console.log(e);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ const search = () => {
|
|
|
+ state.pagination.page = 1;
|
|
|
+ getChartDetail();
|
|
|
+ getList();
|
|
|
+ setCache({
|
|
|
+ current: { timer: timer.value },
|
|
|
+ saveKey: 'classStudentRecordPracticeData'
|
|
|
+ });
|
|
|
+ };
|
|
|
+ const onReset = () => {
|
|
|
+ if(route.query.times) {
|
|
|
+ timer.value = JSON.parse(route.query.times as any)
|
|
|
+ } else {
|
|
|
+ timer.value = [
|
|
|
+ getNowDateAndMonday(new Date().getTime()),
|
|
|
+ getNowDateAndSunday(new Date().getTime())
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ search();
|
|
|
+ getList();
|
|
|
+ setCache({
|
|
|
+ current: { timer: timer.value },
|
|
|
+ saveKey: 'classStudentRecordPracticeData'
|
|
|
+ });
|
|
|
+ };
|
|
|
+ initCache({
|
|
|
+ current: { timer: timer.value },
|
|
|
+ saveKey: 'classStudentRecordPracticeData',
|
|
|
+ callBack: (active: any) => {
|
|
|
+ timer.value = active.timer;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ onMounted(() => {
|
|
|
+ if(route.query.times) {
|
|
|
+ timer.value = JSON.parse(route.query.times as any)
|
|
|
+ }
|
|
|
+ getChartDetail();
|
|
|
+ getList();
|
|
|
+ });
|
|
|
+ return () => (
|
|
|
+ <>
|
|
|
+ <NSpace justify="space-between">
|
|
|
+ <NForm label-placement="left" inline>
|
|
|
+ <NFormItem>
|
|
|
+ <CDatePicker
|
|
|
+ v-model:value={timer.value}
|
|
|
+ separator={'至'}
|
|
|
+ type="daterange"
|
|
|
+ timerValue={timer.value}></CDatePicker>
|
|
|
+ </NFormItem>
|
|
|
+
|
|
|
+ <NFormItem>
|
|
|
+ <NSpace justify="end">
|
|
|
+ <NButton type="primary" class="searchBtn" onClick={search}>
|
|
|
+ 搜索
|
|
|
+ </NButton>
|
|
|
+ <NButton type="primary" ghost class="resetBtn" onClick={onReset}>
|
|
|
+ 重置
|
|
|
+ </NButton>
|
|
|
+ </NSpace>
|
|
|
+ </NFormItem>
|
|
|
+ </NForm>
|
|
|
+ <NSpace>
|
|
|
+ <NButton type="primary" class={state.dayFlag ? "searchDate" : "searchDateDefault"} onClick={() =>{
|
|
|
+ state.dayFlag = true;
|
|
|
+ search()
|
|
|
+ }}>按天</NButton>
|
|
|
+ <NButton type="primary" class={state.dayFlag ? "searchDateDefault" : "searchDate"} onClick={() =>{
|
|
|
+ state.dayFlag = false;
|
|
|
+ search()
|
|
|
+ }}>按月</NButton>
|
|
|
+ </NSpace>
|
|
|
+ </NSpace>
|
|
|
+ <div class={[styles.homeTrainData, styles.homeTrainDataPractice]}>
|
|
|
+ <div class={styles.TrainDataTop}>
|
|
|
+ <div class={styles.TrainDataTopLeft}>
|
|
|
+ <div class={styles.TrainDataItem}>
|
|
|
+ <p class={styles.TrainDataItemTitle}>
|
|
|
+ {getHours(payForm.practiceDurationTotal) > 0 ? (
|
|
|
+ <div>
|
|
|
+ <span>
|
|
|
+ <NNumberAnimation
|
|
|
+ from={0}
|
|
|
+ to={getHours(
|
|
|
+ payForm.practiceDurationTotal
|
|
|
+ )}></NNumberAnimation>
|
|
|
+ </span>
|
|
|
+ <i style={{ width: '4px', display: 'inline-block' }}></i>
|
|
|
+ 时
|
|
|
+ <i style={{ width: '4px', display: 'inline-block' }}></i>
|
|
|
+ </div>
|
|
|
+ ) : null}
|
|
|
+ {getHours(payForm.practiceDurationAvg) > 0 || getLastMinutes(payForm.practiceDurationTotal) > 0 ? (
|
|
|
+ <div>
|
|
|
+ <span>
|
|
|
+ <NNumberAnimation
|
|
|
+ from={0}
|
|
|
+ to={getLastMinutes(
|
|
|
+ payForm.practiceDurationTotal
|
|
|
+ )}></NNumberAnimation>
|
|
|
+ </span>
|
|
|
+ <i style={{ width: '4px', display: 'inline-block' }}></i>
|
|
|
+ 分
|
|
|
+ <i style={{ width: '4px', display: 'inline-block' }}></i>
|
|
|
+ </div>
|
|
|
+ ) : null}
|
|
|
+ <div>
|
|
|
+ <span>
|
|
|
+ <NNumberAnimation
|
|
|
+ from={0}
|
|
|
+ to={getSecend(
|
|
|
+ payForm.practiceDurationTotal
|
|
|
+ )}></NNumberAnimation>
|
|
|
+ </span>
|
|
|
+ <i style={{ width: '4px', display: 'inline-block' }}></i>秒
|
|
|
+ </div>
|
|
|
+ </p>
|
|
|
+ <p class={styles.TrainDataItemsubTitle}>累计练习时长</p>
|
|
|
+ </div>
|
|
|
+ <div class={styles.TrainDataItem}>
|
|
|
+ <p class={styles.TrainDataItemTitle}>
|
|
|
+ {getHours(payForm.practiceDurationAvg) > 0 ? (
|
|
|
+ <div>
|
|
|
+ <span>
|
|
|
+ <NNumberAnimation
|
|
|
+ from={0}
|
|
|
+ to={getHours(
|
|
|
+ payForm.practiceDurationAvg
|
|
|
+ )}></NNumberAnimation>
|
|
|
+ </span>
|
|
|
+ <i style={{ width: '4px', display: 'inline-block' }}></i>
|
|
|
+ 时
|
|
|
+ <i style={{ width: '4px', display: 'inline-block' }}></i>
|
|
|
+ </div>
|
|
|
+ ) : null}
|
|
|
+ {getHours(payForm.practiceDurationAvg) > 0 || getLastMinutes(payForm.practiceDurationAvg) > 0 ? (
|
|
|
+ <div>
|
|
|
+ <span>
|
|
|
+ <NNumberAnimation
|
|
|
+ from={0}
|
|
|
+ to={getLastMinutes(
|
|
|
+ payForm.practiceDurationAvg
|
|
|
+ )}></NNumberAnimation>
|
|
|
+ </span>
|
|
|
+ <i style={{ width: '4px', display: 'inline-block' }}></i>
|
|
|
+ 分
|
|
|
+ <i style={{ width: '4px', display: 'inline-block' }}></i>
|
|
|
+ </div>
|
|
|
+ ) : null}
|
|
|
+ <div>
|
|
|
+ <span>
|
|
|
+ <NNumberAnimation
|
|
|
+ from={0}
|
|
|
+ to={getSecend(
|
|
|
+ payForm.practiceDurationAvg
|
|
|
+ )}></NNumberAnimation>
|
|
|
+ </span>
|
|
|
+ <i style={{ width: '4px', display: 'inline-block' }}></i>秒
|
|
|
+ </div>
|
|
|
+ </p>
|
|
|
+ <p class={styles.TrainDataItemsubTitle}>平均每天练习时长</p>
|
|
|
+ </div>
|
|
|
+ <div class={styles.TrainDataItem}>
|
|
|
+ <p class={styles.TrainDataItemTitle}>
|
|
|
+ <div>
|
|
|
+ <span>
|
|
|
+ <NNumberAnimation
|
|
|
+ from={0}
|
|
|
+ to={payForm.practiceDays}></NNumberAnimation>
|
|
|
+ </span>
|
|
|
+ <i style={{ width: '4px', display: 'inline-block' }}></i>天
|
|
|
+ </div>
|
|
|
+ </p>
|
|
|
+ <p class={styles.TrainDataItemsubTitle}>练习天数</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class={styles.TrainDataTopRight}>
|
|
|
+ <div
|
|
|
+ // onClick={() => {
|
|
|
+ // practiceFlag.value = !practiceFlag.value;
|
|
|
+ // setChart();
|
|
|
+ // }}
|
|
|
+ class={[
|
|
|
+ styles.DataTopRightItem,
|
|
|
+ practiceFlag.value ? '' : styles.DataTopRightItemDis
|
|
|
+ ]}>
|
|
|
+ <div
|
|
|
+ class={[
|
|
|
+ styles.DataTopRightDot,
|
|
|
+ styles.DataTopRightDotBlue
|
|
|
+ ]}></div>
|
|
|
+ <p>学练时长(分钟)</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class={styles.chatrs}>
|
|
|
+ <div
|
|
|
+ ref={chartRef}
|
|
|
+ style={{ height: payForm.height, width: payForm.width }}></div>
|
|
|
+ </div>
|
|
|
+ <div class={[styles.tableWrap, styles.tableWrapEcharts]}>
|
|
|
+ <NDataTable
|
|
|
+ v-slots={{
|
|
|
+ empty: () => <TheEmpty></TheEmpty>
|
|
|
+ }}
|
|
|
+ class={styles.classTable}
|
|
|
+ loading={state.loading}
|
|
|
+ columns={columns()}
|
|
|
+ data={state.tableList}></NDataTable>
|
|
|
+ {/* <Pagination
|
|
|
+ v-model:page={state.pagination.page}
|
|
|
+ v-model:pageSize={state.pagination.rows}
|
|
|
+ v-model:pageTotal={state.pagination.pageTotal}
|
|
|
+ onList={getList}
|
|
|
+ sync
|
|
|
+ saveKey="orchestraRegistration-key"
|
|
|
+ /> */}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </>
|
|
|
+ );
|
|
|
+ }
|
|
|
+});
|