lex-xin hai 1 semana
pai
achega
390e793d08

BIN=BIN
src/tenant/music/train-tool/images/icon-bell.png


BIN=BIN
src/tenant/music/train-tool/images/icon-lock.png


+ 49 - 13
src/tenant/music/train-tool/index.module.less

@@ -11,7 +11,7 @@
   :global {
     input,
     textarea {
-      caret-color: #FE2451 !important;
+      caret-color: #fe2451 !important;
     }
     // 选择框
     // 上拉选择 - ✅
@@ -229,6 +229,34 @@
     padding: 3px 6px 2px;
   }
 
+  .iconLock {
+    position: absolute;
+    left: 0;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    z-index: 10;
+    width: 100%;
+    height: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    flex-direction: column;
+    background-color: rgba(0, 0, 0, 0.4);
+
+    img {
+      width: 18px;
+      height: 18px;
+      margin-bottom: 6px;
+    }
+    p {
+      font-weight: 400;
+      font-size: 14px;
+      color: #ffffff;
+      line-height: 20px;
+    }
+  }
+
   .img {
     margin-bottom: 10px;
     position: relative;
@@ -361,6 +389,11 @@
     font-weight: 500;
     color: #5e3314;
     line-height: 1;
+    span span {
+      font-weight: 500;
+      font-size: 13px;
+      color: #f20000;
+    }
   }
 
   .iconTimer {
@@ -428,7 +461,7 @@
     // line-height: 50px;
     line-height: auto;
     .van-cell__title {
-      text-align: center; 
+      text-align: center;
       padding: 0;
       color: #333333;
       font-size: 16px;
@@ -455,7 +488,7 @@
   .van-dropdown-item__option--active {
     .van-cell__title {
       font-weight: 600;
-      color: #FE2451;
+      color: #fe2451;
       text-align: center;
       background: rgba(254, 36, 81, 0.08);
       border-radius: 10px;
@@ -535,8 +568,6 @@
       background-color: #f6f6f6 !important;
       margin-bottom: 10px !important;
     }
-
-    
   }
 
   .alumnList {
@@ -572,7 +603,6 @@
   }
 }
 
-
 .searchResult {
   padding: 16px 13px 12px;
   overflow: hidden;
@@ -588,9 +618,9 @@
 }
 .resetting {
   color: #333333 !important;
-  border-color: #DBDBDB !important;
+  border-color: #dbdbdb !important;
   &::before {
-    border-color: #DBDBDB !important;
+    border-color: #dbdbdb !important;
   }
 }
 
@@ -637,10 +667,10 @@
 
     .van-tag--primary {
       background: #fff3f5;
-      border-color: #FE2451 !important;
-      color: #FE2451 !important;
+      border-color: #fe2451 !important;
+      color: #fe2451 !important;
       &::before {
-        border-color: #FE2451 !important;
+        border-color: #fe2451 !important;
       }
     }
   }
@@ -663,7 +693,7 @@
   :global {
     .van-button {
       font-size: 16px;
-      font-weight: 500;
+      font-weight: 600;
       & + .van-button {
         margin-left: 15px;
       }
@@ -683,7 +713,7 @@
   :global {
     .van-button {
       font-size: 16px;
-      font-weight: 500;
+      font-weight: 600;
 
       &.van-button--disabled {
         opacity: initial;
@@ -693,6 +723,12 @@
           #ff9daa 100%
         ) !important;
       }
+
+      .van-button__text {
+        span + span {
+          padding-left: 8px;
+        }
+      }
     }
   }
 }

+ 258 - 203
src/tenant/music/train-tool/index.tsx

@@ -31,6 +31,8 @@ import request from '@/helpers/request'
 import Search from '@/components/col-search'
 import iconAlbumCover from '../../images/icon-album-cover.png'
 import iconTimer from './images/icon-timer.png'
+import iconBell from './images/icon-bell.png'
+import iconLock from './images/icon-lock.png'
 import iconArrow from './images/icon-arrow.png'
 import { state as baseState, setLogout } from '@/state'
 import Song from '../component/song'
@@ -48,7 +50,7 @@ import { Swiper, SwiperSlide } from 'swiper/vue'
 import 'swiper/css'
 import 'swiper/css/pagination'
 import CourseItem from '../lessonCourseware/component/CourseItem'
-
+import dayjs from 'dayjs'
 
 export default defineComponent({
   name: 'train-tool',
@@ -96,7 +98,7 @@ export default defineComponent({
       teacherSubjectName: null as any,
       teacherSubjectIndex: 0,
       subjectList: [] as any, // 声部列表
-      instrumentId: '',
+      instrumentId: ''
     })
     // const params = reactive({
     //   keyword: (route.query.search as string) || '',
@@ -117,13 +119,13 @@ export default defineComponent({
     })
     const searchRef = ref()
     const params = reactive({
-      keyword: toolSubject?.keyword || null as any,
+      keyword: toolSubject?.keyword || (null as any),
       // subjectType: '',
-      subjectId: toolSubject?.subjectId ||null,
+      subjectId: toolSubject?.subjectId || null,
       // albumId: route.query.albumId,
       // albumName: '',
-      level: toolSubject?.level ||'',
-      type: toolSubject?.type ||'',
+      level: toolSubject?.level || '',
+      type: toolSubject?.type || '',
       courseTypeCode: '',
       // title: '',
       page: 1,
@@ -188,6 +190,20 @@ export default defineComponent({
           // }
           const { data } = await request.get(url)
           state.albumList = data || []
+
+          state.albumList.forEach((item: any) => {
+            let albumStatus = ''
+            if (!item.endTime) {
+              albumStatus = 'NO_BUY'
+            } else if (dayjs().isBefore(dayjs(item.endTime))) {
+              albumStatus = 'EXPIRED'
+            } else {
+              albumStatus = 'NORMAL'
+            }
+            item.albumStatus = albumStatus
+            item.endTime = dayjs(item.endTime).format('YYYY-MM-DD')
+          })
+
           if (state.albumList.length > 0) {
             let index = 0
             // 以缓存为优先 其次 请求头 state.albumId
@@ -341,7 +357,10 @@ export default defineComponent({
           (item: any) => item.id == state.teacherSubjectId
         )
         state.teacherSubjectIndex = index === -1 ? 0 : index
-        state.instrumentId = index === -1 ? state.subjectList[0]?.instrumentId : state.subjectList[index]?.instrumentId
+        state.instrumentId =
+          index === -1
+            ? state.subjectList[0]?.instrumentId
+            : state.subjectList[index]?.instrumentId
       } catch (e) {
         console.log(e)
       }
@@ -442,7 +461,7 @@ export default defineComponent({
         : 'ENSEMBLE'
       setTimeout(() => {
         state.showLoading = false
-      }, 0);
+      }, 0)
     }
     const onSubmit = async () => {
       const album = state.details
@@ -645,7 +664,7 @@ export default defineComponent({
                         modules={[Pagination]}
                         pagination={{ clickable: true }}
                         onSlideChange={(swiper: any) => {
-                          if(state.initLoadPage) return
+                          if (state.initLoadPage) return
                           params.subjectId = null
                           params.keyword = null
                           params.level = ''
@@ -659,7 +678,7 @@ export default defineComponent({
                           }
                           state.details = state.albumList[swiper.activeIndex]
                           // 等tab渲染完了之后再切换 不然tab会自动重新赋值
-                          nextTick(async() => {
+                          nextTick(async () => {
                             // 当有初始值的时候不刷新
                             // if (state.initialSlide) {
                             //   state.initialSlide = 0
@@ -684,6 +703,19 @@ export default defineComponent({
                                   限购{album.buyedTimes}/{album.buyTimes}次
                                 </span>
                               )}
+                              {/* 是否解锁 并且 未购买 */}
+                              {state.details?.albumStatus !== 'NORMAL' &&
+                                state.buy != '1' && (
+                                  <div class={styles.iconLock}>
+                                    <img src={iconLock} />
+                                    <p>
+                                      {state.details?.albumStatus === 'NO_BUY'
+                                        ? '未开通'
+                                        : '已过期'}
+                                    </p>
+                                  </div>
+                                )}
+
                               <Image
                                 class={styles.image}
                                 width="100%"
@@ -718,10 +750,29 @@ export default defineComponent({
                   {state.buy != '1' && baseState.platformType === 'STUDENT' && (
                     <div class={styles.albumPriceGroup}>
                       <div class={styles.albumTimer}>
-                        <img src={iconTimer} class={styles.iconTimer} />
-                        <span>有效期:{state.details?.purchaseNum || 0}天</span>
+                        <img
+                          src={
+                            state.details?.albumStatus === 'NORMAL'
+                              ? iconTimer
+                              : iconBell
+                          }
+                          class={styles.iconTimer}
+                        />
+                        {state.details?.albumStatus === 'NO_BUY' && (
+                          <span>开通教程,解锁高效训练方式!</span>
+                        )}
+                        {state.details?.albumStatus === 'EXPIRED' && (
+                          <span>教程续费,解锁优质训练资源!</span>
+                        )}
+                        {state.details?.albumStatus === 'NORMAL' && (
+                          <span>
+                            <span>{state.details?.endTime}</span>
+                            到期,续费后有效期将延长
+                          </span>
+                        )}
                       </div>
-                      <div class={styles.albumPriceList}>
+
+                      {/* <div class={styles.albumPriceList}>
                         {(state.details?.originalPrice || 0) >
                           (state.details?.actualPrice || 0) && (
                           <del class={styles.originPrice}>
@@ -735,7 +786,7 @@ export default defineComponent({
                             ¥{moneyFormat(state.details?.actualPrice || 0)}
                           </span>
                         </span>
-                      </div>
+                      </div> */}
                     </div>
                   )}
                 </div>
@@ -764,19 +815,22 @@ export default defineComponent({
                       FetchList()
                     }}
                   >
-                    {!state.showLoading && <>
-                      {state.coursewareCounts && (
-                        <Tab title="云课堂" name="COURSEWARE"></Tab>
-                      )}
-                      {state.subjectCounts && (
-                        <Tab title="基础云练" name="SUBJECT"></Tab>
-                      )}
-                      {state.musicCounts && (
-                        <Tab title="独奏云练" name="MUSIC"></Tab>
-                      )}
-                      {state.ensembleCounts && (
-                        <Tab title="合奏云练" name="ENSEMBLE"></Tab>
-                      )}</>}
+                    {!state.showLoading && (
+                      <>
+                        {state.coursewareCounts && (
+                          <Tab title="云课堂" name="COURSEWARE"></Tab>
+                        )}
+                        {state.subjectCounts && (
+                          <Tab title="基础云练" name="SUBJECT"></Tab>
+                        )}
+                        {state.musicCounts && (
+                          <Tab title="独奏云练" name="MUSIC"></Tab>
+                        )}
+                        {state.ensembleCounts && (
+                          <Tab title="合奏云练" name="ENSEMBLE"></Tab>
+                        )}
+                      </>
+                    )}
                   </Tabs>
                   <Search
                     modelValue={params.keyword}
@@ -793,188 +847,180 @@ export default defineComponent({
                     type="tenant"
                     v-slots={{
                       left: () =>
-                        isSearchStatus.value && state.activeTab !== 'COURSEWARE' && (
+                        isSearchStatus.value &&
+                        state.activeTab !== 'COURSEWARE' && (
                           <DropdownMenu zIndex={2999}>
-                              <DropdownItem
-                                onOpen={() => {
-                                  const targetElement: any =
-                                    document.querySelector('.musicList')
-                                  const targetPosition =
-                                    targetElement.getBoundingClientRect().top +
-                                    window.scrollY
+                            <DropdownItem
+                              onOpen={() => {
+                                const targetElement: any =
+                                  document.querySelector('.musicList')
+                                const targetPosition =
+                                  targetElement.getBoundingClientRect().top +
+                                  window.scrollY
 
-                                  window.scrollTo({
-                                    top: targetPosition - state.heightV + 1
-                                  })
+                                window.scrollTo({
+                                  top: targetPosition - state.heightV + 1
+                                })
+                              }}
+                              teleport="body"
+                              titleClass={
+                                params.subjectId || params.type || params.level
+                                  ? styles.titleActive
+                                  : ''
+                              }
+                              title="筛选"
+                              ref={searchRef}
+                            >
+                              <div
+                                class={styles.searchResult}
+                                style={{
+                                  maxHeight: '45vh',
+                                  overflowY: 'auto'
                                 }}
-                                teleport="body"
-                                titleClass={
-                                  params.subjectId ||
-                                  params.type ||
-                                  params.level
-                                    ? styles.titleActive
-                                    : ''
-                                }
-                                title="筛选"
-                                ref={searchRef}
                               >
-                                <div
-                                  class={styles.searchResult}
-                                  style={{
-                                    maxHeight: '45vh',
-                                    overflowY: 'auto'
+                                {searchObj.value[state.activeTab].subjects &&
+                                  searchObj.value[state.activeTab].subjects
+                                    .length > 0 && (
+                                    <>
+                                      <div class={styles.searchTitle}>声部</div>
+                                      <div
+                                        class={[
+                                          styles['radio-group'],
+                                          styles.radio,
+                                          styles['organ-radio']
+                                        ]}
+                                      >
+                                        {searchObj.value[
+                                          state.activeTab
+                                        ].subjects.map((subject: any) => {
+                                          const isActive =
+                                            subject.id === params.subjectId
+                                          const type = isActive
+                                            ? 'primary'
+                                            : 'default'
+                                          return (
+                                            <Tag
+                                              size="large"
+                                              plain={isActive}
+                                              type={type}
+                                              round
+                                              onClick={() => {
+                                                params.subjectId = subject.id
+                                              }}
+                                            >
+                                              {subject.name}
+                                            </Tag>
+                                          )
+                                        })}
+                                      </div>
+                                    </>
+                                  )}
+                                {searchObj.value[state.activeTab].levelList &&
+                                  searchObj.value[state.activeTab].levelList
+                                    .length > 0 && (
+                                    <>
+                                      <div class={styles.searchTitle}>级别</div>
+                                      <div
+                                        class={[
+                                          styles['radio-group'],
+                                          styles.radio,
+                                          styles['organ-radio']
+                                        ]}
+                                      >
+                                        {searchObj.value[
+                                          state.activeTab
+                                        ].levelList.map((subject: any) => {
+                                          const isActive =
+                                            subject.id === params.level
+                                          const type = isActive
+                                            ? 'primary'
+                                            : 'default'
+                                          return (
+                                            <Tag
+                                              size="large"
+                                              plain={isActive}
+                                              type={type}
+                                              round
+                                              onClick={() => {
+                                                params.level = subject.id
+                                              }}
+                                            >
+                                              {subject.value}
+                                            </Tag>
+                                          )
+                                        })}
+                                      </div>
+                                    </>
+                                  )}
+                                {searchObj.value[state.activeTab].typeList &&
+                                  searchObj.value[state.activeTab].typeList
+                                    .length > 0 && (
+                                    <>
+                                      <div class={styles.searchTitle}>类型</div>
+                                      <div
+                                        class={[
+                                          styles['radio-group'],
+                                          styles.radio,
+                                          styles['organ-radio']
+                                        ]}
+                                      >
+                                        {searchObj.value[
+                                          state.activeTab
+                                        ].typeList.map((subject: any) => {
+                                          const isActive =
+                                            subject.id === params.type
+                                          const type = isActive
+                                            ? 'primary'
+                                            : 'default'
+                                          return (
+                                            <Tag
+                                              size="large"
+                                              plain={isActive}
+                                              type={type}
+                                              round
+                                              onClick={() => {
+                                                params.type = subject.id
+                                              }}
+                                            >
+                                              {subject.value}
+                                            </Tag>
+                                          )
+                                        })}
+                                      </div>
+                                    </>
+                                  )}
+                              </div>
+
+                              <div class={[styles.btnGroup2, 'btnMore']}>
+                                <Button
+                                  class={styles.resetting}
+                                  type="primary"
+                                  plain
+                                  round
+                                  onClick={() => {
+                                    params.subjectId = null
+                                    params.level = ''
+                                    params.type = ''
                                   }}
                                 >
-                                  {searchObj.value[state.activeTab].subjects &&
-                                    searchObj.value[state.activeTab].subjects
-                                      .length > 0 && (
-                                      <>
-                                        <div class={styles.searchTitle}>
-                                          声部
-                                        </div>
-                                        <div
-                                          class={[
-                                            styles['radio-group'],
-                                            styles.radio,
-                                            styles['organ-radio']
-                                          ]}
-                                        >
-                                          {searchObj.value[
-                                            state.activeTab
-                                          ].subjects.map((subject: any) => {
-                                            const isActive =
-                                              subject.id === params.subjectId
-                                            const type = isActive
-                                              ? 'primary'
-                                              : 'default'
-                                            return (
-                                              <Tag
-                                                size="large"
-                                                plain={isActive}
-                                                type={type}
-                                                round
-                                                onClick={() => {
-                                                  params.subjectId = subject.id
-                                                }}
-                                              >
-                                                {subject.name}
-                                              </Tag>
-                                            )
-                                          })}
-                                        </div>
-                                      </>
-                                    )}
-                                  {searchObj.value[state.activeTab].levelList &&
-                                    searchObj.value[state.activeTab].levelList
-                                      .length > 0 && (
-                                      <>
-                                        <div class={styles.searchTitle}>
-                                          级别
-                                        </div>
-                                        <div
-                                          class={[
-                                            styles['radio-group'],
-                                            styles.radio,
-                                            styles['organ-radio']
-                                          ]}
-                                        >
-                                          {searchObj.value[
-                                            state.activeTab
-                                          ].levelList.map((subject: any) => {
-                                            const isActive =
-                                              subject.id === params.level
-                                            const type = isActive
-                                              ? 'primary'
-                                              : 'default'
-                                            return (
-                                              <Tag
-                                                size="large"
-                                                plain={isActive}
-                                                type={type}
-                                                round
-                                                onClick={() => {
-                                                  params.level = subject.id
-                                                }}
-                                              >
-                                                {subject.value}
-                                              </Tag>
-                                            )
-                                          })}
-                                        </div>
-                                      </>
-                                    )}
-                                  {searchObj.value[state.activeTab].typeList &&
-                                    searchObj.value[state.activeTab].typeList
-                                      .length > 0 && (
-                                      <>
-                                        <div class={styles.searchTitle}>
-                                          类型
-                                        </div>
-                                        <div
-                                          class={[
-                                            styles['radio-group'],
-                                            styles.radio,
-                                            styles['organ-radio']
-                                          ]}
-                                        >
-                                          {searchObj.value[
-                                            state.activeTab
-                                          ].typeList.map((subject: any) => {
-                                            const isActive =
-                                              subject.id === params.type
-                                            const type = isActive
-                                              ? 'primary'
-                                              : 'default'
-                                            return (
-                                              <Tag
-                                                size="large"
-                                                plain={isActive}
-                                                type={type}
-                                                round
-                                                onClick={() => {
-                                                  params.type = subject.id
-                                                }}
-                                              >
-                                                {subject.value}
-                                              </Tag>
-                                            )
-                                          })}
-                                        </div>
-                                      </>
-                                    )}
-                                </div>
-
-                                <div class={[styles.btnGroup2,  'btnMore']}>
-                                  <Button
-                                    class={styles.resetting}
-                                    type="primary"
-                                    plain
-                                    round
-                                    onClick={() => {
-                                      params.subjectId = null
-                                      params.level = ''
-                                      params.type = ''
-                                    }}
-                                  >
-                                    重置
-                                  </Button>
-
-                                  <Button
-                                    class={styles.confirm}
-                                    type="primary"
-                                    color="linear-gradient( 270deg, #FF204B 0%, #FE5B71 100%)"
-                                    round
-                                    block
-                                    onClick={() => {
-                                      onSearch(params.keyword)
-                                      searchRef.value?.toggle()
-                                    }}
-                                  >
-                                    确定
-                                  </Button>
-                                </div>
-                              </DropdownItem>
+                                  重置
+                                </Button>
 
+                                <Button
+                                  class={styles.confirm}
+                                  type="primary"
+                                  color="linear-gradient( 270deg, #FF204B 0%, #FE5B71 100%)"
+                                  round
+                                  block
+                                  onClick={() => {
+                                    onSearch(params.keyword)
+                                    searchRef.value?.toggle()
+                                  }}
+                                >
+                                  确定
+                                </Button>
+                              </div>
+                            </DropdownItem>
                           </DropdownMenu>
                         )
                     }}
@@ -1094,7 +1140,16 @@ export default defineComponent({
                       color="linear-gradient(270deg, #FF204B 0%, #FE5B71 100%)"
                       onClick={onSubmit}
                     >
-                      开通训练教程
+                      {/* 开通训练教程 */}
+                      <span>
+                        ¥{state.details?.actualPrice || 0}/
+                        {state.details?.purchaseNum || 0}天
+                      </span>
+                      <span>
+                        {state.details?.albumStatus === 'NO_BUY'
+                          ? '立即开通'
+                          : '立即续费'}
+                      </span>
                     </Button>
                   </div>
                 </TheSticky>

+ 1 - 1
vite.config.ts

@@ -12,7 +12,7 @@ function resolve(dir: string) {
 // https://vitejs.dev/config/
 // https://github.com/vitejs/vite/issues/1930 .env
 // const proxyUrl = 'https://online.colexiu.com/'
-const proxyUrl = 'https://test.colexiu.com/'
+const proxyUrl = 'https://dev.colexiu.com/'
 // const proxyUrl = 'http://192.168.3.14:8000/'
 export default defineConfig({
   base: './',