lex 1 anno fa
parent
commit
2dd7db3d70

+ 2 - 1
package.json

@@ -15,7 +15,8 @@
   "scripts": {
     "dev": "vite",
     "start": "npm run dev",
-    "build": "vue-tsc --noEmit && vite build",
+    "build:prod": "vue-tsc --noEmit && vite build",
+    "build:dev": "vue-tsc --noEmit && vite build --mode development",
     "serve": "vite preview",
     "lint": "eslint --ext .js,.jsx,.vue,.ts,.tsx src",
     "generate": "plop"

File diff suppressed because it is too large
+ 0 - 0
src/components/the-full-refresh/datas/data.json


+ 21 - 0
src/components/the-full-refresh/index.module.less

@@ -0,0 +1,21 @@
+.animateWrap {
+  width: 55px !important;
+  height: 55px !important;
+}
+
+.loading {
+  height: 55px !important;
+  img {
+    height: 30px;
+    width: 120px;
+    margin-top: 20px;
+  }
+}
+
+.pullRefresh {
+  :global {
+    .van-pull-refresh__track {
+      min-height: inherit;
+    }
+  }
+}

+ 77 - 0
src/components/the-full-refresh/index.tsx

@@ -0,0 +1,77 @@
+import { Image, PullRefresh } from 'vant';
+import { defineComponent, reactive, watch } from 'vue';
+import styles from './index.module.less';
+import { Vue3Lottie } from 'vue3-lottie';
+import AstronautJSON from './datas/data.json';
+import 'vue3-lottie/dist/style.css';
+import loading from './loading.gif';
+import loadingJSon from './loading.json';
+export default defineComponent({
+  name: 'm-full-refresh',
+  props: {
+    title: String,
+    modelValue: {
+      type: Boolean,
+      default: false
+    }
+  },
+  emits: ['refresh', 'update:modelValue'],
+  setup(props, { emit, slots }) {
+    const state = reactive({
+      fullState: false
+    });
+    watch(
+      () => props.modelValue,
+      (val: boolean) => {
+        state.fullState = val;
+      }
+    );
+    watch(
+      () => state.fullState,
+      (val: boolean) => {
+        emit('update:modelValue', val);
+      }
+    );
+    return () => (
+      <PullRefresh
+        v-model:modelValue={state.fullState}
+        onRefresh={() => emit('refresh')}
+        loadingText=" "
+        class={styles.pullRefresh}>
+        {{
+          // loading: () => (
+          //   <div>
+          //     {
+          //       // <Image src={loadingJSon.loading} class={styles.loading} />
+          //       <Vue3Lottie
+          //         class={styles.animateWrap}
+          //         animationData={AstronautJSON}></Vue3Lottie>
+          //     }
+          //   </div>
+          // ),
+          // pulling: () => (
+          //   <div>
+          //     {
+          //       // <Image src={loading} class={styles.loading} />
+          //       <Vue3Lottie
+          //         class={styles.animateWrap}
+          //         animationData={AstronautJSON}></Vue3Lottie>
+          //     }
+          //   </div>
+          // ),
+          // loosing: () => (
+          //   <div>
+          //     {
+          //       // <Image src={loading} class={styles.loading} />
+          //       <Vue3Lottie
+          //         class={styles.animateWrap}
+          //         animationData={AstronautJSON}></Vue3Lottie>
+          //     }
+          //   </div>
+          // ),
+          default: () => <> {slots.default && slots.default()}</>
+        }}
+      </PullRefresh>
+    );
+  }
+});

BIN
src/components/the-full-refresh/loading.gif


File diff suppressed because it is too large
+ 1 - 0
src/components/the-full-refresh/loading.json


+ 65 - 0
src/helpers/utils.ts

@@ -48,6 +48,71 @@ export const browser = () => {
   }
 }
 
+/**
+ * @description 格式化日期控件显示内容
+ * @param type
+ * @param option
+ * @returns OBJECT
+ */
+export const formatterDatePicker = (type: any, option: any) => {
+  if (type === 'year') {
+    option.text += '年'
+  }
+  if (type === 'month') {
+    option.text += '月'
+  }
+  if (type === 'day') {
+    option.text += '日'
+  }
+  return option
+}
+
+/**
+ * 数字转成汉字
+ * @params num === 要转换的数字
+ * @return 汉字
+ * */
+export const toChinesNum = (num: any) => {
+  const changeNum = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九']
+  const unit = ['', '十', '百', '千', '万']
+  num = parseInt(num)
+  const getWan = (temp: any) => {
+    const strArr = temp.toString().split('').reverse()
+    let newNum = ''
+    const newArr: string[] = []
+    strArr.forEach((item: any, index: any) => {
+      newArr.unshift(
+        item === '0' ? changeNum[item] : changeNum[item] + unit[index]
+      )
+    })
+    const numArr: number[] = []
+    newArr.forEach((m, n) => {
+      if (m !== '零') numArr.push(n)
+    })
+    if (newArr.length > 1) {
+      newArr.forEach((m, n) => {
+        if (newArr[newArr.length - 1] === '零') {
+          if (n <= numArr[numArr.length - 1]) {
+            newNum += m
+          }
+        } else {
+          newNum += m
+        }
+      })
+    } else {
+      newNum = newArr[0]
+    }
+
+    return newNum
+  }
+  const overWan = Math.floor(num / 10000)
+  let noWan: any = num % 10000
+  if (noWan.toString().length < 4) {
+    noWan = '0' + noWan
+  }
+  return overWan ? getWan(overWan) + '万' + getWan(noWan) : getWan(num)
+}
+
 export const getRandomKey = () => {
   const key = '' + new Date().getTime() + Math.floor(Math.random() * 1000000)
   return key

+ 18 - 10
src/router/routes-tenant.ts

@@ -126,7 +126,7 @@ export default [
         path: '/music-personal',
         component: () => import('@/tenant/music/personal'),
         meta: {
-          title: '我的乐谱'
+          title: '我的曲库'
         }
       },
       {
@@ -135,7 +135,15 @@ export default [
         meta: {
           title: '查看专辑'
         }
-      }
+      },
+      {
+        path: '/exercise-record',
+        name: 'exercise-record',
+        component: () => import('@/tenant/exercise-record/exercis-detail'),
+        meta: {
+          title: '练习统计'
+        }
+      },
       // {
       //   path: '/practiceClass',
       //   name: 'practiceClass',
@@ -176,14 +184,14 @@ export default [
       //     title: '小酷Ai会员大放价'
       //   }
       // },
-      // {
-      //   path: '/memberRecord',
-      //   name: 'memberRecord',
-      //   component: () => import('@/student/member-center/member-record'),
-      //   meta: {
-      //     title: '训练统计'
-      //   }
-      // },
+      {
+        path: '/memberRecord',
+        name: 'memberRecord',
+        component: () => import('@/tenant/exercise-record/exercis-detail'),
+        meta: {
+          title: '训练统计'
+        }
+      }
       // {
       //   path: '/tradeRecord',
       //   name: 'tradeRecord',

+ 2 - 2
src/state.ts

@@ -78,7 +78,7 @@ export const goWechatAuth = (wxAppId: string, urlString?: string) => {
   // 开发环境
   if (import.meta.env.DEV) {
     const replaceUrl =
-      `https://online.colexiu.com/getWxCode?appid=${
+      `https://kt.colexiu.com/getWxCode?appid=${
         wxAppId || 'wx8654c671631cfade'
       }&state=STATE&redirect_uri=` +
       encodeURIComponent(urlString || window.location.href)
@@ -113,7 +113,7 @@ export const goAliAuth = (alipayAppId: string, urlString?: string) => {
   const appid = alipayAppId || '2021004100630808'
   // 开发环境
   if (import.meta.env.DEV) {
-    const url = `https://online.colexiu.com/getAliCode?app_id=${appid}&state=STATE&redirect_uri=${urlNow}`
+    const url = `https://kt.colexiu.com/getAliCode?app_id=${appid}&state=STATE&redirect_uri=${urlNow}`
     window.location.replace(url)
   }
 

+ 165 - 0
src/tenant/exercise-record/exercis-detail.module.less

@@ -0,0 +1,165 @@
+.exercisContainer {
+  :global {
+
+    .van-calendar__day--end,
+    .van-calendar__day--start,
+    .van-calendar__day--start-end,
+    .van-calendar__day--multiple-middle,
+    .van-calendar__day--multiple-selected {
+      background: #FF5074;
+    }
+  }
+
+  .bgImg {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 214px;
+    z-index: -1;
+  }
+}
+
+.topWrap {
+  :global {
+    .van-sticky {
+      background: url('../images/bg-image.png') no-repeat top center;
+      background-size: 100% 214px;
+    }
+  }
+
+
+
+  .userMember {
+    background-color: transparent;
+    width: auto;
+    padding: 0;
+    // border-radius: 10px;
+    padding: 18px 12px 30px 26px;
+
+
+    .level {
+      width: 44px;
+      height: 17px;
+    }
+
+    .userImgSection {
+      position: relative;
+      padding: 3px;
+      background: #fff;
+      margin-right: 12px;
+      border-radius: 50%;
+
+      &::before {
+        content: ' ';
+        position: absolute;
+        left: 1px;
+        top: 1px;
+        bottom: 1px;
+        right: 1px;
+        background-color: #fff;
+        border-radius: 50%;
+      }
+    }
+
+    .userImg {
+      width: 46px;
+      height: 46px;
+      border-radius: 50%;
+      vertical-align: middle;
+      overflow: hidden;
+    }
+
+    .userInfo {
+      padding-top: 4px;
+      display: flex;
+      align-items: center;
+      color: #fff;
+      padding-bottom: 5px;
+
+      .name {
+        padding-right: 5px;
+        max-width: 100px;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+        font-size: 18px;
+        font-weight: 600;
+        color: #742626;
+      }
+    }
+
+    .timeRemaining {
+      margin-top: 0;
+      font-size: 14px;
+      color: #c0c0c0;
+    }
+  }
+
+
+  .topInfoRight {
+    // width: 50%;
+    margin-bottom: 18px;
+    padding: 0 10%;
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    justify-content: center;
+
+    .infoDay,
+    .infoTime {
+      width: 50%;
+    }
+
+    .infoDay {
+      position: relative;
+      margin-right: 20px;
+
+      &::after {
+        position: absolute;
+        content: ' ';
+        right: -12px;
+        top: 12px;
+        width: 1px;
+        height: 35px;
+        background-color: #E0E5E8;
+      }
+    }
+
+    .infoDayMain {
+      font-size: 24px;
+      color: #333333;
+      line-height: 28px;
+      margin-bottom: 7px;
+      font-family: DINAlternate-Bold, DINAlternate;
+      font-weight: 600;
+      text-align: center;
+
+      span {
+        margin-left: 2px;
+        font-size: 12px;
+        font-weight: 400;
+        color: #333333;
+        line-height: 17px;
+      }
+    }
+
+    .infoDaysub {
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      font-size: 12px;
+      font-weight: 400;
+      color: #333333;
+      line-height: 17px;
+      text-align: center;
+
+      img {
+        width: 14px;
+        height: 14px;
+        margin-right: 3px;
+      }
+    }
+  }
+
+}

+ 281 - 0
src/tenant/exercise-record/exercis-detail.tsx

@@ -0,0 +1,281 @@
+import dayjs from 'dayjs'
+import isBetween from 'dayjs/plugin/isBetween'
+dayjs.extend(isBetween)
+import { List, Image, Calendar, Cell } from 'vant'
+import OFullRefresh from '@/components/the-full-refresh'
+import DetailItem from './modals/detail-item'
+import { defineComponent, onMounted, reactive, ref, computed } from 'vue'
+import { useRoute } from 'vue-router'
+import styles from './exercis-detail.module.less'
+import request from '@/helpers/request'
+import { state as baseState } from '@/state'
+import TheSticky from '@/components/the-sticky'
+import ColHeader from '@/components/col-header'
+import ColResult from '@/components/col-result'
+import bgImg from '../images/bg-image.png'
+import iconStudent from '@common/images/icon_student.png'
+import iconLogo from '../member-center/images/icon-logo-default.png'
+import iconLogoActive from '../member-center/images/icon-logo.png'
+
+export default defineComponent({
+  name: 'exercis-detail',
+  setup() {
+    const route = useRoute()
+    const state = reactive({
+      showPopoverTime: false,
+      currentDate: [dayjs().format('YYYY'), dayjs().format('MM')],
+      isClick: false,
+      practiceMonthName: route.query.practiceMonthName
+        ? route.query.practiceMonthName
+        : dayjs().format('YYYY') + '年' + dayjs().format('MM') + '月',
+      userTrainOverView: {
+        trainDays: 0,
+        trainNum: 0,
+        trainTime: 0
+      }
+    })
+
+    const userInfo = computed(() => {
+      const users = baseState.user.data
+      return {
+        username: users?.username,
+        phone: users?.phone,
+        avatar: users?.heardUrl,
+        id: users?.userId,
+        memberRankSettingId: users?.memberRankSettingId,
+        isVip: users?.isVip,
+        membershipDays: users?.membershipDays,
+        membershipEndTime: users?.membershipEndTime
+      }
+    })
+    const forms = reactive({
+      practiceMonth: dayjs().day(1).format('YYYYMMDD'),
+      startTime: '2023-09',
+      endTime: dayjs().day(7).format('YYYY-MM-DD'),
+      page: 1,
+      rows: 20
+    })
+    const refreshing = ref(false)
+    const loading = ref(false)
+    const finished = ref(false)
+    const showContact = ref(false)
+    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 { data } = await request.get(
+          `/api-student/sysMusicRecord/studentTrainData`,
+          {
+            params: { ...forms }
+          }
+        )
+
+        // 在第一页的时候才处理数据显示
+        if (data.detail.pageNo === 1) {
+          state.userTrainOverView = data.userTrainOverView
+        }
+        if (list.value.length > 0 && data.detail.pageNo === 1) {
+          return
+        }
+
+        list.value = list.value.concat(data.detail.rows || [])
+        forms.page = data.detail.pageNo + 1
+        showContact.value = list.value.length > 0
+        loading.value = false
+        finished.value = data.detail.pageNo >= data.detail.totalPage
+      } catch {
+        showContact.value = false
+        finished.value = true
+      }
+      state.isClick = false
+    }
+
+    onMounted(async () => {
+      await getList()
+    })
+
+    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}>
+          <TheSticky position="top">
+            <ColHeader
+              border={false}
+              background={'transparent'}
+              color={'#333333'}
+            />
+            <Cell
+              class={styles.userMember}
+              labelClass={styles.timeRemaining}
+              v-slots={{
+                icon: () => (
+                  <div class={styles.userImgSection}>
+                    <Image
+                      class={styles.userImg}
+                      src={userInfo.value.avatar || iconStudent}
+                      fit="cover"
+                    />
+                  </div>
+                ),
+                title: () => (
+                  <div class={styles.userInfo}>
+                    <span class={styles.name}>{userInfo.value.username}</span>
+                    <Image
+                      class={styles.level}
+                      src={userInfo.value.isVip ? iconLogoActive : iconLogo}
+                    />
+                  </div>
+                ),
+                label: () => <div class={styles.subjectName}></div>
+              }}
+            ></Cell>
+          </TheSticky>
+        </div>
+        <img class={styles.bgImg} src={bgImg} />
+        {/* <div class={styles.topInfoRight}>
+            <div class={styles.infoDay}>
+              <p class={styles.infoDayMain}>
+                {infoDetail.value.practiceDays
+                  ? infoDetail.value.practiceDays
+                  : 0}
+              </p>
+              <p class={styles.infoDaysub}>
+                <img src={iconDays} />
+                练习天数(天)
+              </p>
+            </div>
+            <div class={styles.infoTime}>
+              <p class={styles.infoDayMain}>
+                {infoDetail.value.practiceTimes
+                  ? Math.floor(infoDetail.value.practiceTimes / 60)
+                  : 0}
+
+              </p>
+              <p class={styles.infoDaysub}>
+                <img src={iconClock} />
+                练习时长(分钟)
+              </p>
+            </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>
+         */}
+        {showContact.value ? (
+          <OFullRefresh
+            v-model:modelValue={refreshing.value}
+            onRefresh={onRefresh}
+            style={{ minHeight: `calc(100vh - var(--header-height))` }}
+          >
+            <List
+              loading-text=" "
+              finished={finished.value}
+              finished-text=" "
+              onLoad={getList}
+            >
+              {list.value.map((item: any) => (
+                <DetailItem item={item} />
+              ))}
+            </List>
+          </OFullRefresh>
+        ) : (
+          <div
+            style={{
+              height: `calc(100vh - var(--header-height))`,
+              display: 'flex',
+              alignItems: 'center'
+            }}
+          >
+            <ColResult tips="暂无学练统计" btnStatus={false} />
+          </div>
+        )}
+
+        <Calendar
+          v-model:show={state.showPopoverTime}
+          firstDayOfWeek={1}
+          showConfirm={false}
+          type="range"
+          title="周期选择"
+          maxRange={7}
+          minDate={new Date('2023-02-27')}
+          defaultDate={[
+            dayjs(forms.practiceMonth).toDate(),
+            dayjs(forms.endTime).toDate()
+          ]}
+          style={{
+            height: '70%'
+          }}
+          onSelect={(item: any) => {
+            forms.practiceMonth = ''
+            forms.endTime = ''
+            if (
+              !dayjs(item[0]).isBetween(
+                dayjs(forms.practiceMonth),
+                dayjs(forms.endTime)
+              )
+            ) {
+              const week = dayjs(item[0]).day()
+              if (week === 0) {
+                // 星期天
+                forms.practiceMonth = dayjs(item[0])
+                  .subtract(6, 'day')
+                  .format('YYYYMMDD')
+                forms.endTime = dayjs(item[0]).format('YYYY-MM-DD')
+              } else if (week === 1) {
+                // 星期一
+                forms.practiceMonth = dayjs(item[0]).format('YYYYMMDD')
+                forms.endTime = dayjs(item[0])
+                  .add(6, 'day')
+                  .format('YYYY-MM-DD')
+              } else {
+                forms.practiceMonth = dayjs(item[0])
+                  .subtract(week - 1, 'day')
+                  .format('YYYYMMDD')
+                forms.endTime = dayjs(item[0])
+                  .add(7 - week, 'day')
+                  .format('YYYY-MM-DD')
+              }
+            }
+            state.showPopoverTime = false
+          }}
+        />
+      </div>
+    )
+  }
+})

BIN
src/tenant/exercise-record/images/Image1.png


BIN
src/tenant/exercise-record/images/Image2.png


BIN
src/tenant/exercise-record/images/Image3.png


BIN
src/tenant/exercise-record/images/Image4.png


BIN
src/tenant/exercise-record/images/Image5.png


BIN
src/tenant/exercise-record/images/good-icon.png


+ 98 - 0
src/tenant/exercise-record/modals/detail-item.module.less

@@ -0,0 +1,98 @@
+.itemWrap {
+  background: #ffffff;
+  border-radius: 10px;
+  padding: 12px 15px 20px;
+  margin: 0 13px 13px;
+
+  .itemTop {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    align-items: center;
+    border-bottom: 1px solid #f2f2f2;
+    padding-bottom: 12px;
+
+    .itemTopLeft {
+      .itemTopMain {
+        height: 22px;
+        font-size: 16px;
+        font-weight: 500;
+        color: #333333;
+        line-height: 22px;
+        margin-bottom: 6px;
+        max-width: 160px;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+      }
+
+      .itemTopSub {
+        font-size: 12px !important;
+        font-weight: 400;
+        color: #777777;
+        line-height: 17px;
+      }
+    }
+
+    .itemTopRight {
+      display: flex;
+      flex-direction: row;
+      align-items: center;
+
+      .imgWrap {
+        width: 100px;
+        height: 33px;
+        background: #e9e3ff;
+        border-radius: 19px;
+
+        img {
+          width: 100%;
+          height: 100%;
+        }
+      }
+
+      .imgIcon {
+        font-size: 16px;
+        color: #d8d8d8;
+        margin-left: 6px;
+      }
+    }
+  }
+
+  .itemBottom {
+    margin-top: 15px;
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    justify-content: space-around;
+    text-align: center;
+
+    .itemBottomDot {
+      width: 25%;
+
+      .dotMain {
+        font-size: 26px;
+        color: #333333;
+        line-height: 30px;
+        margin-bottom: 4px;
+        font-family: DINAlternate-Bold, DINAlternate;
+        font-weight: bold;
+
+        span {
+          margin-left: 1px;
+          font-size: 12px;
+          font-weight: 400;
+          color: #333333;
+          line-height: 17px;
+        }
+      }
+
+      .dotSub {
+        font-size: 12px;
+        font-weight: 400;
+        color: #777777;
+        line-height: 17px;
+      }
+    }
+  }
+}

+ 125 - 0
src/tenant/exercise-record/modals/detail-item.tsx

@@ -0,0 +1,125 @@
+import { defineComponent } from 'vue';
+import styles from './detail-item.module.less';
+import { postMessage } from '@/helpers/native-message';
+import { Icon } from 'vant';
+import Image1 from '../images/Image1.png';
+import Image2 from '../images/Image2.png';
+import Image3 from '../images/Image3.png';
+import Image4 from '../images/Image4.png';
+import Image5 from '../images/Image5.png';
+
+const scoreInfos: any = {
+  1: {
+    img: Image1,
+    tips: '你的演奏不太好,音准和完整性还需加强,再练一练吧~',
+    mome: '敢于尝试'
+  },
+  2: {
+    img: Image2,
+    tips: '你的演奏还不熟练,音准和完整性还需加强,加紧训练才能有好成绩哦~',
+    mome: '还要加油哦~'
+  },
+  3: {
+    img: Image3,
+    tips: '你的演奏还不流畅,音准和节奏还需加强,科学的练习才能更完美哦~',
+    mome: '突破自我'
+  },
+  4: {
+    img: Image4,
+    tips: '你的演奏还不错,继续加油吧,加强音准,离完美就差一步啦~',
+    mome: '崭露头角'
+  },
+  5: {
+    img: Image5,
+    tips: '你的演奏非常不错,音准的把握和节奏稍有瑕疵,完整性把握的很好~',
+    mome: '你很棒'
+  }
+};
+export default defineComponent({
+  props: ['item'],
+  name: 'detail-item',
+
+  setup(props) {
+    const getLeveByScoreId = (score?: number) => {
+      if (!score && typeof score !== 'number') {
+        return {};
+      }
+      let leve: any = 1;
+      if (score > 20 && score <= 40) {
+        leve = 2;
+      } else if (score > 40 && score <= 60) {
+        leve = 3;
+      } else if (score > 60 && score <= 80) {
+        leve = 4;
+      } else if (score > 80) {
+        leve = 5;
+      }
+      return leve;
+    };
+    const gotoDetail = () => {
+      const url =
+        window.location.origin +
+        `/instrument/#/evaluat-report?id=${props.item.id}`;
+      // const url = `https://test.lexiaoya.cn/instrument/#/evaluat-report?id=${props.item.id}`;
+      postMessage({
+        api: 'openWebView',
+        content: {
+          url: url,
+          orientation: 0,
+          isHideTitle: true,
+          statusBarTextColor: false,
+          isOpenLight: true
+        }
+      });
+    };
+    return () => (
+      <div class={styles.itemWrap} onClick={gotoDetail}>
+        <div class={styles.itemTop}>
+          <div class={styles.itemTopLeft}>
+            <p class={styles.itemTopMain}>{props.item.musicSheetName}</p>
+            <p class={styles.itemTopSub}>{props.item.createTime}</p>
+          </div>
+          <div class={styles.itemTopRight}>
+            <div class={styles.imgWrap}>
+              <img
+                src={scoreInfos[getLeveByScoreId(props.item.score || 0)].img}
+                alt=""
+              />
+            </div>
+            <Icon name="arrow" class={styles.imgIcon} />
+          </div>
+        </div>
+        <div class={styles.itemBottom}>
+          <div class={styles.itemBottomDot}>
+            <p class={styles.dotMain} style={{ color: '#ff5a56' }}>
+              {props.item.score || 0}
+              <span>分</span>{' '}
+            </p>
+            <p class={styles.dotSub}> 综合得分</p>
+          </div>
+          <div class={styles.itemBottomDot}>
+            <p class={styles.dotMain}>
+              {props.item.intonation || 0}
+              <span>分</span>{' '}
+            </p>
+            <p class={styles.dotSub}>音准 </p>
+          </div>
+          <div class={styles.itemBottomDot}>
+            <p class={styles.dotMain}>
+              {props.item.cadence || 0}
+              <span>分</span>{' '}
+            </p>
+            <p class={styles.dotSub}>节奏 </p>
+          </div>
+          <div class={styles.itemBottomDot}>
+            <p class={styles.dotMain}>
+              {props.item.integrity || 0}
+              <span>分</span>{' '}
+            </p>
+            <p class={styles.dotSub}>完成度 </p>
+          </div>
+        </div>
+      </div>
+    );
+  }
+});

+ 2 - 2
src/tenant/main.ts

@@ -15,8 +15,8 @@ import { browser, setAuth } from '@/helpers/utils'
 
 const app = createApp(App)
 
-// import Vconsole from 'vconsole'
-// const vconsole = new Vconsole()
+import Vconsole from 'vconsole'
+const vconsole = new Vconsole()
 postMessage(
   {
     api: 'getVersion'

+ 54 - 0
src/tenant/music/personal/index.module.less

@@ -17,6 +17,13 @@
       color: var(--van-primary);
     }
 
+    .van-tabs__line {
+      width: 24px;
+      height: 4px;
+      background: linear-gradient(90deg, #FF3C81 0%, rgba(255, 118, 166, 0.5) 100%) !important;
+      border-radius: 36px 36px 0px 0px;
+    }
+
     .van-button--plain.van-button--primary {
       background-color: transparent;
     }
@@ -79,4 +86,51 @@
 
 .musicGrid {
   margin: 16px 12px;
+}
+
+.tennatCellGroup {
+  margin: 12px;
+  border-radius: 16px;
+
+  :global {
+    .van-cell {
+      padding: 15px 12px;
+      font-size: 15px;
+    }
+
+    .van-cell__right-icon {
+      font-size: 16px;
+      color: #DADADA;
+    }
+  }
+
+  .tenantLogo {
+    width: 24px;
+    height: 24px;
+    border-radius: 50%;
+    margin-right: 8px;
+  }
+
+  .tenantCoverImg {
+    width: 98px;
+    height: 98px;
+    border-radius: 12px;
+    margin-right: 16px;
+    overflow: hidden;
+  }
+
+  .tenantContent {
+    h2 {
+      font-size: 16px;
+      font-weight: 500;
+      color: #131415;
+      line-height: 24px;
+    }
+
+    p {
+      font-size: 13px;
+      color: #777777;
+      line-height: 24px;
+    }
+  }
 }

+ 2 - 0
src/tenant/music/personal/index.tsx

@@ -12,6 +12,7 @@ import { getRandomKey } from '../music'
 import { useEventTracking } from '@/helpers/hooks'
 import TheSticky from '@/components/the-sticky'
 import ColHeader from '@/components/col-header'
+import TenantAlbum from './tenant-album'
 
 export default defineComponent({
   name: 'MusicPersonal',
@@ -62,6 +63,7 @@ export default defineComponent({
             {/* <Tab title="赠送单曲" name="personal-gift"></Tab>
             <Tab title="赠送专辑" name="album-gift"></Tab> */}
           </Tabs>
+          {activeTab.value === 'train-course' && <TenantAlbum />}
           {(activeTab.value === 'personal' ||
             activeTab.value === 'personal-gift') && (
             <Personal

+ 89 - 0
src/tenant/music/personal/tenant-album.tsx

@@ -0,0 +1,89 @@
+import { defineComponent, reactive, ref, watch } from 'vue'
+import { Cell, CellGroup, Image, List } from 'vant'
+import request from '@/helpers/request'
+import { useRoute, useRouter } from 'vue-router'
+import ColResult from '@/components/col-result'
+import { state } from '@/state'
+import styles from './index.module.less'
+
+export default defineComponent({
+  name: 'tenant-album',
+  props: {},
+  setup(props) {
+    const router = useRouter()
+    const params = reactive({
+      page: 1,
+      rows: 20
+    })
+    const rows = ref<any>([])
+    const data = ref<any>(null)
+    const loading = ref(false)
+    const finished = ref(false)
+    const isError = ref(false)
+
+    const FetchList = async () => {
+      if (loading.value) {
+        return
+      }
+      loading.value = true
+      isError.value = false
+      try {
+        const res = await request.post('/userTenantAlbumRecord/page', {
+          prefix:
+            state.platformType === 'TEACHER' ? '/api-teacher' : '/api-student',
+          data: params
+        })
+        rows.value = [...rows.value, ...res.data.rows]
+        data.value = res.data
+        params.page = res.data.pageNo + 1
+        finished.value = res.data.pageNo >= res.data.totalPage
+      } catch (error) {
+        isError.value = true
+      }
+      loading.value = false
+    }
+
+    return () => (
+      <List
+        loading={loading.value}
+        finished={finished.value}
+        finished-text={rows.value.length ? '没有更多了' : ''}
+        onLoad={FetchList}
+        error={isError.value}
+      >
+        {rows.value.length ? (
+          <CellGroup class={styles.tennatCellGroup} border={false}>
+            <Cell isLink>
+              {{
+                icon: () => <img class={styles.tenantLogo} />,
+                title: () => <div class={styles.tenantName}>测试机构</div>
+              }}
+            </Cell>
+            <Cell>
+              {{
+                icon: () => <Image class={styles.tenantCoverImg} />,
+                title: () => (
+                  <div class={styles.tenantContent}>
+                    <h2>巴赫旧约 | 四号勃兰登堡长笛协奏曲</h2>
+                    <p class="van-multi-ellipsis--l2">
+                      巴赫经典曲目巴赫经典曲目巴赫经典曲目巴赫经典曲目巴赫经典曲目
+                      巴赫经典曲目 巴赫经典曲目 巴赫经典曲目 巴赫经典曲目
+                    </p>
+                  </div>
+                )
+              }}
+            </Cell>
+          </CellGroup>
+        ) : (
+          !loading.value && (
+            <ColResult
+              tips="暂无训练教程"
+              classImgSize="SMALL"
+              btnStatus={false}
+            />
+          )
+        )}
+      </List>
+    )
+  }
+})

+ 83 - 0
src/tenant/music/train-list/index.module.less

@@ -25,6 +25,19 @@
       }
     }
 
+    .van-dropdown-menu__bar {
+      background-color: transparent;
+      box-shadow: none;
+      padding-right: 15px;
+    }
+
+    .van-dropdown-menu__title {
+      padding-left: 0
+    }
+
+    .van-dropdown-menu__title:after {
+      border-color: transparent transparent rgba(0, 0, 0, 0.4) rgba(0, 0, 0, 0.4);
+    }
   }
 }
 
@@ -147,4 +160,74 @@
   span {
     padding-top: 3px;
   }
+}
+
+.searchResult {
+  padding: 16px 16px 0;
+  overflow: hidden;
+  margin-bottom: 20px;
+
+  .searchTitle {
+    font-size: 16px;
+    color: #333333;
+    line-height: 22px;
+  }
+}
+
+.radio-group {
+  display: flex;
+  margin-top: 10px;
+  margin-bottom: 20px;
+  flex-wrap: wrap;
+
+  .radio:first-child {
+    :global {
+      .van-radio__label {
+        margin-left: 0;
+      }
+    }
+  }
+}
+
+.radio {
+  :global {
+    .van-radio__icon {
+      display: none;
+    }
+
+    .van-tag--large {
+      width: 80px;
+      height: 32px;
+      font-size: 16px;
+      text-align: center;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+    }
+
+    .van-tag {
+      box-sizing: border-box;
+      width: 31% !important;
+    }
+
+    .van-tag--default {
+      color: var(--van-tag-text-default-color);
+    }
+
+    .van-tag--primary {
+      background-color: #fff;
+    }
+  }
+}
+
+.organ-radio {
+  :global {
+    .van-tag--large {
+      width: auto;
+      padding: 0 12px;
+      margin-bottom: 8px;
+      margin-right: 8px;
+      font-size: 14px;
+    }
+  }
 }

+ 88 - 64
src/tenant/music/train-list/index.tsx

@@ -1,5 +1,16 @@
 import { defineComponent, nextTick, onMounted, reactive, ref } from 'vue'
-import { Sticky, List, Popup, Icon, Switch, Tabs, Tab } from 'vant'
+import {
+  Sticky,
+  List,
+  Popup,
+  Icon,
+  Switch,
+  Tabs,
+  Tab,
+  DropdownMenu,
+  DropdownItem,
+  Tag
+} from 'vant'
 import Search from '@/components/col-search'
 import request from '@/helpers/request'
 // import Item from './item'
@@ -97,7 +108,6 @@ export default defineComponent({
       tempParams.platform =
         baseState.platformType === 'STUDENT' ? 'ios-student' : 'ios-teacher'
     }
-    const exquisiteFlag = ref(false)
     // 判断是否在搜索页面用过
     if (!hideSearch) {
       if (baseState.platformType === 'TEACHER') {
@@ -107,23 +117,20 @@ export default defineComponent({
         tempParams.subjectIds = getSubject.id
       }
 
-      const getMusic: any = useSubjectId(SubjectEnum.MUSIC_FREE)
-      exquisiteFlag.value = getMusic.chargeType
+      // const getMusic: any = useSubjectId(SubjectEnum.MUSIC_FREE)
     }
     //
     const params = reactive({
       search: (route.query.search as string) || '',
-      // exquisiteFlag: 1,
-      musicTagIds: route.query.tagids || '',
+      subjectType: (route.query.subjectType as string) || '',
       page: 1,
-      ...defauleParams,
       ...tempParams
     })
+    const subjectList = ref<any>([])
     const data = ref<any>(null)
     const loading = ref(false)
     const finished = ref(false)
     const isError = ref(false)
-    const isAudit = ref(true)
 
     const apiSuffix = ref(
       baseState.platformType === 'STUDENT' ? '/api-student' : '/api-teacher'
@@ -143,24 +150,16 @@ export default defineComponent({
       loading.value = true
       isError.value = false
       const tempParams = {
-        ...params,
-        auditStatus: 'PASS',
-        idAndName: params.search,
-        createBy: teacherId
-      }
-      if (exquisiteFlag.value) {
-        tempParams.chargeType = 'FREE'
-      }
-      if (myself) {
-        tempParams.myself = true
-      } else {
-        tempParams.myself = false
+        ...params
       }
 
       try {
-        const res = await request.post(`${apiSuffix.value}/music/sheet/list`, {
-          data: tempParams
-        })
+        const res = await request.post(
+          `${apiSuffix.value}/tenantAlbumMusic/page`,
+          {
+            data: tempParams
+          }
+        )
         if (data.value) {
           const result = (data.value?.rows || []).concat(res.data.rows || [])
           data.value.rows = result
@@ -221,31 +220,33 @@ export default defineComponent({
       id: getSubject.id || ''
     })
 
-    onMounted(async () => {
-      try {
-        if (!browser().iPhone) {
-          isAudit.value = false
-          return
-        }
-        const { data } = await request.get(
-          '/api-admin/appVersionInfo/queryByPlatform',
-          {
-            params: {
-              platform:
-                baseState.platformType === 'TEACHER'
-                  ? 'ios-teacher'
-                  : 'ios-student'
-            }
+    const getSubjectList = async () => {
+      const { data } = await request.get(
+        `${apiSuffix.value}/subject/subjectSelect?type=MUSIC`
+      )
+      if (Array.isArray(data)) {
+        const subject: any = []
+        data.forEach((item: any) => {
+          if (item.subjects && item.subjects.length) {
+            item.subjects.forEach(s => {
+              subject.push(s)
+            })
           }
-        )
-        if (baseState.version > data.version) {
-          isAudit.value = true
-        } else {
-          isAudit.value = false
-        }
-      } catch {
-        //
+        })
+        subjectList.value = subject || []
       }
+    }
+
+    const getSelectCondition = async () => {
+      const { data } = await request.post(
+        `${apiSuffix.value}/tenantAlbumMusic/selectCondition?subjectType=${params.subjectType}`
+      )
+      console.log(data)
+    }
+
+    onMounted(async () => {
+      getSubjectList()
+      getSelectCondition()
     })
 
     expose({
@@ -273,21 +274,44 @@ export default defineComponent({
                   // leftIcon={iconSearch}
                   v-slots={{
                     left: () => (
-                      <div
-                        class={styles.label}
-                        onClick={() => (subject.show = true)}
-                      >
-                        {baseState.platformType === 'TEACHER'
-                          ? teacherDetaultSubject.value.name
-                          : subject.name}
-
-                        <Icon
-                          classPrefix="iconfont"
-                          name="down"
-                          size={12}
-                          color="#131415"
-                        />
-                      </div>
+                      <DropdownMenu>
+                        <DropdownItem title="筛选">
+                          <div
+                            class={styles.searchResult}
+                            style={{ maxHeight: '45vh', overflowY: 'auto' }}
+                          >
+                            <div class={styles.searchTitle}>声部</div>
+                            <div
+                              class={[
+                                styles['radio-group'],
+                                styles.radio,
+                                styles['organ-radio']
+                              ]}
+                            >
+                              {subjectList.value.map((subject: any) => {
+                                const isActive =
+                                  subject.id ===
+                                  Number(params.subjectIds || null)
+                                const type = isActive ? 'primary' : 'default'
+                                return (
+                                  <Tag
+                                    size="large"
+                                    plain={isActive}
+                                    type={type}
+                                    round
+                                    onClick={() => {
+                                      console.log(subject, '1212')
+                                      // this.subject = { ...subject }
+                                    }}
+                                  >
+                                    {subject.name}
+                                  </Tag>
+                                )
+                              })}
+                            </div>
+                          </div>
+                        </DropdownItem>
+                      </DropdownMenu>
                     )
                   }}
                 />
@@ -330,7 +354,7 @@ export default defineComponent({
               ) : (
                 !loading.value && (
                   <ColResult
-                    tips="暂无曲目"
+                    tips="暂无声部训练"
                     classImgSize="SMALL"
                     btnStatus={false}
                   />
@@ -340,7 +364,7 @@ export default defineComponent({
           </div>
 
           {/* 声部弹框 */}
-          <Popup
+          {/* <Popup
             show={subject.show}
             position="bottom"
             round
@@ -358,7 +382,7 @@ export default defineComponent({
               }
               onComfirm={onComfirmSubject}
             />
-          </Popup>
+          </Popup> */}
         </>
       )
     }

+ 5 - 4
src/views/adapay/pay-define/index.tsx

@@ -52,10 +52,10 @@ export default defineComponent({
           }
         )
 
-        console.log(data.paymentVender)
-        state.isYeePay = data.paymentVender
-          ? data.paymentVender.indexOf('yeepay') !== -1
-          : false
+        console.log(data, 'paymentVender')
+        // state.isYeePay = data.paymentVender
+        //   ? data.paymentVender.indexOf('yeepay') !== -1
+        //   : false
         scanCodePay(data.reqParams)
       } catch (e) {
         //
@@ -193,6 +193,7 @@ export default defineComponent({
       const isYeePay = state.paymentType
         ? state.paymentType?.indexOf('yeepay') !== -1
         : false
+      state.isYeePay = isYeePay
       if (browser().weixin) {
         if (pay_channel === 'wx_pub') {
           //授权

+ 1 - 1
src/views/adapay/payment/index.tsx

@@ -119,7 +119,7 @@ export default defineComponent({
           <p>应付金额</p>
           <div class={styles.amount}>
             <span>¥ </span>
-            {moneyFormat(props.paymentConfig.currentPrice)}
+            {moneyFormat(props.paymentConfig.actualPrice)}
           </div>
         </div>
         <RadioGroup v-model={state.payType}>

+ 3 - 3
src/views/order-detail/index.tsx

@@ -201,7 +201,7 @@ export default defineComponent({
         const orderObject = orderStatus.orderObject
 
         console.log(this.paymentVendor, '12')
-        if (this.paymentVersion === 'V1') {
+        if (this.paymentVersion === 'V2') {
           const url =
             state.platformType === 'TEACHER'
               ? '/api-teacher/userOrder/executeOrder'
@@ -326,7 +326,7 @@ export default defineComponent({
         pay_channel: val.pay_channel,
         wxAppId: config.wxAppId,
         alipayAppId: config.alipayAppId,
-        // paymentType: state.paymentType,
+        paymentType: this.orderInfo.paymentType,
         body: config.body,
         price: config.price,
         orderNo: config.merOrderNo,
@@ -486,7 +486,7 @@ export default defineComponent({
           style={{ minHeight: '30%' }}
         >
           {/* 判断类型使用什么去支付 */}
-          {this.paymentVersion === 'V1' ? (
+          {this.paymentVersion === 'V2' ? (
             <Payment
               v-model={this.paymentStatus}
               orderInfo={orderStatus.orderObject}

Some files were not shown because too many files changed in this diff