| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 | import OHeader from '@/components/m-header';import OSticky from '@/components/m-sticky';import OEmpty from '@/components/m-empty';import dayjs from 'dayjs';import { DatePicker, Popup, List, Image, CellGroup, Cell } from 'vant';import OFullRefresh from '@/components/m-full-refresh';import DetailItem from './modals/detail-item';import { defineComponent, onMounted, reactive, ref, nextTick } from 'vue';import { useRoute } from 'vue-router';import styles from './exercis-detail.module.less';import request from '@/helpers/request';import iconStudent from '@common/images/icon-student.png';import iconData from './images/icon-data.png';import { useRect } from '@vant/use';import { formatterDatePicker } from '@/helpers/utils';import { useEventListener, useWindowScroll } from '@vueuse/core';import { state as baseState } from '@/state';export default defineComponent({  name: 'exercis-detail',  setup() {    const route = useRoute();    const state = reactive({      showPopoverTime: false,      currentDate: [dayjs().format('YYYY'), dayjs().format('MM')],      isClick: false,      background: 'transparent',      color: '#fff',      practiceMonthName: route.query.practiceMonthName        ? route.query.practiceMonthName        : dayjs().format('YYYY') + '年' + dayjs().format('MM') + '月'    });    const forms = reactive({      practiceMonth: route.query.practiceMonth        ? route.query.practiceMonth        : state.currentDate[0] + '' + state.currentDate[1],      page: 1,      rows: 20    });    const refreshing = ref(false);    const loading = ref(false);    const finished = ref(false);    const showContact = ref(false);    const infoDetail = ref({} as any);    const list = ref([]);    const getList = async () => {      if (state.isClick) {        return;      }      state.isClick = true;      if (refreshing.value) {        list.value = [];        forms.page = 1;        refreshing.value = false;      }      try {        const res = await request.post(`/edu-app/musicPracticeRecord/page`, {          data: { ...forms, feature: 'EVALUATION' }        });        if (list.value.length > 0 && res.data.current === 1) {          return;        }        list.value = list.value.concat(res.data.rows || []);        forms.page = res.data.current + 1;        showContact.value = list.value.length > 0;        loading.value = false;        finished.value = res.data.current >= res.data.pages;      } catch {        showContact.value = false;        finished.value = true;      }      state.isClick = false;    };    const getDetail = async () => {      try {        const res = await request.get(`/edu-app/student/detail`, {          params: {            id: baseState.user.data?.id          }        });        infoDetail.value = { ...res.data };      } catch (e: any) {}    };    const topWrap = ref();    const topWrapHeight = ref(0);    onMounted(async () => {      useEventListener(document, 'scroll', () => {        const { y } = useWindowScroll();        if (y.value > 52) {          state.background = '#fff';          state.color = '#323333';        } else {          state.background = 'transparent';          state.color = '#fff';        }      });      await getList();      await getDetail();      nextTick(() => {        const { height } = useRect(topWrap.value);        topWrapHeight.value = height;      });    });    const checkTimer = (val: any) => {      forms.practiceMonth = val.selectedValues[0] + val.selectedValues[1];      state.practiceMonthName =        val.selectedValues[0] + '年' + val.selectedValues[1] + '月';      state.showPopoverTime = false;      refreshing.value = true;      getList();    };    const onRefresh = () => {      finished.value = false;      // 重新加载数据      // 将 loading 设置为 true,表示处于加载状态      loading.value = true;      getList();    };    return () => (      <>        <div class={[styles.exercisContainer]}>          <div class={styles.topWrap} ref={topWrap}>            <OSticky position="top">              <OHeader                border={false}                background={state.background}                color={state.color}              />            </OSticky>            <div class={styles.topInfo}>              <div class={styles.topInfoLeft}>                <div class={styles.headWrap}>                  <Image                    src={                      infoDetail.value.avatar                        ? infoDetail.value.avatar                        : iconStudent                    }                    fit="cover"                    width="68px"                    height="68px"                  />                </div>                <div class={styles.infoMsg}>                  <p>{infoDetail.value.nickname}</p>                  <div class={styles.tag}>                    {infoDetail.value.subjectNames                      ? infoDetail.value.subjectNames                      : '暂无声部'}                  </div>                </div>              </div>              <div class={styles.topInfoRight}>                <div class={styles.infoDay}>                  <p class={styles.infoDayMain}>                    {infoDetail.value.practiceDays                      ? infoDetail.value.practiceDays                      : 0}                    <span>天</span>                  </p>                  <p class={styles.infoDaysub}>练习天数</p>                </div>                <div class={styles.infoTime}>                  <p class={styles.infoDayMain}>                    {infoDetail.value.practiceTimes                      ? infoDetail.value.practiceTimes                      : 0}                    <span>分钟</span>                  </p>                  <p class={styles.infoDaysub}>练习时长</p>                </div>              </div>            </div>            <CellGroup inset>              <Cell                class={styles.select}                center                isLink                onClick={() => (state.showPopoverTime = true)}>                {{                  icon: () => <img class={styles.icon} src={iconData} />,                  title: () => (                    <div class="van-ellipsis">{state.practiceMonthName}</div>                  )                }}              </Cell>            </CellGroup>          </div>          {showContact.value ? (            <OFullRefresh              v-model:modelValue={refreshing.value}              onRefresh={onRefresh}              style={{ minHeight: `calc(100vh - ${topWrapHeight.value}px)` }}>              <List                loading-text=" "                finished={finished.value}                finished-text=" "                onLoad={getList}>                {list.value.map((item: any) => (                  <DetailItem item={item} />                ))}              </List>            </OFullRefresh>          ) : (            <OEmpty              description="暂无练习统计"              style={{ height: `calc(100vh - ${topWrapHeight.value}px)` }}            />          )}        </div>        <Popup          v-model:show={state.showPopoverTime}          position="bottom"          round          class={'popupBottomSearch'}>          <DatePicker            onCancel={() => {              state.showPopoverTime = false;            }}            onConfirm={checkTimer}            v-model={state.currentDate}            formatter={formatterDatePicker}            columnsType={['year', 'month']}          />        </Popup>      </>    );  }});
 |