Browse Source

Merge branch 'iteration-login'

liushengqiang 1 year ago
parent
commit
e9d69a370f

+ 23 - 0
src/views/data-module/api.tsx

@@ -8,3 +8,26 @@ export const getTrainingStat = (params: any) => {
     // requestType: 'form'
   });
 };
+
+
+export const getTrainingStatList = (params: any) => {
+  return request.post(`/edu-app/musicPracticeRecordStat/trainingList`, {
+    data: params
+  });
+};
+
+
+export const getTestStat = (params: any) => {
+  return request.post('/edu-app/musicPracticeRecordStat/trainingStat', {
+    data: params
+    // requestType: 'form'
+  });
+};
+
+
+export const getTrainingRanking = (params: any) => {
+  return request.post('/edu-app/musicPracticeRecordStat/trainingRanking', {
+    data: params
+    // requestType: 'form'
+  });
+}

+ 27 - 5
src/views/data-module/index.tsx

@@ -21,6 +21,9 @@ export default defineComponent({
         activeTab.value = val.form.tabName;
       }
     });
+    const TrainDataRef = ref();
+    const PracticeDataRef = ref();
+    const PracticeRankingRef = ref();
     const setTabs = (val: any) => {
       setTabsCaches(val, 'tabName', route);
     };
@@ -33,6 +36,18 @@ export default defineComponent({
       console.log('监听改变', value);
     };
 
+    const onSearch = () => {
+      console.log(timer.value);
+      if (TrainDataRef.value) {
+        TrainDataRef.value.getList();
+      }
+      if (PracticeDataRef.value) {
+        PracticeDataRef.value.getList();
+      }
+      if (PracticeRankingRef.value) {
+        PracticeRankingRef.value.getList();
+      }
+    };
     return () => (
       <div>
         <div class={styles.listWrap}>
@@ -50,11 +65,14 @@ export default defineComponent({
                   <div class={styles.homeStudyInfoDate}>
                     <NSpace>
                       <CDatePicker
+                         v-model:value={timer.value}
                         separator={'-'}
                         type="daterange"
-                        onUpdateValue={updaeTimer}
                         timerValue={timer.value}></CDatePicker>
-                      <NButton type="primary" class={styles.searchBtn}>
+                      <NButton
+                        type="primary"
+                        class={styles.searchBtn}
+                        onClick={() => onSearch()}>
                         搜索
                       </NButton>
                       <NButton type="primary" ghost class={styles.resetBtn}>
@@ -66,13 +84,17 @@ export default defineComponent({
               )
             }}>
             <NTabPane name="training " tab="训练统计">
-              <TrainData timer={timer.value}></TrainData>
+              <TrainData ref={TrainDataRef} timer={timer.value}></TrainData>
             </NTabPane>
             <NTabPane name="practice" tab="练习数据">
-              <PracticeData timer={timer.value}></PracticeData>
+              <PracticeData
+                ref={PracticeDataRef}
+                timer={timer.value}></PracticeData>
             </NTabPane>
             <NTabPane name="ranking" tab="练习排行">
-              <PracticeRanking timer={timer.value}></PracticeRanking>
+              <PracticeRanking
+                ref={PracticeRankingRef}
+                timer={timer.value}></PracticeRanking>
             </NTabPane>
           </NTabs>
         </div>

+ 123 - 63
src/views/home/components/practiceData.tsx

@@ -1,38 +1,35 @@
-import { Ref, defineComponent, onMounted, reactive, ref } from 'vue';
+import { Ref, computed, defineComponent, onMounted, reactive, ref } from 'vue';
 import styles from '../index.module.less';
 import { NButton, NDataTable, NNumberAnimation } from 'naive-ui';
 import numeral from 'numeral';
 import { useECharts } from '@/hooks/web/useECharts';
 import Pagination from '/src/components/pagination';
-import { getTrainingStat } from '@/views/data-module/api'
-import { getTimes } from '/src/utils/dateFormat';
+import { getTestStat } from '@/views/data-module/api';
+import { getMinutes, getSecend, getTimes } from '/src/utils/dateFormat';
+import { useRoute, useRouter } from 'vue-router';
+import { getTrainingStatList } from '../../classList/api';
 export default defineComponent({
   name: 'home-practiceData',
-  props:{
-    timer:{
-      type:Array,
-      defaut:()=>[]
+  props: {
+    timer: {
+      type: Array,
+      defaut: () => []
     }
   },
-  setup(props,{expose}) {
+  setup(props, { expose }) {
     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,
+      practiceUserCount: 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({
@@ -90,51 +87,92 @@ export default defineComponent({
       ] as any,
       goCourseVisiable: false
     });
+    const currentTimer = computed(() => {
+      return props.timer;
+    });
     const columns = () => {
       return [
         {
           title: '日期',
-          key: 'createTime'
-        },
-        {
-          title: '练习人数',
-          key: 'quantityNum',
-          render(row: any) {
-            return <span>{row.quantityNum}人</span>;
-          }
+          key: 'date'
         },
-
         {
           title: '平均练习时长(分钟)',
-          key: 'submitNum',
+          key: 'practiceDuration',
           render(row: any) {
-            return <span>{row.submitNum}分钟</span>;
+            return (
+              <>
+                {' '}
+                <>
+                  {row.practiceDuration
+                    ? getMinutes(row.practiceDuration) > 0
+                      ? getMinutes(row.practiceDuration) +
+                      '分' +
+                      getSecend(row.practiceDuration) +
+                      '秒'
+                      : getSecend(row.practiceDuration) + '秒'
+                    : 0 + '分钟'}
+                </>
+              </>
+            );
           }
         }
       ];
     };
     const getList = async () => {
-      try{
-        const res = await getTrainingStat({  ...getTimes(props.timer, ['startTime', 'endTime'], 'YYYY-MM-DD')})
+      try {
+        const res = await getTrainingStatList({
+          page: 1,
+          rows: 999,
+          ...getTimes(
+            currentTimer.value,
+            ['startTime', 'endTime'],
+            'YYYY-MM-DD'
+          )
+        });
+
+        const res2 = await getTestStat({
+          page: 1,
+          rows: 999,
+          ...getTimes(
+            currentTimer.value,
+            ['startTime', 'endTime'],
+            'YYYY-MM-DD'
+          )
+        });
+        state.tableList = res.data.rows;
+
+        payForm.practiceDurationAvg = res2.data.practiceDurationAvg;
+        payForm.practiceUserCount = res2.data.practiceUserCount;
+        payForm.dateList = res2.data.trainingStatDetailList.map((item: any) => {
+          return item.date;
+        });
 
-      }catch(e){
-        console.log(e)
+        payForm.timeList = res2.data.trainingStatDetailList.map((item: any) => {
+          return item.practiceDuration;
+        });
+
+        console.log('trainingStatDetailList', payForm.timeList);
+
+        setChart();
+      } catch (e) {
+        console.log(e);
       }
     };
-    expose({getList})
+    expose({ getList });
     const setChart = () => {
       setOptions({
         tooltip: {
           trigger: 'axis',
           axisPointer: {
-            type: 'none'
+            type: 'shadow'
           }
         },
         legend: {
           show: false,
           selected: {
             //在这里设置默认展示就ok了
-            '练习时长(分钟)': practiceFlag.value
+            '平均练习时长(分钟)': practiceFlag.value
           }
         },
         xAxis: {
@@ -176,14 +214,14 @@ export default defineComponent({
             data: payForm.timeList,
             type: 'bar',
             barWidth: '48px',
-            label: {
-              // 柱图头部显示值
-              show: true,
-              position: 'top',
-              color: '#333',
-              fontSize: '12px',
-              fontWeight: 600
-            },
+            // label: {
+            //   // 柱图头部显示值
+            //   show: true,
+            //   position: 'top',
+            //   color: '#333',
+            //   fontSize: '12px',
+            //   fontWeight: 600
+            // },
 
             itemStyle: {
               normal: {
@@ -205,15 +243,17 @@ export default defineComponent({
           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;
+              ...item.map((d: any) => {
+                let str;
+                getMinutes(d.value) > 0
+                  ? (str =
+                    getMinutes(d.value) + '分' + getSecend(d.value) + '秒')
+                  : (str = getSecend(d.value) + '秒');
+                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;">练习时长: ${d.value}${'分钟'} </span>`
-              )
+                  line-height: 18px;">平均练习时长: ${str} </span>`;
+              })
             ].join('');
           } else {
             return item;
@@ -229,10 +269,10 @@ export default defineComponent({
         // ]
       });
     };
-    onMounted(()=>{
-      getList()
-      setChart();
-    })
+
+    onMounted(() => {
+      getList();
+    });
 
     return () => (
       <>
@@ -242,7 +282,9 @@ export default defineComponent({
               <div class={styles.TrainDataItem}>
                 <p class={styles.TrainDataItemTitle}>
                   <span>
-                    <NNumberAnimation from={0} to={32}></NNumberAnimation>
+                    <NNumberAnimation
+                      from={0}
+                      to={payForm.practiceUserCount}></NNumberAnimation>
                   </span>
                 </p>
@@ -250,10 +292,28 @@ export default defineComponent({
               </div>
               <div class={styles.TrainDataItem}>
                 <p class={styles.TrainDataItemTitle}>
-                  <span>
-                    <NNumberAnimation from={0} to={32}></NNumberAnimation>
-                  </span>
-                  分钟
+                  {getMinutes(payForm.practiceDurationAvg) > 0 ? (
+                    <div>
+                      <span>
+                        <NNumberAnimation
+                          from={0}
+                          to={getMinutes(
+                            payForm.practiceDurationAvg
+                          )}></NNumberAnimation>
+                      </span>{' '}
+                      分
+                    </div>
+                  ) : null}
+                  <div>
+                    <span>
+                      <NNumberAnimation
+                        from={0}
+                        to={getSecend(
+                          payForm.practiceDurationAvg
+                        )}></NNumberAnimation>
+                    </span>{' '}
+                    秒
+                  </div>
                 </p>
                 <p class={styles.TrainDataItemsubTitle}>平均练习时长</p>
               </div>
@@ -288,14 +348,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>
       </>

+ 92 - 59
src/views/home/components/practiceRanking.tsx

@@ -13,15 +13,17 @@ import SearchInput from '@/components/searchInput';
 import CSelect from '@/components/CSelect';
 import Pagination from '@/components/pagination';
 import add from './images/add.png';
+import { getMinutes, getSecend, getTimes } from '/src/utils/dateFormat';
+import { getTestList } from '../../classList/api';
 export default defineComponent({
   name: 'student-studentList',
-  props:{
-    timer:{
-      type:Array,
-      defaut:()=>[]
+  props: {
+    timer: {
+      type: Array,
+      defaut: () => []
     }
   },
-  setup(props, { emit,expose }) {
+  setup(props, { emit, expose }) {
     const state = reactive({
       searchWord: '',
       orchestraType: null,
@@ -35,36 +37,7 @@ export default defineComponent({
         rows: 10,
         pageTotal: 4
       },
-      tableList: [
-        {
-          studentName: '胡小小',
-          phone: '17625367893',
-          trainNum: '49',
-          trainDay: '9',
-          averageNum: '35'
-        },
-        {
-          studentName: '丁曼蓉',
-          phone: '14677789334',
-          trainNum: '49',
-          trainDay: '9',
-          averageNum: '35'
-        },
-        {
-          studentName: '李书意',
-          phone: '13467857893',
-          trainNum: '49',
-          trainDay: '9',
-          averageNum: '35'
-        },
-        {
-          studentName: '夏小满',
-          phone: '13925367893',
-          trainNum: '49',
-          trainDay: '9',
-          averageNum: '35'
-        }
-      ] as any
+      tableList: [] as any
     });
     const search = () => {
       console.log('search', state);
@@ -73,10 +46,84 @@ export default defineComponent({
     const onReset = () => {
       console.log('search');
     };
-    const getList = () => {
-      console.log('getList');
+    const getList = async () => {
+      state.loading = true;
+      try {
+        const res = await getTestList({
+          ...state.pagination,
+          ...getTimes(props.timer, ['startTime', 'endTime'], 'YYYY-MM-DD')
+        });
+
+        state.tableList = res.data.rows;
+
+        state.pagination.pageTotal = res.data.total;
+        state.loading = false;
+      } catch (e) {
+        state.loading = false;
+        console.log(e);
+      }
+    };
+    expose({ getList });
+    const handleSorterChange = (sroter: any) => {
+      if(!sroter){
+        practiceDaysRef.sortOrder = false
+        practiceDurationRef.sortOrder = false
+        practiceDurationAvgRef.sortOrder = false
+      }
+      console.log(sroter, 'sroter');
+      // getList()
     };
-    expose({getList})
+
+    const practiceDaysRef = reactive({
+      title: '练习天数',
+      key: 'practiceDays',
+      sorter: true,
+      sortOrder: false,
+      render(row: any) {
+        return <>{row.practiceDays ? row.practiceDays : 0}天</>;
+      }
+    });
+    const practiceDurationRef = reactive({
+      title: '练习总时长',
+      key: 'practiceDuration',
+      sorter: true,
+      sortOrder: false,
+      render(row: any) {
+        return (
+          <>
+            {row.practiceDuration
+              ? getMinutes(row.practiceDuration) > 0
+                ? getMinutes(row.practiceDuration) +
+                  '分' +
+                  getSecend(row.practiceDuration) +
+                  '秒'
+                : getSecend(row.practiceDuration) + '秒'
+              : 0}
+          </>
+        );
+      }
+    });
+    const practiceDurationAvgRef = reactive({
+      title: '平均练习时长',
+      key: 'practiceDurationAvg',
+      sorter: true,
+      sortOrder: false,
+      render(row: any) {
+        return (
+          <>
+            {row.practiceDurationAvg
+              ? getMinutes(row.practiceDurationAvg) > 0
+                ? getMinutes(row.practiceDurationAvg) +
+                  '分' +
+                  getSecend(row.practiceDurationAvg) +
+                  '秒'
+                : getSecend(row.practiceDurationAvg) + '秒'
+              : 0}
+          </>
+        );
+      }
+    });
+
     const columns = () => {
       return [
         {
@@ -84,27 +131,12 @@ export default defineComponent({
           key: 'studentName'
         },
         {
-          title: '练习天数',
-          key: 'trainDay',
-          render(row: any) {
-            return <span>{row.trainDay}天</span>;
-          }
+          title: '手机号',
+          key: 'studentPhone'
         },
-        {
-          title: '练习总时长',
-          key: 'trainNum',
-          render(row: any) {
-            return <span>{row.trainNum}分钟</span>;
-          }
-        },
-
-        {
-          title: '平均练习时长',
-          key: 'averageNum',
-          render(row: any) {
-            return <span>{row.averageNum}分钟</span>;
-          }
-        }
+        practiceDaysRef,
+        practiceDurationRef,
+        practiceDurationAvgRef
       ];
     };
     return () => (
@@ -114,7 +146,8 @@ export default defineComponent({
             class={styles.classTable}
             loading={state.loading}
             columns={columns()}
-            data={state.tableList}></NDataTable>
+            data={state.tableList}
+            onUpdate:sorter={handleSorterChange}></NDataTable>
           <Pagination
             v-model:page={state.pagination.page}
             v-model:pageSize={state.pagination.rows}

+ 125 - 31
src/views/home/components/trainData.tsx

@@ -1,11 +1,15 @@
-import { Ref, defineComponent, onMounted, reactive, ref } from 'vue';
+import { Ref, computed, defineComponent, onMounted, reactive, ref,watch } from 'vue';
 import styles from '../index.module.less';
-import { NButton, NDataTable, NNumberAnimation } from 'naive-ui';
+import { NButton, NDataTable, NNumberAnimation, NSpace } from 'naive-ui';
 import numeral from 'numeral';
 import { useECharts } from '@/hooks/web/useECharts';
 import Pagination from '/src/components/pagination';
 import { getTimes } from '/src/utils/dateFormat';
 import { getTrainingStat } from '../../data-module/api';
+import { useRoute, useRouter } from 'vue-router';
+import { getTrainingList } from '../../classList/api';
+import dayjs from 'dayjs';
+
 export default defineComponent({
   name: 'home-trainData',
   props: {
@@ -19,6 +23,8 @@ export default defineComponent({
     const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
     const qualifiedFlag = ref(true);
     const unqualifiedFlag = ref(true);
+    const router = useRouter();
+    const route = useRoute()
     const payForm = reactive({
       height: '360px',
       width: '100%',
@@ -33,16 +39,16 @@ export default defineComponent({
         '2022-10-15',
         '2022-10-16'
       ],
-      studentList: [50, 100, 80, 180, 70, 99, 300],
-      payInfoList: [100, 200, 300, 450, 330, 200, 10]
+      studentList: [],
+      payInfoList: []
     });
     const totalDateRef = ref({
-      qualifiedRate: 9,
-      qualifiedStudentCount: 1,
-      submitStudentCount: 3,
-      totalStudentCount: 11,
-      trainingCount: 4,
-      trainingRate: 27, //
+      qualifiedRate: 0,
+      qualifiedStudentCount: 0,
+      submitStudentCount: 0,
+      totalStudentCount: 0,
+      trainingCount: 0,
+      trainingRate: 0 //
     } as any);
     const state = reactive({
       loading: false,
@@ -99,6 +105,12 @@ export default defineComponent({
       ] as any,
       goCourseVisiable: false
     });
+
+
+    const currentTimer = computed(()=>{
+
+      return props.timer
+    })
     const columns = () => {
       return [
         {
@@ -107,17 +119,23 @@ export default defineComponent({
         },
         {
           title: '布置时间',
-          key: 'createTime'
+          key: 'createTime',
+          render(row: any) {
+            return <>{row.createTime}</>;
+          }
         },
         {
           title: '截止时间',
-          key: 'endTime'
+          key: 'expireDate',
+          render(row: any) {
+            return <>{row.expireDate}</>;
+          }
         },
         {
           title: '训练状态',
           key: 'status',
           render(row: any) {
-            return row.status == 'ing' ? (
+            return row.status == 0 ? (
               <div class={styles.indDot}>
                 {' '}
                 <span></span> 进行中
@@ -131,51 +149,107 @@ export default defineComponent({
         },
         {
           title: '布置人数',
-          key: 'studentNum'
+          key: 'expectNum'
         },
         {
           title: '提交人数',
-          key: 'submitNum'
+          key: 'trainingNum'
         },
         {
           title: '合格人数',
-          key: 'quantityNum'
+          key: 'standardNum'
         },
         {
           title: '提交率',
-          key: 'submitRate',
+          key: 'trainingRate',
           render(row: any) {
-            return <span>{row.submitRate}%</span>;
+            return <>{row.trainingRate}%</>;
           }
         },
         {
           title: '合格率',
-          key: 'quantityRate',
+          key: 'qualifiedRate',
           render(row: any) {
-            return <span>{row.quantityRate}%</span>;
+            return <>{row.qualifiedRate}%</>;
           }
         },
+        // {
+        //   title: '',
+        //   key: 'sex',
+        //   render(row: any) {
+        //     return <>{row.sex == '0' ? '女' : '男'}</>;
+        //   }
+        // },
         {
           title: '操作',
           key: 'id',
           render(row: any) {
             return (
-              <NButton text type="primary">
-                详情
-              </NButton>
+              <NSpace>
+                <NButton
+                  text
+                  type="primary"
+                  onClick={() => gotoWorkDetail(row)}>
+                  详情
+                </NButton>
+              </NSpace>
             );
           }
         }
       ];
     };
+    const gotoWorkDetail = (row: any) => {
+      console.log(row);
+      router.push({
+        path: '/afterWorkDetail',
+        query: {
+          ...route.query,
+          teacherName: row.teacherName,
+          trainingId: row.id,
+          id:row.classGroupId,
+          name:row.classGroupName
+        }
+      });
+    };
     const getList = async () => {
       try {
         const res = await getTrainingStat({
-          ...getTimes(props.timer, ['startTime', 'endTime'], 'YYYY-MM-DD')
+          ...getTimes(currentTimer.value, ['startTime', 'endTime'], 'YYYY-MM-DD')
         });
+        totalDateRef.value = {...res.data}
+        payForm.dateList = res.data.trainingStatDetails.map((item:any)=>{
+          return item.date
+        })
+        payForm.payInfoList = res.data.trainingStatDetails.map((item:any)=>{
+          return item.qualifiedStudentCount
+        })
+        payForm.studentList = res.data.trainingStatDetails.map((item:any)=>{
+          return item.unqualifiedStudentCount
+        })
+
+        setChart();
       } catch (e) {
         console.log(e);
       }
+
+      try {
+        const res = await getTrainingList({
+          ...state.pagination,
+          ...getTimes(
+            currentTimer.value,
+            ['startTime', 'endTime'],
+            'YYYY-MM-DD'
+          )
+        });
+
+        state.tableList = res.data.rows;
+
+        state.pagination.pageTotal = res.data.total;
+        state.loading = false;
+      } catch (e) {
+        state.loading = false;
+        console.log(e);
+      }
     };
     expose({ getList });
     const setChart = () => {
@@ -355,7 +429,7 @@ export default defineComponent({
     };
     onMounted(() => {
       getList();
-      setChart();
+
     });
 
     return () => (
@@ -366,7 +440,9 @@ export default defineComponent({
               <div class={styles.TrainDataItem}>
                 <p class={styles.TrainDataItemTitle}>
                   <span>
-                    <NNumberAnimation from={0} to={totalDateRef.value.trainingCount}></NNumberAnimation>
+                    <NNumberAnimation
+                      from={0}
+                      to={totalDateRef.value.trainingCount}></NNumberAnimation>
                   </span>
                 </p>
@@ -375,7 +451,11 @@ export default defineComponent({
               <div class={styles.TrainDataItem}>
                 <p class={styles.TrainDataItemTitle}>
                   <span>
-                    <NNumberAnimation from={0} to={totalDateRef.value.totalStudentCount}></NNumberAnimation>
+                    <NNumberAnimation
+                      from={0}
+                      to={
+                        totalDateRef.value.totalStudentCount
+                      }></NNumberAnimation>
                   </span>
                   人次
                 </p>
@@ -384,7 +464,11 @@ export default defineComponent({
               <div class={styles.TrainDataItem}>
                 <p class={styles.TrainDataItemTitle}>
                   <span>
-                    <NNumberAnimation from={0} to={totalDateRef.value.submitStudentCount}></NNumberAnimation>
+                    <NNumberAnimation
+                      from={0}
+                      to={
+                        totalDateRef.value.submitStudentCount
+                      }></NNumberAnimation>
                   </span>
                   人次
                 </p>
@@ -394,7 +478,11 @@ export default defineComponent({
                 <p class={styles.TrainDataItemTitle}>
                   <span>
                     {' '}
-                    <NNumberAnimation from={0} to={totalDateRef.value.qualifiedStudentCount}></NNumberAnimation>
+                    <NNumberAnimation
+                      from={0}
+                      to={
+                        totalDateRef.value.qualifiedStudentCount
+                      }></NNumberAnimation>
                   </span>
                   人次
                 </p>
@@ -403,7 +491,10 @@ export default defineComponent({
               <div class={styles.TrainDataItem}>
                 <p class={styles.TrainDataItemTitle}>
                   <span>
-                    <NNumberAnimation from={0} to={totalDateRef.value.trainingRate}></NNumberAnimation>%
+                    <NNumberAnimation
+                      from={0}
+                      to={totalDateRef.value.trainingRate}></NNumberAnimation>
+                    %
                   </span>
                 </p>
                 <p class={styles.TrainDataItemsubTitle}>训练提交率</p>
@@ -411,7 +502,10 @@ export default defineComponent({
               <div class={styles.TrainDataItem}>
                 <p class={styles.TrainDataItemTitle}>
                   <span>
-                    <NNumberAnimation from={0} to={totalDateRef.value.qualifiedRate}></NNumberAnimation>%
+                    <NNumberAnimation
+                      from={0}
+                      to={totalDateRef.value.qualifiedRate}></NNumberAnimation>
+                    %
                   </span>
                 </p>
                 <p class={styles.TrainDataItemsubTitle}>训练合格率</p>

+ 7 - 0
src/views/home/index.module.less

@@ -453,6 +453,9 @@
         margin-right: 40px;
 
         .TrainDataItemTitle {
+          display: flex;
+          flex-direction: row;
+          align-items: center;
           text-align: center;
           font-size: 13px;
           font-weight: 400;
@@ -787,4 +790,8 @@
       }
     }
   }
+}
+
+.tableWrap {
+  margin-top: 40px;
 }