|
@@ -0,0 +1,327 @@
|
|
|
|
+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 {
|
|
|
|
+ getNowDateAndMonday,
|
|
|
|
+ getNowDateAndSunday,
|
|
|
|
+ getTimes
|
|
|
|
+} from '/src/utils/dateFormat';
|
|
|
|
+import CDatePicker from '/src/components/CDatePicker';
|
|
|
|
+export default defineComponent({
|
|
|
|
+ name: 'student-practiceData',
|
|
|
|
+ props: {
|
|
|
|
+ studentId: {
|
|
|
|
+ type: String,
|
|
|
|
+ default: ''
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ setup(props) {
|
|
|
|
+ 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,
|
|
|
|
+ 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 <span>{row.practiceDuration}分钟</span>;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ ];
|
|
|
|
+ };
|
|
|
|
+ const getList = () => {
|
|
|
|
+ console.log('1');
|
|
|
|
+ };
|
|
|
|
+ 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} 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',
|
|
|
|
+ label: {
|
|
|
|
+ // 柱图头部显示值
|
|
|
|
+ show: true,
|
|
|
|
+ position: 'top',
|
|
|
|
+ color: '#333',
|
|
|
|
+ fontSize: '12px',
|
|
|
|
+ fontWeight: 600
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ 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) =>
|
|
|
|
+ `<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;">练习时长: ${d.value}${'分钟'} </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,
|
|
|
|
+ ...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) => {
|
|
|
|
+ return item.practiceDuration;
|
|
|
|
+ });
|
|
|
|
+ state.tableList = res.data.trainingStatDetailList;
|
|
|
|
+ setChart();
|
|
|
|
+ console.log(payForm);
|
|
|
|
+ } catch (e) {
|
|
|
|
+ console.log(e);
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ const search = () => {
|
|
|
|
+ state.pagination.page = 1;
|
|
|
|
+ getChartDetail();
|
|
|
|
+ console.log('search');
|
|
|
|
+ };
|
|
|
|
+ const onReset = () => {
|
|
|
|
+ timer.value = [
|
|
|
|
+ getNowDateAndMonday(new Date().getTime()),
|
|
|
|
+ getNowDateAndSunday(new Date().getTime())
|
|
|
|
+ ];
|
|
|
|
+ search();
|
|
|
|
+ console.log('onReset');
|
|
|
|
+ };
|
|
|
|
+ onMounted(() => {
|
|
|
|
+ console.log(props.studentId);
|
|
|
|
+ getChartDetail();
|
|
|
|
+ });
|
|
|
|
+ return () => (
|
|
|
|
+ <>
|
|
|
|
+ <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>
|
|
|
|
+ <div class={styles.homeTrainData}>
|
|
|
|
+ <div class={styles.TrainDataTop}>
|
|
|
|
+ <div class={styles.TrainDataTopLeft}>
|
|
|
|
+ <div class={styles.TrainDataItem}>
|
|
|
|
+ <p class={styles.TrainDataItemTitle}>
|
|
|
|
+ <span>
|
|
|
|
+ <NNumberAnimation
|
|
|
|
+ from={0}
|
|
|
|
+ to={payForm.practiceDurationTotal}></NNumberAnimation>
|
|
|
|
+ </span>
|
|
|
|
+ 人
|
|
|
|
+ </p>
|
|
|
|
+ <p class={styles.TrainDataItemsubTitle}>累计练习时长</p>
|
|
|
|
+ </div>
|
|
|
|
+ <div class={styles.TrainDataItem}>
|
|
|
|
+ <p class={styles.TrainDataItemTitle}>
|
|
|
|
+ <span>
|
|
|
|
+ <NNumberAnimation
|
|
|
|
+ from={0}
|
|
|
|
+ to={payForm.practiceDurationAvg}></NNumberAnimation>
|
|
|
|
+ </span>
|
|
|
|
+ 分钟
|
|
|
|
+ </p>
|
|
|
|
+ <p class={styles.TrainDataItemsubTitle}>平均练习时长</p>
|
|
|
|
+ </div>
|
|
|
|
+ <div class={styles.TrainDataItem}>
|
|
|
|
+ <p class={styles.TrainDataItemTitle}>
|
|
|
|
+ <span>
|
|
|
|
+ <NNumberAnimation
|
|
|
|
+ from={0}
|
|
|
|
+ to={payForm.practiceDays}></NNumberAnimation>
|
|
|
|
+ </span>
|
|
|
|
+ 天
|
|
|
|
+ </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}>
|
|
|
|
+ <NDataTable
|
|
|
|
+ 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>
|
|
|
|
+ </>
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+});
|