Przeglądaj źródła

到测评 等待数据

1
mo 1 rok temu
rodzic
commit
6a4607264c

+ 8 - 2
src/views/classList/components/classStudentRecode.tsx

@@ -18,6 +18,8 @@ import defultHeade from '@/components/layout/images/teacherIcon.png';
 import femaleIcon from '@/views/setting/images/femaleIcon.png';
 import maleIcon from '@/views/setting/images/maleIcon.png';
 import PracticeData from '@/views/studentList/components/practiceData';
+import EvaluationRecords from '@/views/studentList/components/evaluationRecords';
+
 import dayjs from 'dayjs';
 export default defineComponent({
   name: 'classStudentRecode',
@@ -89,9 +91,13 @@ export default defineComponent({
             pane-wrapper-style="margin: 0 -4px"
             pane-style="padding-left: 4px; padding-right: 4px; box-sizing: border-box;">
             <NTabPane name="textRcode" tab="练习记录">
-              <PracticeData></PracticeData>
+              <PracticeData
+                studentId={route.query.studentId as string}></PracticeData>
+            </NTabPane>
+            <NTabPane name="evaluatingRcode" tab="评测记录">
+              <EvaluationRecords
+                studentId={route.query.studentId as string}></EvaluationRecords>
             </NTabPane>
-            <NTabPane name="evaluatingRcode" tab="评测记录"></NTabPane>
           </NTabs>
         </div>
       </div>

+ 3 - 5
src/views/classList/index.tsx

@@ -171,13 +171,11 @@ export default defineComponent({
                     开始上课
                   </NButton>
                   {!(row.preStudentNum > 0) ? (
-                    <NButton
-                      type="primary"
-                      text
-                      textColor="#EA4132"
+                    <p
+                      style={{ color: '#EA4132', cursor: 'pointer' }}
                       onClick={() => removeClass(row)}>
                       删除
-                    </NButton>
+                    </p>
                   ) : null}
                 </NSpace>
               </div>

+ 21 - 0
src/views/studentList/api.ts

@@ -0,0 +1,21 @@
+import request from '@/utils/request';
+/**
+ * 学员管理 - 获取学员训练统计
+ */
+export const getTrainingStat = (params: any) => {
+  return request.post('/edu-app/musicPracticeRecordStat/trainingStat', {
+    data: params
+    // requestType: 'form'
+  });
+};
+
+/**
+ * 获取评测列表
+ */
+export const getPracticeRecordList = (params: any) => {
+  return request.post('/edu-app/musicPracticeRecord/page', {
+    data: params,
+    params
+    // requestType: 'form'
+  });
+};

+ 189 - 0
src/views/studentList/components/evaluationRecords.tsx

@@ -0,0 +1,189 @@
+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 { getPracticeRecordList } 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: 'createTime'
+        },
+        {
+          title: '评测曲目',
+          key: 'musicSheetName',
+          render(row: any) {
+            return <span>{row.musicSheetName}</span>;
+          }
+        },
+        {
+          title: '评测难度',
+          key: 'heardLevel',
+          render(row: any) {
+            return <span>{row.heardLevel}</span>;
+          }
+        },
+        {
+          title: '评测分数',
+          key: 'score',
+          render(row: any) {
+            return <span>{row.score}</span>;
+          }
+        },
+        {
+          title: '音准',
+          key: 'intonation',
+          render(row: any) {
+            return <span>{row.intonation}</span>;
+          }
+        },
+        {
+          title: '节奏',
+          key: 'cadence',
+          render(row: any) {
+            return <span>{row.cadence}</span>;
+          }
+        },
+        {
+          title: '完整度',
+          key: 'integrity',
+          render(row: any) {
+            return <span>{row.integrity}</span>;
+          }
+        },
+        {
+          title: '操作',
+          key: 'id',
+          render(row: any) {
+            return (
+              <NButton
+                text
+                type="primary"
+                onClick={() => {
+                  gotoRecode(row);
+                }}>
+                评测报告
+              </NButton>
+            );
+          }
+        }
+      ];
+    };
+    const getList = async () => {
+      const res = await getPracticeRecordList({
+        userId: props.studentId,
+        ...state.pagination,
+        ...getTimes(timer.value, ['startTime', 'endTime'], 'YYYY-MM-DD')
+      });
+      state.tableList = res.data.trainingStatDetailList;
+      state.pagination.pageTotal = res.data.total;
+    };
+    const gotoRecode = (row: any) => {
+      console.log('gotoRecode');
+    };
+    const search = () => {
+      getList();
+    };
+    const onReset = () => {
+      timer.value = [
+        getNowDateAndMonday(new Date().getTime()),
+        getNowDateAndSunday(new Date().getTime())
+      ];
+      search();
+    };
+    onMounted(() => {
+      getList();
+      console.log(props.studentId);
+    });
+    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.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>
+      </>
+    );
+  }
+});

+ 121 - 80
src/views/studentList/components/practiceData.tsx

@@ -1,30 +1,43 @@
-import { Ref, defineComponent, reactive, ref } from 'vue';
+import { Ref, defineComponent, onMounted, reactive, ref } from 'vue';
 import styles from '../index.module.less';
-import { NButton, NDataTable, NNumberAnimation } from 'naive-ui';
+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',
-  setup() {
+  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%',
-      studentNum: 0,
-      paymentAmount: 0,
-      dateList: [
-        '2022-10-10',
-        '2022-10-11',
-        '2022-10-12',
-        '2022-10-13',
-        '2022-10-14',
-        '2022-10-15',
-        '2022-10-16'
-      ],
-      timeList: [90, 128, 242, 120, 186, 77, 148]
+      practiceDurationAvg: 0,
+      practiceDays: 0,
+      practiceDurationTotal: 0,
+      dateList: [],
+      timeList: []
     });
 
     const state = reactive({
@@ -34,73 +47,24 @@ export default defineComponent({
         rows: 10,
         pageTotal: 4
       },
-      tableList: [
-        {
-          teacherName: '孙忆枫',
-          createTime: '2023-06-27',
-          endTime: '2023-06-30',
-          status: 'ing',
-          studentNum: 100,
-          submitNum: 100,
-          quantityNum: 60,
-          submitRate: 100,
-          quantityRate: 60
-        },
-        {
-          teacherName: '孙忆枫',
-          createTime: '2023-06-27',
-          endTime: '2023-06-30',
-          status: 'ing',
-          studentNum: 100,
-          submitNum: 100,
-          quantityNum: 60,
-          submitRate: 100,
-          quantityRate: 60
-        },
-        {
-          teacherName: '孙忆枫',
-          createTime: '2023-06-27',
-          endTime: '2023-06-30',
-          status: 'ing',
-          studentNum: 100,
-          submitNum: 100,
-          quantityNum: 60,
-          submitRate: 100,
-          quantityRate: 60
-        },
-        {
-          teacherName: '孙忆枫',
-          createTime: '2023-06-25',
-          endTime: '2023-06-26',
-          status: 'end',
-          studentNum: 100,
-          submitNum: 100,
-          quantityNum: 60,
-          submitRate: 100,
-          quantityRate: 60
-        }
-      ] as any,
+      tableList: [] as any,
       goCourseVisiable: false
     });
+    const timer = ref<[number, number]>([
+      getNowDateAndMonday(new Date().getTime()),
+      getNowDateAndSunday(new Date().getTime())
+    ]);
     const columns = () => {
       return [
         {
           title: '日期',
-          key: 'createTime'
+          key: 'date'
         },
         {
-          title: '练习人数',
-          key: 'quantityNum',
+          title: '练习时长(分钟)',
+          key: 'practiceDuration',
           render(row: any) {
-            return <span>{row.quantityNum}人</span>;
-          }
-        },
-
-        {
-          title: '平均练习时长(分钟)',
-          key: 'submitNum',
-          render(row: any) {
-            return <span>{row.submitNum}分钟</span>;
+            return <span>{row.practiceDuration}分钟</span>;
           }
         }
       ];
@@ -113,7 +77,7 @@ export default defineComponent({
         tooltip: {
           trigger: 'axis',
           axisPointer: {
-            type: 'none'
+            type: 'shadow'
           }
         },
         legend: {
@@ -162,6 +126,7 @@ export default defineComponent({
             data: payForm.timeList,
             type: 'bar',
             barWidth: '48px',
+            stack: 'total',
             label: {
               // 柱图头部显示值
               show: true,
@@ -178,6 +143,7 @@ export default defineComponent({
                 color: '#D5E9FF'
               },
               emphasis: {
+                focus: 'series',
                 color: '#3583FA' //hover时改变柱子颜色
                 // borderWidth: 4,
                 // borderColor: 'rgba(213, 233, 255,.4)',
@@ -215,30 +181,105 @@ export default defineComponent({
         // ]
       });
     };
-    setChart();
+
+    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={32}></NNumberAnimation>
+                    <NNumberAnimation
+                      from={0}
+                      to={payForm.practiceDurationTotal}></NNumberAnimation>
                   </span>
                 </p>
-                <p class={styles.TrainDataItemsubTitle}>练习人数</p>
+                <p class={styles.TrainDataItemsubTitle}>累计练习时长</p>
               </div>
               <div class={styles.TrainDataItem}>
                 <p class={styles.TrainDataItemTitle}>
                   <span>
-                    <NNumberAnimation from={0} to={32}></NNumberAnimation>
+                    <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
@@ -270,14 +311,14 @@ export default defineComponent({
               loading={state.loading}
               columns={columns()}
               data={state.tableList}></NDataTable>
-            <Pagination
+            {/* <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>
       </>

+ 46 - 0
src/views/studentList/index.module.less

@@ -199,3 +199,49 @@
     }
   }
 }
+
+.tableWrap {
+  margin-top: 40px;
+
+  :global {
+    .n-data-table {
+      border-radius: 10px 10px 0 0;
+      overflow: hidden;
+    }
+
+    .n-data-table-thead {
+      height: 54px;
+      line-height: 54px;
+    }
+
+    .n-data-table-th {
+      padding: 0 20px;
+      background-color: #f7f7f8;
+      color: rgba(0, 0, 0, 0.88);
+    }
+
+    .n-data-table-th__title-wrapper {
+      &::after {
+        content: '';
+        width: 1px;
+        height: 22px;
+        background: #ebebeb;
+
+        &:nth-last-child(1) {
+          display: none;
+        }
+      }
+    }
+
+    .n-data-table-th--last {
+      .n-data-table-th__title-wrapper {
+        &::after {
+          content: '';
+          width: 0px;
+          height: 22px;
+          background: #ebebeb;
+        }
+      }
+    }
+  }
+}