|  | @@ -5,7 +5,7 @@ import iconArrow11 from '../images/icon-arrow1-1.png'
 | 
	
		
			
				|  |  |  import icon1 from '../images/icon-1.png'
 | 
	
		
			
				|  |  |  import icon2 from '../images/icon-2.png'
 | 
	
		
			
				|  |  |  import iconDownload from '../images/icon-download.png'
 | 
	
		
			
				|  |  | -import { Button, DatetimePicker, Popup } from 'vant'
 | 
	
		
			
				|  |  | +import { Button, DatetimePicker, Icon, Popup } from 'vant'
 | 
	
		
			
				|  |  |  import Echats from './echats'
 | 
	
		
			
				|  |  |  import ColHeader from '@/components/col-header'
 | 
	
		
			
				|  |  |  import TheSticky from '@/components/the-sticky'
 | 
	
	
		
			
				|  | @@ -15,6 +15,7 @@ import request from '@/helpers/request'
 | 
	
		
			
				|  |  |  import { getTimeRange, TIME_TYPE } from '../home-statistics'
 | 
	
		
			
				|  |  |  import ColResult from '@/components/col-result'
 | 
	
		
			
				|  |  |  import { promisefiyPostMessage } from '@/helpers/native-message'
 | 
	
		
			
				|  |  | +import { useRouter } from 'vue-router'
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /** 秒转分 */
 | 
	
		
			
				|  |  |  export const formatSecToMin = (second: number) => {
 | 
	
	
		
			
				|  | @@ -47,6 +48,7 @@ export const formatSecToHMS = second => {
 | 
	
		
			
				|  |  |  export default defineComponent({
 | 
	
		
			
				|  |  |    name: 'PracticeDetail',
 | 
	
		
			
				|  |  |    setup() {
 | 
	
		
			
				|  |  | +    const router = useRouter()
 | 
	
		
			
				|  |  |      const searchStatus = ref(false)
 | 
	
		
			
				|  |  |      const currentType = ref<TIME_TYPE>('MONTH')
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -67,7 +69,9 @@ export default defineComponent({
 | 
	
		
			
				|  |  |        startTime: new Date(timeRange?.startTime || ''),
 | 
	
		
			
				|  |  |        startTimeStr: timeRange?.startTime || '',
 | 
	
		
			
				|  |  |        endTime: new Date(timeRange?.endTime || ''),
 | 
	
		
			
				|  |  | -      endTimeStr: timeRange?.endTime || ''
 | 
	
		
			
				|  |  | +      endTimeStr: timeRange?.endTime || '',
 | 
	
		
			
				|  |  | +      sortField: '' as 'totalPracticeTime' | 'averagePracticeTime' | '', // 排序字段
 | 
	
		
			
				|  |  | +      sortType: '' as 'ASC' | 'DESC' | '' // 排序方式 ,ASC升序,DESC降序
 | 
	
		
			
				|  |  |      })
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      // 练习统计
 | 
	
	
		
			
				|  | @@ -107,7 +111,16 @@ export default defineComponent({
 | 
	
		
			
				|  |  |      const onExport = async () => {
 | 
	
		
			
				|  |  |        try {
 | 
	
		
			
				|  |  |          const { data } = await request.post(
 | 
	
		
			
				|  |  | -          '/api-teacher/home/exportStudentPractice'
 | 
	
		
			
				|  |  | +          '/api-teacher/home/exportStudentPractice',
 | 
	
		
			
				|  |  | +          {
 | 
	
		
			
				|  |  | +            data: {
 | 
	
		
			
				|  |  | +              startTime: forms.startTimeStr,
 | 
	
		
			
				|  |  | +              endTime: forms.endTimeStr,
 | 
	
		
			
				|  |  | +              subjectId: forms.subjectId,
 | 
	
		
			
				|  |  | +              sortField: forms.sortField,
 | 
	
		
			
				|  |  | +              sortType: forms.sortType // 排序方式 ,ASC升序,DESC降序
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  |          )
 | 
	
		
			
				|  |  |          console.log(data, 'data')
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -175,10 +188,30 @@ export default defineComponent({
 | 
	
		
			
				|  |  |          obj.value.yAxisDataTime = practiceTimeList
 | 
	
		
			
				|  |  |          obj.value.xAxisDataCount = xAxisDataCounts
 | 
	
		
			
				|  |  |          obj.value.yAxisDataCount = countList
 | 
	
		
			
				|  |  | +      } catch {
 | 
	
		
			
				|  |  | +        //
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      forms.loading = false
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    // 用户列表数据
 | 
	
		
			
				|  |  | +    const getStudentDetail = async () => {
 | 
	
		
			
				|  |  | +      try {
 | 
	
		
			
				|  |  | +        const { data } = await request.post(
 | 
	
		
			
				|  |  | +          '/api-teacher/home/studentPractice',
 | 
	
		
			
				|  |  | +          {
 | 
	
		
			
				|  |  | +            data: {
 | 
	
		
			
				|  |  | +              startTime: forms.startTimeStr,
 | 
	
		
			
				|  |  | +              endTime: forms.endTimeStr,
 | 
	
		
			
				|  |  | +              subjectId: forms.subjectId,
 | 
	
		
			
				|  |  | +              sortField: forms.sortField,
 | 
	
		
			
				|  |  | +              sortType: forms.sortType
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +        )
 | 
	
		
			
				|  |  |          // 学员练习时长
 | 
	
		
			
				|  |  | -        const studentPracticeSummary = data.studentPracticeSummary || []
 | 
	
		
			
				|  |  | -        let tempStudents: any = []
 | 
	
		
			
				|  |  | +        const studentPracticeSummary = data || []
 | 
	
		
			
				|  |  | +        const tempStudents: any = []
 | 
	
		
			
				|  |  |          studentPracticeSummary.forEach((item: any) => {
 | 
	
		
			
				|  |  |            const student = {
 | 
	
		
			
				|  |  |              avatar: item.avatar,
 | 
	
	
		
			
				|  | @@ -186,17 +219,16 @@ export default defineComponent({
 | 
	
		
			
				|  |  |              practiceDays: item.practiceDays || 0,
 | 
	
		
			
				|  |  |              studentName: item.studentName,
 | 
	
		
			
				|  |  |              subjectName: item.subjectName,
 | 
	
		
			
				|  |  | -            totalPracticeTime: formatSecToHMS(item.totalPracticeTime || 0)
 | 
	
		
			
				|  |  | +            totalPracticeTime: formatSecToHMS(item.totalPracticeTime || 0),
 | 
	
		
			
				|  |  | +            userId: item.userId
 | 
	
		
			
				|  |  |            }
 | 
	
		
			
				|  |  | -          tempStudents = student
 | 
	
		
			
				|  |  | +          tempStudents.push(student)
 | 
	
		
			
				|  |  |          })
 | 
	
		
			
				|  |  |          obj.value.students = tempStudents
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |          forms.dataShow = tempStudents.length > 0 ? true : false
 | 
	
		
			
				|  |  |        } catch {
 | 
	
		
			
				|  |  |          //
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | -      forms.loading = false
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      const getSubjectList = async () => {
 | 
	
	
		
			
				|  | @@ -217,6 +249,7 @@ export default defineComponent({
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      getSubjectList()
 | 
	
		
			
				|  |  |      getDetail()
 | 
	
		
			
				|  |  | +    getStudentDetail()
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      const onChangeTime = (type: TIME_TYPE) => {
 | 
	
		
			
				|  |  |        if (searchObj.type === type) return
 | 
	
	
		
			
				|  | @@ -245,6 +278,38 @@ export default defineComponent({
 | 
	
		
			
				|  |  |        forms.subjectId = searchObj.tempSubjectId
 | 
	
		
			
				|  |  |        getDetail()
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /** 排序 */
 | 
	
		
			
				|  |  | +    const onSort = (
 | 
	
		
			
				|  |  | +      field: 'totalPracticeTime' | 'averagePracticeTime' | ''
 | 
	
		
			
				|  |  | +    ) => {
 | 
	
		
			
				|  |  | +      console.log(field, 'field')
 | 
	
		
			
				|  |  | +      if (!field) return
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      if (forms.sortField !== field) {
 | 
	
		
			
				|  |  | +        forms.sortType = ''
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      forms.sortField = field
 | 
	
		
			
				|  |  | +      if (forms.sortType === 'ASC') {
 | 
	
		
			
				|  |  | +        forms.sortType = ''
 | 
	
		
			
				|  |  | +      } else if (forms.sortType === 'DESC') {
 | 
	
		
			
				|  |  | +        forms.sortType = 'ASC'
 | 
	
		
			
				|  |  | +      } else {
 | 
	
		
			
				|  |  | +        forms.sortType = 'DESC'
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      getStudentDetail()
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /** 跳转详情 */
 | 
	
		
			
				|  |  | +    const toDetail = (item: any) => {
 | 
	
		
			
				|  |  | +      router.push({
 | 
	
		
			
				|  |  | +        path: '/exercise-detail',
 | 
	
		
			
				|  |  | +        query: {
 | 
	
		
			
				|  |  | +          studentId: item.userId || '',
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      })
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |      return () => (
 | 
	
		
			
				|  |  |        <div class={styles.practiceDetail}>
 | 
	
		
			
				|  |  |          <TheSticky position="top">
 | 
	
	
		
			
				|  | @@ -359,17 +424,79 @@ export default defineComponent({
 | 
	
		
			
				|  |  |                        <th class={styles.tdFixedLeft}>学员</th>
 | 
	
		
			
				|  |  |                        <th>乐器</th>
 | 
	
		
			
				|  |  |                        <th>
 | 
	
		
			
				|  |  | -                        <div>练习时长</div>
 | 
	
		
			
				|  |  | -                        {/* <div class={styles.filters}>
 | 
	
		
			
				|  |  | -                    </div> */}
 | 
	
		
			
				|  |  | +                        <div
 | 
	
		
			
				|  |  | +                          class={styles.filterSection}
 | 
	
		
			
				|  |  | +                          onClick={() => onSort('totalPracticeTime')}
 | 
	
		
			
				|  |  | +                        >
 | 
	
		
			
				|  |  | +                          练习时长
 | 
	
		
			
				|  |  | +                          <div class={styles.filters}>
 | 
	
		
			
				|  |  | +                            <Icon
 | 
	
		
			
				|  |  | +                              classPrefix="iconfont"
 | 
	
		
			
				|  |  | +                              name="down"
 | 
	
		
			
				|  |  | +                              class={styles.upArrow}
 | 
	
		
			
				|  |  | +                              size={12}
 | 
	
		
			
				|  |  | +                              color={
 | 
	
		
			
				|  |  | +                                forms.sortField === 'totalPracticeTime' &&
 | 
	
		
			
				|  |  | +                                forms.sortType === 'ASC'
 | 
	
		
			
				|  |  | +                                  ? 'rgba(223, 128, 16, 1)'
 | 
	
		
			
				|  |  | +                                  : 'rgba(0, 0, 0, 0.20)'
 | 
	
		
			
				|  |  | +                              }
 | 
	
		
			
				|  |  | +                            />
 | 
	
		
			
				|  |  | +                            <Icon
 | 
	
		
			
				|  |  | +                              classPrefix="iconfont"
 | 
	
		
			
				|  |  | +                              name="down"
 | 
	
		
			
				|  |  | +                              class={styles.downArrow}
 | 
	
		
			
				|  |  | +                              size={12}
 | 
	
		
			
				|  |  | +                              color={
 | 
	
		
			
				|  |  | +                                forms.sortField === 'totalPracticeTime' &&
 | 
	
		
			
				|  |  | +                                forms.sortType === 'DESC'
 | 
	
		
			
				|  |  | +                                  ? 'rgba(223, 128, 16, 1)'
 | 
	
		
			
				|  |  | +                                  : 'rgba(0, 0, 0, 0.20)'
 | 
	
		
			
				|  |  | +                              }
 | 
	
		
			
				|  |  | +                            />
 | 
	
		
			
				|  |  | +                          </div>
 | 
	
		
			
				|  |  | +                        </div>
 | 
	
		
			
				|  |  |                        </th>
 | 
	
		
			
				|  |  |                        <th>练习天数</th>
 | 
	
		
			
				|  |  | -                      <th>平均练习时长</th>
 | 
	
		
			
				|  |  | +                      <th>
 | 
	
		
			
				|  |  | +                        <div
 | 
	
		
			
				|  |  | +                          class={styles.filterSection}
 | 
	
		
			
				|  |  | +                          onClick={() => onSort('averagePracticeTime')}
 | 
	
		
			
				|  |  | +                        >
 | 
	
		
			
				|  |  | +                          平均练习时长
 | 
	
		
			
				|  |  | +                          <div class={styles.filters}>
 | 
	
		
			
				|  |  | +                            <Icon
 | 
	
		
			
				|  |  | +                              classPrefix="iconfont"
 | 
	
		
			
				|  |  | +                              name="down"
 | 
	
		
			
				|  |  | +                              class={styles.upArrow}
 | 
	
		
			
				|  |  | +                              size={12}
 | 
	
		
			
				|  |  | +                              color={
 | 
	
		
			
				|  |  | +                                forms.sortField === 'averagePracticeTime' &&
 | 
	
		
			
				|  |  | +                                forms.sortType === 'ASC'
 | 
	
		
			
				|  |  | +                                  ? 'rgba(223, 128, 16, 1)'
 | 
	
		
			
				|  |  | +                                  : 'rgba(0, 0, 0, 0.20)'
 | 
	
		
			
				|  |  | +                              }
 | 
	
		
			
				|  |  | +                            />
 | 
	
		
			
				|  |  | +                            <Icon
 | 
	
		
			
				|  |  | +                              classPrefix="iconfont"
 | 
	
		
			
				|  |  | +                              name="down"
 | 
	
		
			
				|  |  | +                              class={styles.downArrow}
 | 
	
		
			
				|  |  | +                              size={12}
 | 
	
		
			
				|  |  | +                              color={
 | 
	
		
			
				|  |  | +                                forms.sortField === 'averagePracticeTime' &&
 | 
	
		
			
				|  |  | +                                forms.sortType === 'DESC'
 | 
	
		
			
				|  |  | +                                  ? 'rgba(223, 128, 16, 1)'
 | 
	
		
			
				|  |  | +                                  : 'rgba(0, 0, 0, 0.20)'
 | 
	
		
			
				|  |  | +                              }
 | 
	
		
			
				|  |  | +                            />
 | 
	
		
			
				|  |  | +                          </div>
 | 
	
		
			
				|  |  | +                        </div>
 | 
	
		
			
				|  |  | +                      </th>
 | 
	
		
			
				|  |  |                      </tr>
 | 
	
		
			
				|  |  |                    </thead>
 | 
	
		
			
				|  |  |                    <tbody>
 | 
	
		
			
				|  |  |                      {obj.value.students.map((item: any) => (
 | 
	
		
			
				|  |  | -                      <tr>
 | 
	
		
			
				|  |  | +                      <tr onClick={() => toDetail(item)}>
 | 
	
		
			
				|  |  |                          <td class={styles.tdFixedLeft}>
 | 
	
		
			
				|  |  |                            <img class={styles.userImg} src={item.avatar} />
 | 
	
		
			
				|  |  |                            <span>{item.studentName}</span>
 |