浏览代码

添加搜索条件

lex-xin 3 月之前
父节点
当前提交
264922403e

+ 16 - 1
src/helpers/hooks.ts

@@ -1,6 +1,7 @@
 import { reactive } from 'vue'
 import { postMessage } from './native-message'
 import request from './request'
+import { browser } from './utils'
 
 // 搜索关键字
 export const SubjectEnum = {
@@ -27,7 +28,7 @@ export const useSubjectId = (
     let subject = localStorage.getItem(key)
     subject = subject ? JSON.parse(subject) : { name: '', id: '' }
     return subject
-  } else if(type === "remove") {
+  } else if (type === 'remove') {
     localStorage.removeItem(key)
   } else {
     localStorage.setItem(key, value)
@@ -135,3 +136,17 @@ export const useEventTracking = (name: eventName) => {
     }
   })
 }
+
+/**
+ * 学生端 - 埋点统计
+ * @param params { objectType: string, objectId: number}
+ */
+export const useStatisticTracking = (params: {
+  objectType: 'VIP_COURSE' | 'PRACTICE' | 'GROUP' | 'LIVE' | 'VIDEO' | 'MUSIC'
+  objectId: number | string
+}) => {
+  request.post('/api-student/exposure/record', {
+    hideLoading: false,
+    data: [{ ...params, platform: browser().ios ? 'ios' : 'android' }]
+  })
+}

+ 7 - 0
src/student/group-class/group-detail.tsx

@@ -20,6 +20,7 @@ import { tradeOrder } from '../trade/tradeOrder'
 import { courseType } from '@/constant'
 import GroupPlanStep from '@/business-components/group-plan-step'
 import TheSticky from '@/components/the-sticky'
+import { useStatisticTracking } from '@/helpers/hooks'
 interface IProps {
   courseTime: string
   coursePlan: string
@@ -131,6 +132,12 @@ export default defineComponent({
     } else {
       this.shareUrl = `${location.origin}/teacher/#/shareGroup?recomUserId=${state.user.data?.userId}&groupId=${this.groupId}&userType=${state.platformType}&p=tenant`
     }
+
+    /** 埋点 */
+    useStatisticTracking({
+      objectType: "GROUP",
+      objectId: this.groupId as any
+    })
   },
   methods: {
     async _init() {

+ 147 - 7
src/teacher/statistics/home-statistics-detail/echats/index.module.less

@@ -1,4 +1,3 @@
-
 .homeHead {
   display: flex;
   justify-content: space-between;
@@ -18,7 +17,7 @@
       margin-right: 6px;
     }
   }
-  
+
   .right {
     display: flex;
     align-items: center;
@@ -38,7 +37,7 @@
     }
 
     &.showItemActive {
-      color: #2DC7AA;
+      color: #2dc7aa;
     }
   }
 }
@@ -52,7 +51,7 @@
   .eChartTitle {
     display: flex;
     justify-content: space-between;
-    background: #F8F8F8;
+    background: #f8f8f8;
     border-radius: 4px;
     padding: 6px 12px;
 
@@ -65,7 +64,7 @@
       display: flex;
       align-items: center;
       margin-right: 12px;
-      --color: #2DC7AA;
+      --color: #2dc7aa;
 
       &:last-child {
         margin-right: 0;
@@ -77,7 +76,6 @@
         height: 3px;
         background: var(--color);
         border-radius: 3px;
-
       }
 
       .text {
@@ -100,4 +98,146 @@
     height: 240px;
     padding: 0;
   }
-}
+}
+
+.popupContainer {
+  // max-height: 504px;
+  // overflow-x: hidden;
+  // overflow-y: auto;
+  .popupTitle {
+    position: sticky;
+    z-index: 1;
+    top: 0;
+    text-align: center;
+    font-weight: 600;
+    font-size: 18px;
+    color: #333333;
+    line-height: 24px;
+    padding: 18px 0 12px;
+  }
+
+  // .popupSearchList {
+  // min-height: 30vh;
+  // max-height: 50vh;
+  // overflow: hidden auto;
+  // }
+
+  .popupSection {
+    padding: 0 16px 18px;
+    .title {
+      display: flex;
+      justify-content: space-between;
+      padding-bottom: 10px;
+      span {
+        display: flex;
+        align-items: center;
+        font-weight: 600;
+        font-size: 15px;
+        color: #333333;
+        line-height: 18px;
+        &::before {
+          content: '';
+          display: inline-block;
+          width: 3px;
+          height: 12px;
+          background: linear-gradient(180deg, #59e5d4 0%, #2dc7aa 100%);
+          border-radius: 2px;
+          margin-right: 4px;
+        }
+      }
+    }
+
+    .timeCount {
+      display: flex;
+      align-items: center;
+
+      p {
+        margin-left: 10px;
+        flex: 1;
+        background: #f8f8f8;
+        border: 1px solid #f8f8f8;
+        border-radius: 4px;
+        font-size: 13px;
+        color: #999999;
+        line-height: 18px;
+        text-align: center;
+        padding: 6px 0;
+        &:first-child {
+          margin-left: 0;
+        }
+
+        &.active {
+          background: #e9fff8;
+          border-radius: 4px;
+          border: 1px solid #2dc7aa;
+          color: #2dc7aa;
+        }
+      }
+    }
+
+    .timeSubject {
+      flex-wrap: wrap;
+      margin-left: -5px;
+      margin-right: -5px;
+      p {
+        width: calc(33.333% - 10px);
+        padding: 6px 3px;
+        margin: 0 5px;
+        flex: none;
+        overflow: hidden;
+        white-space: nowrap;
+        text-overflow: ellipsis;
+        margin-bottom: 9px;
+        box-sizing: border-box;
+        &:first-child {
+          margin-left: 5px;
+        }
+      }
+    }
+
+    .timeRang {
+      margin-top: 10px;
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+
+      .timeInput {
+        width: 159px;
+        line-height: 32px;
+        text-align: center;
+        background: #f8f8f8;
+        border-radius: 4px;
+        font-size: 13px;
+        color: #999999;
+        cursor: pointer;
+      }
+      .hasValue {
+        color: #333;
+      }
+
+      .timeUnit {
+        width: 12px;
+        height: 1px;
+        background: #d0d0d0;
+      }
+    }
+  }
+
+  .popupBottom {
+    position: sticky;
+    z-index: 1;
+    bottom: 0;
+    border-top: 1px solid #f2f2f2;
+    padding: 20px 13px 30px;
+    display: flex;
+    align-items: center;
+    :global {
+      .van-button {
+        font-size: 16px;
+      }
+      .van-button + .van-button {
+        margin-left: 15px;
+      }
+    }
+  }
+}

+ 241 - 36
src/teacher/statistics/home-statistics-detail/echats/index.tsx

@@ -1,7 +1,15 @@
-import { defineComponent, nextTick, onMounted, ref } from 'vue'
+import {
+  defineComponent,
+  nextTick,
+  onMounted,
+  PropType,
+  reactive,
+  ref,
+  watch
+} from 'vue'
 import styles from './index.module.less'
-import icon1 from '../../images/icon1.png';
-import iconArrow from '../../images/icon-arrow.png';
+import icon1 from '../../images/icon1.png'
+import iconArrow from '../../images/icon-arrow.png'
 import iconArrow1 from '../../images/icon-arrow1.png'
 import iconArrow11 from '../../images/icon-arrow1-1.png'
 import * as echarts from 'echarts/core'
@@ -28,6 +36,10 @@ import {
 } from 'echarts/components'
 import { LabelLayout } from 'echarts/features'
 import { CanvasRenderer } from 'echarts/renderers'
+import { Button, DatetimePicker, Popup } from 'vant'
+import { formatterDatePicker } from '@/helpers/utils'
+import dayjs from 'dayjs'
+import { getTimeRange, TIME_TYPE } from '../../home-statistics'
 
 // 注册必须的组件
 echarts.use([
@@ -154,51 +166,49 @@ const lineChartOption = (xAxisData: any, seriesData: any) => {
 export default defineComponent({
   name: 'eChats-model',
   props: {
-    list: {
-      type: Array,
-      default: () => []
+    obj: {
+      type: Object,
+      default: () => ({})
+    },
+    currentType: {
+      type: String as PropType<TIME_TYPE>,
+      default: 'MONTH'
     }
   },
+  emits: ['confirm'],
   setup(props, { emit }) {
     const chartId = 'eChart' + Date.now()
-    const popoverStatus = ref(false)
     const statisticCounts = ref({
       browseCount: 0,
       buyCount: 0
     })
-    let myChart: echarts.ECharts
-
-    nextTick(() => {
-      myChart = echarts.init(
-        document.getElementById(chartId) as HTMLDivElement
-      )
+    const currentType = ref<TIME_TYPE>(props.currentType)
+    const timeRange = getTimeRange(currentType.value)
+    const searchStatus = ref(false)
+    const forms = reactive({
+      loading: false,
+      dataShow: true,
+      subjectId: '' as any, // 选择的声部
+      subjectList: [] as any,
+      startTimeStatus: false,
+      endTimeMinDate: new Date(),
+      endTimeMaxDate: dayjs(new Date()).add(1, 'year').toDate(),
+      endTimeStatus: false,
+      startTime: new Date(timeRange?.startTime || ''),
+      startTimeStr: timeRange?.startTime || '',
+      endTime: new Date(timeRange?.endTime || ''),
+      endTimeStr: timeRange?.endTime || ''
     })
+    let myChart: echarts.ECharts
 
-    onMounted(() => {
+    const _initData = () => {
       nextTick(() => {
+        statisticCounts.value.browseCount = props.obj.browseCount || 0
+        statisticCounts.value.buyCount = props.obj.buyCount || 0
         myChart.clear()
         lineChartOption &&
           myChart.setOption(
-            lineChartOption(
-              [
-                '01月',
-                '02月',
-                '03月',
-                '04月',
-                '05月',
-                '06月',
-                '07月',
-                '08月',
-                '09月',
-                '10月',
-                '11月',
-                '12月'
-              ],
-              [
-                ['0', '0', '0', '0', '0', '0', '0', '2', '0', '8', '10', '0'],
-                ['0', '0', '0', '0', '1', '3', '0', '2', '0', '8', '10', '0']
-              ]
-            )
+            lineChartOption(props.obj.xAxisData, props.obj.yAxisData)
           )
         myChart.on('highlight', function (params: any) {
           const batch = params.batch || []
@@ -215,7 +225,51 @@ export default defineComponent({
           })
         })
       })
+    }
+
+    nextTick(() => {
+      myChart = echarts.init(document.getElementById(chartId) as HTMLDivElement)
+      _initData()
     })
+
+    watch(
+      () => props.obj,
+      () => {
+        _initData()
+      },
+      {
+        deep: true
+      }
+    )
+
+    watch(
+      () => props.currentType,
+      () => {
+        currentType.value = props.currentType
+      }
+    )
+
+    const onChangeTime = (type: TIME_TYPE) => {
+      if (currentType.value === type) return
+      currentType.value = type
+      resetTime(type)
+      // emit('confirm', currentType.value)
+    }
+
+    // 格式化
+    const resetTime = (type: TIME_TYPE) => {
+      const timeRang = getTimeRange(type)
+
+      forms.startTime = new Date(timeRang?.startTime || '')
+      forms.startTimeStr = timeRang?.startTime || ''
+      forms.endTimeMinDate = dayjs(timeRang?.startTime || '').toDate()
+      forms.endTimeMaxDate = dayjs(timeRang?.startTime || '')
+        .add(1, 'year')
+        .toDate()
+      forms.endTime = new Date(timeRang?.endTime || '')
+      forms.endTimeStr = timeRang?.endTime || ''
+    }
+
     return () => (
       <div class={styles.eChartSection}>
         <div class={styles.homeHead}>
@@ -228,11 +282,12 @@ export default defineComponent({
             <div
               class={[
                 styles.showItem,
-                popoverStatus.value && styles.showItemActive
+                searchStatus.value && styles.showItemActive
               ]}
+              onClick={() => (searchStatus.value = true)}
             >
               <span>本月</span>
-              <img src={popoverStatus.value ? iconArrow11 : iconArrow1} />
+              <img src={searchStatus.value ? iconArrow11 : iconArrow1} />
             </div>
           </div>
         </div>
@@ -256,6 +311,156 @@ export default defineComponent({
         <div class={styles.eChart}>
           <div id={chartId} style="width: 100%; height: 100%;"></div>
         </div>
+
+        <Popup
+          v-model:show={searchStatus.value}
+          closeable
+          round
+          position="bottom"
+          teleport="body"
+        >
+          <div class={styles.popupContainer}>
+            <div class={styles.popupTitle}>筛选</div>
+
+            <div class={styles.popupSearchList}>
+              <div class={styles.popupSection}>
+                <div class={styles.title}>
+                  <span>时间</span>
+                </div>
+
+                <div class={styles.timeCount}>
+                  <p
+                    onClick={() => onChangeTime('MONTH')}
+                    class={currentType.value === 'MONTH' ? styles.active : ''}
+                  >
+                    本月
+                  </p>
+                  <p
+                    onClick={() => onChangeTime('THREE_MONTH')}
+                    class={
+                      currentType.value === 'THREE_MONTH' ? styles.active : ''
+                    }
+                  >
+                    近三个月
+                  </p>
+                  <p
+                    onClick={() => onChangeTime('HALF_YEAR')}
+                    class={
+                      currentType.value === 'HALF_YEAR' ? styles.active : ''
+                    }
+                  >
+                    近半年
+                  </p>
+                  <p
+                    onClick={() => onChangeTime('YEAR')}
+                    class={currentType.value === 'YEAR' ? styles.active : ''}
+                  >
+                    近一年
+                  </p>
+                </div>
+
+                <div class={styles.timeRang}>
+                  <p
+                    class={[
+                      styles.timeInput,
+                      forms.startTimeStr && styles.hasValue
+                    ]}
+                    onClick={() => (forms.startTimeStatus = true)}
+                  >
+                    {forms.startTimeStr || '起始时间'}
+                  </p>
+                  <p class={styles.timeUnit}></p>
+                  <p
+                    class={[
+                      styles.timeInput,
+                      forms.endTimeStr && styles.hasValue
+                    ]}
+                    onClick={() => (forms.endTimeStatus = true)}
+                  >
+                    {forms.endTimeStr || '终止时间'}
+                  </p>
+                </div>
+              </div>
+            </div>
+
+            <div class={styles.popupBottom}>
+              <Button
+                round
+                block
+                type="default"
+                onClick={() => {
+                  currentType.value = props.currentType
+                  resetTime(props.currentType)
+                }}
+              >
+                重置
+              </Button>
+              <Button
+                round
+                block
+                type="primary"
+                onClick={() => {
+                  emit('confirm', {
+                    startTime: forms.startTimeStr,
+                    endTime: forms.endTimeStr
+                  })
+                  searchStatus.value = false
+                }}
+              >
+                确定
+              </Button>
+            </div>
+          </div>
+        </Popup>
+
+        {/* 开始日期 */}
+        <Popup
+          v-model:show={forms.startTimeStatus}
+          position="bottom"
+          round
+          class={'popupBottomSearch'}
+          teleport={'body'}
+        >
+          <DatetimePicker
+            v-model={forms.startTime}
+            type="date"
+            formatter={formatterDatePicker}
+            onCancel={() => (forms.startTimeStatus = false)}
+            onConfirm={(val: any) => {
+              forms.startTime = val
+              forms.startTimeStr = dayjs(val).format('YYYY-MM-DD')
+              forms.startTimeStatus = false
+              forms.endTime = null as any
+              forms.endTimeStr = ''
+              forms.endTimeMinDate = dayjs(val || new Date()).toDate()
+              forms.endTimeMaxDate = dayjs(val || new Date())
+                .add(1, 'year')
+                .toDate()
+            }}
+          />
+        </Popup>
+        {/* 结束日期 */}
+        <Popup
+          v-model:show={forms.endTimeStatus}
+          position="bottom"
+          round
+          class={'popupBottomSearch'}
+          teleport={'body'}
+        >
+          <DatetimePicker
+            v-model={forms.endTime}
+            type="date"
+            minDate={forms.endTimeMinDate}
+            maxDate={forms.endTimeMaxDate}
+            formatter={formatterDatePicker}
+            onCancel={() => (forms.endTimeStatus = false)}
+            onConfirm={(val: any) => {
+              forms.endTime = val
+              forms.endTimeStatus = false
+              forms.endTimeStr = dayjs(val).format('YYYY-MM-DD')
+            }}
+          />
+        </Popup>
       </div>
     )
   }

+ 3 - 1
src/teacher/statistics/home-statistics-detail/index.module.less

@@ -26,11 +26,13 @@
       border-radius: 2px;
     }
     .van-tabs__content {
-      padding-top: 12px;
       height: calc(100vh - var(--van-tabs-line-height) - var(--header-height, 0));
       overflow-x: hidden;
       overflow-y: auto;
     }
+    .van-tab__panel {
+      height: 100%;
+    }
   }
 }
 

+ 14 - 22
src/teacher/statistics/home-statistics-detail/index.tsx

@@ -1,10 +1,8 @@
 import { defineComponent } from 'vue'
 import styles from './index.module.less'
 import { Tab, Tabs } from 'vant'
-import Echats from './echats'
 import ColHeader from '@/components/col-header'
 import TheSticky from '@/components/the-sticky'
-import TeacherItem from './teacher-item'
 import List from './list'
 
 export default defineComponent({
@@ -13,33 +11,27 @@ export default defineComponent({
     return () => (
       <div class={styles.homeStatistics}>
         <TheSticky position="top">
-        <ColHeader border={false} background="transparent" />
+          <ColHeader border={false} background="transparent" />
         </TheSticky>
 
-        {/* PRACTICE: '趣纠课',
-  LIVE: '直播课',
-  GROUP: '小组课',
-  VIDEO: '视频课',
-  MUSIC: '乐谱',
-  VIP_COURSE */}
-        <Tabs class={styles.tabs}>
-          <Tab title="VIP定制课" name="vip">
-            <List type="vip" />
+        <Tabs class={styles.tabs} swipeable>
+          <Tab title="VIP定制课" name="VIP_COURSE">
+            <List type="VIP_COURSE" />
           </Tab>
-          <Tab title="趣纠课" name="practice">
-            <List type="practice" />
+          <Tab title="趣纠课" name="PRACTICE">
+            <List type="PRACTICE" />
           </Tab>
-          <Tab title="小组课" name="group">
-            <List type="group" />
+          <Tab title="小组课" name="GROUP">
+            <List type="GROUP" />
           </Tab>
-          <Tab title="直播课" name="live">
-            <List type="live" />
+          <Tab title="直播课" name="LIVE">
+            <List type="LIVE" />
           </Tab>
-          <Tab title="视频课" name="video">
-            <List type="video" />
+          <Tab title="视频课" name="VIDEO">
+            <List type="VIDEO" />
           </Tab>
-          <Tab title="乐谱" name="music">
-            <List type="music" />
+          <Tab title="乐谱" name="MUSIC">
+            <List type="MUSIC" />
           </Tab>
         </Tabs>
       </div>

+ 6 - 2
src/teacher/statistics/home-statistics-detail/list/index.module.less

@@ -1,7 +1,11 @@
+.list {
+  padding: 12px 0 30px;
+}
+
 .expectedIncome {
   background: #ffffff;
   border-radius: 10px;
-  margin: 12px 14px 30px;
+  margin: 12px 14px 0;
   overflow: hidden;
   .incomeTitle {
     display: flex;
@@ -41,7 +45,7 @@
     border-radius: 6px;
     border: 1px solid #ffefdf;
     padding: 5px 10px;
-    margin: 10px 12px 0;
+    margin: 0 12px 0;
   }
 
   .element {

+ 185 - 28
src/teacher/statistics/home-statistics-detail/list/index.tsx

@@ -1,65 +1,222 @@
-import { defineComponent, PropType } from 'vue'
+import { defineComponent, PropType, ref } from 'vue'
 import styles from './index.module.less'
-import { CellGroup, Sticky } from 'vant'
+import { CellGroup, List, Sticky } from 'vant'
 import iconMoney from '../../images/icon-money.png'
 import ColResult from '@/components/col-result'
 import Echats from '../echats'
 import TeacherItem from '../teacher-item'
 import BuyItem from '../buy-item'
 import request from '@/helpers/request'
+import { getTimeRange, TIME_TYPE } from '../../home-statistics'
+import { moneyFormat } from '@/helpers/utils'
 
 export default defineComponent({
   name: 'list',
   props: {
     type: {
       type: String as PropType<
-        'vip' | 'practice' | 'group' | 'live' | 'video' | 'music'
+        'VIP_COURSE' | 'PRACTICE' | 'GROUP' | 'LIVE' | 'VIDEO' | 'MUSIC'
       >,
-      default: 'vip'
+      default: 'VIP_COURSE'
     }
   },
   setup(props) {
-    
-    const getList = async () => {
+    const timeRange = ref(getTimeRange('MONTH'))
+
+    const obj = ref({
+      xAxisData: [] as any,
+      yAxisData: [] as any,
+      browseCount: 0,
+      buyCount: 0
+    })
+
+    const dataShow = ref(true) // 判断是否有数据
+    const state = {
+      statInfo: 0, // 预计课程总收入
+      accountPeriod: 0, // 几天后
+      loading: false,
+      finished: false,
+      params: {
+        page: 1,
+        rows: 20
+      }
+    }
+
+    const tableList = ref<any[]>([])
+
+    const getSysConfig = async () => {
       try {
-        const { data } = await request.post('/api-teacher/home/teacherIncomeList', {
-          data: {
+        const { data } = await request.get('/api-teacher/sysConfig/list', {
+          params: {
+            group: 'ACCOUNT_PERIOD'
+          }
+        })
+        const result = data || []
+        result.forEach((item: any) => {
+          if (
+            props.type === 'VIP_COURSE' &&
+            item.paramName === 'vip_course_account_period'
+          ) {
+            state.accountPeriod = item.paramValue
+          } else if (
+            props.type === 'PRACTICE' &&
+            item.paramName === 'practice_account_period'
+          ) {
+            state.accountPeriod = item.paramValue
+          } else if (
+            props.type === 'GROUP' &&
+            item.paramName === 'group_course_account_period'
+          ) {
+            state.accountPeriod = item.paramValue
+          } else if (
+            props.type === 'LIVE' &&
+            item.paramName === 'live_account_period'
+          ) {
+            state.accountPeriod = item.paramValue
+          } else if (
+            props.type === 'VIDEO' &&
+            item.paramName === 'video_account_period'
+          ) {
+            state.accountPeriod = item.paramValue
+          } else if (
+            props.type === 'MUSIC' &&
+            item.paramName === 'music_account_period'
+          ) {
+            state.accountPeriod = item.paramValue
+          }
+        })
+      } catch {
+        //
+      }
+    }
+
+    const getDetail = async () => {
+      try {
+        const { data } = await request.post(
+          '/api-teacher/home/courseExposure',
+          {
+            data: { ...timeRange.value, type: props.type }
+          }
+        )
 
+        const buy = data.buy || []
+        const exposure = data.exposure || []
+        const xAxisData: string[] = []
+        const exposureList: number[] = []
+        exposure.forEach((item: any, index: number) => {
+          xAxisData.push(item.date)
+          exposureList.push(item.exposureNum)
+
+          if (exposure.length - 1 === index) {
+            obj.value.browseCount = item.exposureNum
           }
         })
+        const buyList: number[] = []
+        buy.forEach((item: any, index: number) => {
+          buyList.push(item.exposureNum)
+
+          if (buy.length - 1 === index) {
+            obj.value.buyCount = item.exposureNum
+          }
+        })
+        const yAxisData = [exposureList, buyList]
+
+        obj.value.xAxisData = xAxisData
+        obj.value.yAxisData = yAxisData
       } catch {
-        // 
+        //
       }
     }
 
+    const getList = async () => {
+      try {
+        const { data } = await request.post(
+          '/api-teacher/home/teacherIncomeList',
+          {
+            data: {
+              ...timeRange.value,
+              type: props.type,
+              ...state.params
+            }
+          }
+        )
+
+        state.loading = false
+        state.statInfo = data.statInfo || 0
+        tableList.value = tableList.value.concat(data.rows || [])
+
+        state.finished = data.pageNo >= data.totalPage
+        state.params.page = data.pageNo + 1
+        dataShow.value = tableList.value.length > 0
+      } catch {
+        dataShow.value = false
+        state.finished = true
+      }
+    }
+
+    getSysConfig()
+    getDetail()
+    getList()
+
     return () => (
       <div class={styles.list}>
-        <Echats />
+        <Echats
+          obj={obj.value}
+          currentType={'MONTH'}
+          onConfirm={(val: any) => {
+            // currentType.value = val
+            timeRange.value = val
+            getDetail()
+            getList()
+          }}
+        />
 
         <div class={styles.expectedIncome}>
           {/* <Sticky> */}
-            <div class={styles.incomeTitle}>
-              <div class={styles.title}>
-                <img src={iconMoney} />
-                <span>预计总收入</span>
-              </div>
-
-              <div class={styles.price}>
-                <span>¥ </span>
-                4260.00
-              </div>
+          <div class={styles.incomeTitle}>
+            <div class={styles.title}>
+              <img src={iconMoney} />
+              <span>预计总收入</span>
+            </div>
+
+            <div class={styles.price}>
+              <span>¥ </span>
+              {moneyFormat(state.statInfo || 0)}
             </div>
+          </div>
           {/* </Sticky> */}
-          <div class={styles.incomeTip}>实际收入将在课程结束2天后结算</div>
+          <div class={styles.incomeTip}>
+            实际收入将在课程结束{state.accountPeriod || 0}天后结算
+          </div>
 
           <div class={styles.element}></div>
-          <CellGroup border={false}>
-            {['vip', 'practice'].includes(props.type) && <TeacherItem list={[1,2,3,4,5,6,7,7,8,]} />}
-            {['group', 'live', 'video', 'music'].includes(props.type) && (
-              <BuyItem list={[1,2,3,4,5,6,7,7,8,]} isSquare={props.type === "music"} />
-            )}
-          </CellGroup>
-          {/* <ColResult type="empty" btnStatus={false} classImgSize="SMALL" tips='暂无数据~' /> */}
+          {dataShow.value ? (
+            <List
+              v-model:loading={state.loading}
+              finished={state.finished}
+              finishedText=" "
+              onLoad={getList}
+            >
+              <CellGroup border={false}>
+                {['VIP_COURSE', 'PRACTICE'].includes(props.type) && (
+                  <TeacherItem list={tableList.value} />
+                )}
+                {['GROUP', 'LIVE', 'VIDEO', 'MUSIC'].includes(props.type) && (
+                  <BuyItem
+                    list={tableList.value}
+                    isSquare={props.type === 'MUSIC'}
+                  />
+                )}
+              </CellGroup>
+            </List>
+          ) : (
+            <ColResult
+              type="empty"
+              btnStatus={false}
+              classImgSize="SMALL"
+              tips="暂无数据~"
+            />
+          )}
         </div>
       </div>
     )

+ 15 - 4
src/teacher/statistics/home-statistics/index.tsx

@@ -167,9 +167,11 @@ const lineChartOption = (xAxisData: any, seriesData: any) => {
   }
 }
 
+export type TIME_TYPE = 'MONTH' | 'THREE_MONTH' | 'HALF_YEAR' | 'YEAR'
+
 /** 获取时间范围 */
 export const getTimeRange = (
-  type: 'MONTH' | 'THREE_MONTH' | 'HALF_YEAR' | 'YEAR'
+  type: TIME_TYPE
 ) => {
   if (type === 'MONTH') {
     return {
@@ -197,9 +199,10 @@ export const getTimeRange = (
 export default defineComponent({
   name: 'HomeStatistics',
   setup() {
+    const homeStatisticsRef = ref()
     const router = useRouter()
     const popoverStatus = ref(false)
-    const currentType = ref<'MONTH' | 'THREE_MONTH' | 'HALF_YEAR' | 'YEAR'>(
+    const currentType = ref<TIME_TYPE>(
       'MONTH'
     )
     const timeRange = ref(getTimeRange(currentType.value))
@@ -213,6 +216,14 @@ export default defineComponent({
         document.getElementById('eChart') as HTMLDivElement
       )
       getDetail()
+
+      const round = homeStatisticsRef.value?.getBoundingClientRect()
+      postMessage({
+        api: 'homeStatisticsHeight',
+        content: {
+          height: round.height || 300
+        }
+      })
     })
 
     const searchText = computed(() => {
@@ -279,7 +290,7 @@ export default defineComponent({
     }
 
     const onChangeTime = (
-      type: 'MONTH' | 'THREE_MONTH' | 'HALF_YEAR' | 'YEAR'
+      type: TIME_TYPE
     ) => {
       popoverStatus.value = false
       if (currentType.value === type) return
@@ -304,7 +315,7 @@ export default defineComponent({
       }
     }
     return () => (
-      <div class={styles.homeStatistics}>
+      <div class={styles.homeStatistics} ref={homeStatisticsRef}>
         <div class={styles.homeHead}>
           <div class={styles.title}>
             <img src={icon1} />

+ 55 - 47
src/teacher/statistics/practice-statistics-detail/echats/index.tsx

@@ -1,4 +1,11 @@
-import { defineComponent, nextTick, onMounted, ref, shallowRef } from 'vue'
+import {
+  defineComponent,
+  nextTick,
+  onMounted,
+  ref,
+  shallowRef,
+  watch
+} from 'vue'
 import styles from './index.module.less'
 import * as echarts from 'echarts/core'
 import {
@@ -24,6 +31,7 @@ import {
 } from 'echarts/components'
 import { LabelLayout } from 'echarts/features'
 import { CanvasRenderer } from 'echarts/renderers'
+import { formatSecToHMS } from '..'
 
 // 注册必须的组件
 echarts.use([
@@ -151,22 +159,21 @@ const lineChartOption = (params: {
 export default defineComponent({
   name: 'eChats-model',
   props: {
-    list: {
-      type: Array,
-      default: () => []
+    obj: {
+      type: Object,
+      default: () => ({})
     },
     type: {
       type: String as PropType<'TIME' | 'NUM'>,
       default: 'TIME'
     }
   },
-  setup(props, { emit }) {
+  setup(props) {
     const chartId = 'eChart_' + Date.now() + props.type
     const color = props.type === 'NUM' ? '#FF955D' : '#2DC7AA'
     const statisticCounts = ref({
-      time: '',
-      browseCount: 0,
-      buyCount: 0
+      time: '' as any,
+      count: 0 as any
     })
     let myChart: echarts.ECharts
 
@@ -174,40 +181,20 @@ export default defineComponent({
       myChart = echarts.init(document.getElementById(chartId) as HTMLDivElement)
     })
 
-    onMounted(() => {
+    const _initData = () => {
       nextTick(() => {
+        statisticCounts.value.time = props.obj.time || ''
+        statisticCounts.value.count =
+          props.type === 'NUM'
+            ? props.obj.count
+            : formatSecToHMS(props.obj.count).all
+
         myChart.clear()
         lineChartOption &&
           myChart.setOption(
             lineChartOption({
-              xAxisData: [
-                '01月',
-                '02月',
-                '03月',
-                '04月',
-                '05月',
-                '06月',
-                '07月',
-                '08月',
-                '09月',
-                '10月',
-                '11月',
-                '12月'
-              ],
-              seriesData: [
-                '0',
-                '0',
-                '0',
-                '0',
-                '0',
-                '0',
-                '0',
-                '2',
-                '0',
-                '8',
-                '10',
-                '0'
-              ],
+              xAxisData: props.obj.xAxisData,
+              seriesData: props.obj.yAxisData,
               colors: {
                 lineColor: color,
                 startColor:
@@ -224,20 +211,39 @@ export default defineComponent({
           )
         myChart.on('highlight', function (params: any) {
           const batch = params.batch || []
-          const options: any = myChart.getOption()
+          // const options: any = myChart.getOption()
+
           batch.forEach((item: any) => {
             const batchIndex = item.dataIndex
 
-            const browseCount = options.series[0].data[batchIndex]
-            const buyCount = options.series[1].data[batchIndex]
+            const count =
+              props.type === 'NUM'
+                ? props.obj.yAxisData[batchIndex]
+                : formatSecToHMS(props.obj.yAxisData[batchIndex] || 0).all
+            const time = props.obj.xAxisData[batchIndex]
             statisticCounts.value = {
-              browseCount,
-              buyCount
+              count,
+              time
             }
           })
         })
       })
+    }
+
+    nextTick(() => {
+      myChart = echarts.init(document.getElementById(chartId) as HTMLDivElement)
+      _initData()
     })
+
+    watch(
+      () => props.obj,
+      () => {
+        _initData()
+      },
+      {
+        deep: true
+      }
+    )
     return () => (
       <div class={styles.eChartSection}>
         <div class={styles.eChartTitle}>
@@ -246,17 +252,19 @@ export default defineComponent({
               {/* <span class={styles.line}></span> */}
               {props.type === 'NUM' ? (
                 <>
-                  <span class={styles.text}>{statisticCounts.value.time} 练习人数</span>
+                  <span class={styles.text}>
+                    {statisticCounts.value.time} 练习人数
+                  </span>
                   <span class={styles.num}>
-                    {statisticCounts.value.browseCount}人
+                    {statisticCounts.value.count || 0}人
                   </span>
                 </>
               ) : (
                 <>
-                  <span class={styles.text}>{statisticCounts.value.time} 练习时长</span>
-                  <span class={styles.num}>
-                    {statisticCounts.value.browseCount}
+                  <span class={styles.text}>
+                    {statisticCounts.value.time} 练习时长
                   </span>
+                  <span class={styles.num}>{statisticCounts.value.count}</span>
                 </>
               )}
             </div>

+ 3 - 0
src/teacher/statistics/practice-statistics-detail/index.module.less

@@ -357,6 +357,9 @@
         color: #999999;
         cursor: pointer;
       }
+      .hasValue {
+        color: #333;
+      }
 
       .timeUnit {
         width: 12px;

+ 396 - 68
src/teacher/statistics/practice-statistics-detail/index.tsx

@@ -1,4 +1,4 @@
-import { defineComponent, reactive, ref } from 'vue'
+import { defineComponent, reactive, ref, shallowReactive } from 'vue'
 import styles from './index.module.less'
 import iconArrow1 from '../images/icon-arrow1.png'
 import iconArrow11 from '../images/icon-arrow1-1.png'
@@ -11,18 +11,240 @@ import ColHeader from '@/components/col-header'
 import TheSticky from '@/components/the-sticky'
 import { formatterDatePicker } from '@/helpers/utils'
 import dayjs from 'dayjs'
+import request from '@/helpers/request'
+import { getTimeRange, TIME_TYPE } from '../home-statistics'
+import ColResult from '@/components/col-result'
+import { promisefiyPostMessage } from '@/helpers/native-message'
+
+/** 秒转分 */
+export const formatSecToMin = (second: number) => {
+  if (isNaN(second)) {
+    return '0'
+  }
+  const mm = (Math.floor(second / 60) + Math.floor(second % 60) / 60).toFixed(2)
+  return mm
+}
+
+/** 秒转时分秒 */
+export const formatSecToHMS = second => {
+  const hours = Math.floor(second / 3600)
+    .toString()
+    .padStart(2, '0')
+  const minutes = Math.floor((second % 3600) / 60)
+    .toString()
+    .padStart(2, '0')
+  const seconds = Math.round(second % 60)
+    .toString()
+    .padStart(2, '0')
+  return {
+    all: hours + '时' + minutes + '分' + seconds + '秒',
+    hours,
+    minutes,
+    seconds
+  }
+}
 
 export default defineComponent({
   name: 'PracticeDetail',
   setup() {
     const searchStatus = ref(false)
+    const currentType = ref<TIME_TYPE>('MONTH')
+
+    const searchObj = reactive({
+      tempSubjectId: '' as any,
+      type: 'MONTH' as TIME_TYPE
+    })
+    const timeRange = getTimeRange(currentType.value)
     const forms = reactive({
+      loading: false,
+      dataShow: true,
+      subjectId: '' as any, // 选择的声部
+      subjectList: [] as any,
       startTimeStatus: false,
       endTimeMinDate: new Date(),
+      endTimeMaxDate: dayjs(new Date()).add(1, 'year').toDate(),
       endTimeStatus: false,
-      startTime: new Date(),
-      endTime: null as any,
+      startTime: new Date(timeRange?.startTime || ''),
+      startTimeStr: timeRange?.startTime || '',
+      endTime: new Date(timeRange?.endTime || ''),
+      endTimeStr: timeRange?.endTime || ''
+    })
+
+    // 练习统计
+    const practiceSummary = shallowReactive({
+      averagePracticeTime: '0',
+      practiceCount: '0',
+      totalPracticeTime: '0',
+      totalTimes: {
+        hours: '00',
+        minutes: '00',
+        seconds: '00'
+      }
+    })
+    const obj = ref({
+      students: [] as any,
+      xAxisDataTime: [] as any,
+      yAxisDataTime: [] as any,
+      timeCount: 0,
+      timeStr: '',
+      xAxisDataCount: [] as any,
+      yAxisDataCount: [] as any,
+      countCount: 0,
+      countStr: ''
     })
+
+    // const searchText = computed(() => {
+    //       const template = {
+    //         MONTH: '本月',
+    //         THREE_MONTH: '近三个月',
+    //         HALF_YEAR: '近年半',
+    //         YEAR: '近一年'
+    //       }
+    //       return template[currentType.value]
+    //     })
+
+    // 导出学生练习时长数据
+    const onExport = async () => {
+      try {
+        const { data } = await request.post(
+          '/api-teacher/home/exportStudentPractice'
+        )
+        console.log(data, 'data')
+
+        // promisefiyPostMessage({
+        //   api: 'downloadFile',
+        //   content: {
+        //     downloadUrl: staffData.musicPdfUrl,
+        //     fileName: songName
+        //   }
+        // })
+      } catch {
+        //
+      }
+    }
+
+    const getDetail = async () => {
+      forms.loading = true
+      try {
+        const { data } = await request.post('/api-teacher/home/practice', {
+          data: {
+            startTime: forms.startTimeStr,
+            endTime: forms.endTimeStr,
+            subjectId: forms.subjectId
+          }
+        })
+        const summary = data.practiceSummary || {}
+        practiceSummary.averagePracticeTime = formatSecToMin(
+          summary.averagePracticeTime || 0
+        )
+        practiceSummary.practiceCount = summary.practiceCount || 0
+        practiceSummary.totalPracticeTime = summary.totalPracticeTime || 0
+        practiceSummary.totalTimes = formatSecToHMS(
+          summary.totalPracticeTime || 0
+        )
+
+        // 练习时长
+        const practiceTimes = data.practiceTimes || []
+        const xAxisDataTimes: string[] = []
+        const practiceTimeList: number[] = []
+        practiceTimes.forEach((item: any, index: number) => {
+          xAxisDataTimes.push(item.date)
+          practiceTimeList.push(item.practiceTime)
+
+          if (practiceTimes.length - 1 === index) {
+            obj.value.timeCount = item.practiceTime
+            obj.value.timeStr = item.date
+          }
+        })
+
+        // 练习人数
+        const practiceCounts = data.practiceCounts || []
+        const xAxisDataCounts: string[] = []
+        const countList: number[] = []
+        practiceCounts.forEach((item: any, index: number) => {
+          xAxisDataCounts.push(item.date)
+          countList.push(item.practiceTime)
+
+          if (practiceCounts.length - 1 === index) {
+            obj.value.countCount = item.practiceTime
+            obj.value.countStr = item.date
+          }
+        })
+
+        obj.value.xAxisDataTime = xAxisDataTimes
+        obj.value.yAxisDataTime = practiceTimeList
+        obj.value.xAxisDataCount = xAxisDataCounts
+        obj.value.yAxisDataCount = countList
+
+        // 学员练习时长
+        const studentPracticeSummary = data.studentPracticeSummary || []
+        let tempStudents: any = []
+        studentPracticeSummary.forEach((item: any) => {
+          const student = {
+            avatar: item.avatar,
+            averagePracticeTime: formatSecToHMS(item.averagePracticeTime || 0),
+            practiceDays: item.practiceDays || 0,
+            studentName: item.studentName,
+            subjectName: item.subjectName,
+            totalPracticeTime: formatSecToHMS(item.totalPracticeTime || 0)
+          }
+          tempStudents = student
+        })
+        obj.value.students = tempStudents
+
+        forms.dataShow = tempStudents.length > 0 ? true : false
+      } catch {
+        //
+      }
+      forms.loading = false
+    }
+
+    const getSubjectList = async () => {
+      const { data } = await request.get(
+        `api-teacher/subject/subjectSelect?type=MUSIC&clientId=TEACHER`
+      )
+      if (Array.isArray(data)) {
+        // 初始化乐器编号
+        data.forEach((item: any) => {
+          if (Array.isArray(item.subjects)) {
+            item.subjects.forEach((child: any) => {
+              forms.subjectList.push(child)
+            })
+          }
+        })
+      }
+    }
+
+    getSubjectList()
+    getDetail()
+
+    const onChangeTime = (type: TIME_TYPE) => {
+      if (searchObj.type === type) return
+      searchObj.type = type
+
+      resetTime(type)
+    }
+    // 格式化
+    const resetTime = (type: TIME_TYPE) => {
+      const timeRang = getTimeRange(type)
+
+      forms.startTime = new Date(timeRang?.startTime || '')
+      forms.startTimeStr = timeRang?.startTime || ''
+      forms.endTimeMinDate = dayjs(timeRang?.startTime || '').toDate()
+      forms.endTimeMaxDate = dayjs(timeRang?.startTime || '')
+        .add(1, 'year')
+        .toDate()
+      forms.endTime = new Date(timeRang?.endTime || '')
+      forms.endTimeStr = timeRang?.endTime || ''
+    }
+
+    // 重置
+    const onConfirm = () => {
+      // timeRange.value = getTimeRange(currentType.value)
+      searchStatus.value = false
+      forms.subjectId = searchObj.tempSubjectId
+      getDetail()
+    }
     return () => (
       <div class={styles.practiceDetail}>
         <TheSticky position="top">
@@ -42,11 +264,15 @@ export default defineComponent({
             </div>
 
             <div class={styles.leaveTime}>
-              <span class={styles.num}>23</span>
+              <span class={styles.num}>{practiceSummary.totalTimes.hours}</span>
               <span class={styles.text}>时</span>
-              <span class={styles.num}>36</span>
+              <span class={styles.num}>
+                {practiceSummary.totalTimes.minutes}
+              </span>
               <span class={styles.text}>分</span>
-              <span class={styles.num}>23</span>
+              <span class={styles.num}>
+                {practiceSummary.totalTimes.seconds}
+              </span>
               <span class={styles.text}>秒</span>
             </div>
 
@@ -57,7 +283,9 @@ export default defineComponent({
                   <span>练习人数</span>
                 </div>
                 <div class={styles.sBottom}>
-                  <span class={styles.num}>23</span>
+                  <span class={styles.num}>
+                    {practiceSummary.practiceCount}
+                  </span>
                   <span class={styles.text}>人</span>
                 </div>
               </div>
@@ -67,7 +295,9 @@ export default defineComponent({
                   <span>平均练习时长</span>
                 </div>
                 <div class={styles.sBottom}>
-                  <span class={styles.num}>23</span>
+                  <span class={styles.num}>
+                    {practiceSummary.averagePracticeTime}
+                  </span>
                   <span class={styles.text}>分钟</span>
                 </div>
               </div>
@@ -79,7 +309,14 @@ export default defineComponent({
               <span>练习时长</span>
             </div>
 
-            <Echats />
+            <Echats
+              obj={{
+                xAxisData: obj.value.xAxisDataTime,
+                yAxisData: obj.value.yAxisDataTime,
+                count: obj.value.timeCount,
+                time: obj.value.timeStr
+              }}
+            />
           </div>
 
           <div class={styles.section}>
@@ -87,60 +324,89 @@ export default defineComponent({
               <span>练习人数</span>
             </div>
 
-            <Echats type="NUM" />
+            <Echats
+              type="NUM"
+              obj={{
+                xAxisData: obj.value.xAxisDataCount,
+                yAxisData: obj.value.yAxisDataCount,
+                count: obj.value.countCount,
+                time: obj.value.countStr
+              }}
+            />
           </div>
 
           <div class={styles.section}>
             <div class={styles.title}>
               <span>学员练习时长</span>
-              <div class={styles.download}>
+              <div class={styles.download} onClick={onExport}>
                 <div>导出</div>
                 <img src={iconDownload} />
               </div>
             </div>
 
             <div class={styles.scroll}>
-              <table class={styles.dataTable} style={{ width: '486px' }}>
-                <colgroup>
-                  <col style="width: 88px;" />
-                  <col style="width: 105px;" />
-                  <col style="width: 106px;" />
-                  <col style="width: 72px;" />
-                  <col style="width: 106px;" />
-                </colgroup>
-                <thead>
-                  <tr>
-                    <th class={styles.tdFixedLeft}>学员</th>
-                    <th>乐器</th>
-                    <th>
-                      <div>练习时长</div>
-                      {/* <div class={styles.filters}>
-                    </div> */}
-                    </th>
-                    <th>练习天数</th>
-                    <th>平均练习时长</th>
-                  </tr>
-                </thead>
-                <tbody>
-                  {[1, 2, 3, 4, 5, 6, 7, 78, 89].map(() => (
+              {forms.dataShow ? (
+                <table class={styles.dataTable} style={{ width: '486px' }}>
+                  <colgroup>
+                    <col style="width: 88px;" />
+                    <col style="width: 105px;" />
+                    <col style="width: 106px;" />
+                    <col style="width: 72px;" />
+                    <col style="width: 106px;" />
+                  </colgroup>
+                  <thead>
                     <tr>
-                      <td class={styles.tdFixedLeft}>
-                        <img class={styles.userImg} />
-                        <span>王曼王曼王曼</span>
-                      </td>
-                      <td>长笛</td>
-                      <td>22小时56分24秒</td>
-                      <td>8</td>
-                      <td>22小时56分24秒</td>
+                      <th class={styles.tdFixedLeft}>学员</th>
+                      <th>乐器</th>
+                      <th>
+                        <div>练习时长</div>
+                        {/* <div class={styles.filters}>
+                    </div> */}
+                      </th>
+                      <th>练习天数</th>
+                      <th>平均练习时长</th>
                     </tr>
-                  ))}
-                </tbody>
-              </table>
+                  </thead>
+                  <tbody>
+                    {obj.value.students.map((item: any) => (
+                      <tr>
+                        <td class={styles.tdFixedLeft}>
+                          <img class={styles.userImg} src={item.avatar} />
+                          <span>{item.studentName}</span>
+                        </td>
+                        <td>{item.subjectName}</td>
+                        <td>
+                          {item.totalPracticeTime.hours}小时
+                          {item.totalPracticeTime.minutes}分
+                          {item.totalPracticeTime.seconds}秒
+                        </td>
+                        <td>{item.practiceDays}</td>
+                        <td>
+                          {item.averagePracticeTime.hours}小时
+                          {item.averagePracticeTime.minutes}分
+                          {item.averagePracticeTime.seconds}秒
+                        </td>
+                      </tr>
+                    ))}
+                  </tbody>
+                </table>
+              ) : (
+                <ColResult
+                  classImgSize="SMALL"
+                  btnStatus={false}
+                  tips="暂无数据~"
+                />
+              )}
             </div>
           </div>
         </div>
 
-        <Popup v-model:show={searchStatus.value} closeable round position="bottom">
+        <Popup
+          v-model:show={searchStatus.value}
+          closeable
+          round
+          position="bottom"
+        >
           <div class={styles.popupContainer}>
             <div class={styles.popupTitle}>筛选</div>
 
@@ -151,16 +417,54 @@ export default defineComponent({
                 </div>
 
                 <div class={styles.timeCount}>
-                  <p class={styles.active}>本月</p>
-                  <p>近三个月</p>
-                  <p>近半年</p>
-                  <p>近一年</p>
+                  <p
+                    onClick={() => onChangeTime('MONTH')}
+                    class={searchObj.type === 'MONTH' ? styles.active : ''}
+                  >
+                    本月
+                  </p>
+                  <p
+                    onClick={() => onChangeTime('THREE_MONTH')}
+                    class={
+                      searchObj.type === 'THREE_MONTH' ? styles.active : ''
+                    }
+                  >
+                    近三个月
+                  </p>
+                  <p
+                    onClick={() => onChangeTime('HALF_YEAR')}
+                    class={searchObj.type === 'HALF_YEAR' ? styles.active : ''}
+                  >
+                    近半年
+                  </p>
+                  <p
+                    onClick={() => onChangeTime('YEAR')}
+                    class={searchObj.type === 'YEAR' ? styles.active : ''}
+                  >
+                    近一年
+                  </p>
                 </div>
 
                 <div class={styles.timeRang}>
-                  <p class={styles.timeInput} onClick={() => forms.startTimeStatus = true}>起始时间</p>
+                  <p
+                    class={[
+                      styles.timeInput,
+                      forms.startTimeStr && styles.hasValue
+                    ]}
+                    onClick={() => (forms.startTimeStatus = true)}
+                  >
+                    {forms.startTimeStr || '起始时间'}
+                  </p>
                   <p class={styles.timeUnit}></p>
-                  <p class={styles.timeInput} onClick={() => forms.endTimeStatus = true}>终止时间</p>
+                  <p
+                    class={[
+                      styles.timeInput,
+                      forms.endTimeStr && styles.hasValue
+                    ]}
+                    onClick={() => (forms.endTimeStatus = true)}
+                  >
+                    {forms.endTimeStr || '终止时间'}
+                  </p>
                 </div>
               </div>
 
@@ -170,26 +474,44 @@ export default defineComponent({
                 </div>
 
                 <div class={[styles.timeCount, styles.timeSubject]}>
-                  <p class={styles.active}>本月</p>
-                  <p>近三个月</p>
-                  <p>近半年</p>
-                  <p>近一年近一年近一年</p>
-                  <p>近一年</p>
-                  <p>近一年近一年</p>
-                  <p>近一年</p>
-                  <p>近一年</p>
-                  <p>近一年近一年近一年</p>
-                  <p>近一年</p>
-                  <p>近一年近一年</p>
-                  <p>近一年</p>
-                  <p>近一年</p>
+                  <p
+                    class={searchObj.tempSubjectId === '' ? styles.active : ''}
+                    onClick={() => (searchObj.tempSubjectId = '')}
+                  >
+                    全部
+                  </p>
+                  {forms.subjectList.map((item: any) => (
+                    <p
+                      class={
+                        searchObj.tempSubjectId === item.id ? styles.active : ''
+                      }
+                      onClick={() => {
+                        searchObj.tempSubjectId = item.id
+                      }}
+                    >
+                      {item.name}
+                    </p>
+                  ))}
                 </div>
               </div>
             </div>
 
             <div class={styles.popupBottom}>
-              <Button round block type="default">重置</Button>
-              <Button round block type='primary'>确定</Button>
+              <Button
+                round
+                block
+                type="default"
+                onClick={() => {
+                  searchObj.tempSubjectId = ''
+                  searchObj.type = 'MONTH'
+                  resetTime('MONTH')
+                }}
+              >
+                重置
+              </Button>
+              <Button round block type="primary" onClick={onConfirm}>
+                确定
+              </Button>
             </div>
           </div>
         </Popup>
@@ -207,11 +529,15 @@ export default defineComponent({
             formatter={formatterDatePicker}
             onCancel={() => (forms.startTimeStatus = false)}
             onConfirm={(val: any) => {
-              console.log(val, 'val')
               forms.startTime = val
+              forms.startTimeStr = dayjs(val).format('YYYY-MM-DD')
               forms.startTimeStatus = false
               forms.endTime = null as any
+              forms.endTimeStr = ''
               forms.endTimeMinDate = dayjs(val || new Date()).toDate()
+              forms.endTimeMaxDate = dayjs(val || new Date())
+                .add(1, 'year')
+                .toDate()
             }}
           />
         </Popup>
@@ -226,11 +552,13 @@ export default defineComponent({
             v-model={forms.endTime}
             type="date"
             minDate={forms.endTimeMinDate}
+            maxDate={forms.endTimeMaxDate}
             formatter={formatterDatePicker}
             onCancel={() => (forms.endTimeStatus = false)}
             onConfirm={(val: any) => {
               forms.endTime = val
               forms.endTimeStatus = false
+              forms.endTimeStr = dayjs(val).format('YYYY-MM-DD')
             }}
           />
         </Popup>

+ 9 - 57
src/views/music/list/index.tsx

@@ -160,8 +160,10 @@ export default defineComponent({
     //   tempParams.subjectIds = getSubject.id
     // }
     //
+
     const params = reactive({
       search: (route.query.search as string) || '',
+      musicSortType: (route.query.type as string) || "",
       // exquisiteFlag: 1,
       musicTagIds: route.query.tagids || '',
       page: 1,
@@ -334,7 +336,7 @@ export default defineComponent({
     })
 
     return () => {
-      const tagList = ((state.value && state.value.data) as any) || []
+      // const tagList = ((state.value && state.value.data) as any) || []
       return (
         <>
           {!hideSearch && (
@@ -363,65 +365,15 @@ export default defineComponent({
                         ></i>
                         <Tabs
                           class={styles.tabSection}
-                          // v-model:active={state.tabActive}
+                          v-model:active={params.musicSortType}
                           shrink
-                          // onClickTab={(val) => {
-                          //   if (state.tabActive === '') {
-                          //     if (state.isAllStatus) {
-                          //       state.searchPopup = !state.searchPopup;
-                          //       if (state.searchPopup) {
-                          //         const allSearch = state.allSearch;
-                          //         if (allSearch.audioPlayTypes.length > 0) {
-                          //           if (allSearch.audioPlayTypes.length == 1) {
-                          //             state.sAPT = allSearch.audioPlayTypes.join(',');
-                          //           } else {
-                          //             state.sAPT = 'PLAY_SING';
-                          //           }
-                          //         } else {
-                          //           state.sAPT = '';
-                          //         }
-                          //         state.sNt = allSearch.musicTagIds;
-                          //         if (allSearch.bookVersionId) {
-                          //           let ids: any = [];
-                          //           data.tags.forEach((item: any) => {
-                          //             if (item.id === allSearch.bookVersionId) {
-                          //               ids.push(item.id);
-                          //             }
-                          //           });
-                          //           if (ids.length <= 0) {
-                          //             ids = formatParentId(
-                          //               allSearch.bookVersionId,
-                          //               data.tags
-                          //             );
-                          //           }
-                          //           // console.log(ids, 'ids', allSearch.bookVersionId)
-                          //           data.tagActiveId = ids[0];
-
-                          //           if (data.tagActiveId) {
-                          //             const item = data.tags.find(
-                          //               item => item.id === ids[0]
-                          //             );
-                          //             if (item) changeTag(item, ids[1]);
-                          //           }
-                          //         } else {
-                          //           data.tagActiveId = '';
-                          //           data.childSelectId = null;
-                          //           data.selectParents = {};
-                          //         }
-                          //       }
-                          //     } else {
-                          //       state.isAllStatus = true;
-                          //       onSearch();
-                          //     }
-                          //   } else {
-                          //     state.searchPopup = false;
-                          //     state.isAllStatus = false;
-                          //     onSearch();
-                          //   }
-                          // }}
+                          onClick-tab={(val) => {
+                            params.musicSortType = val.name
+                            onSearch(params.search)
+                          }}
                         >
                           <Tab name="" title="全部"></Tab>
-                          <Tab name="RECOMMEND" title="推荐"></Tab>
+                          <Tab name="TOP" title="推荐"></Tab>
                           <Tab name="HOT" title="热门"></Tab>
                           <Tab name="NEW" title="最新"></Tab>
                         </Tabs>