Browse Source

添加购买

lex 1 year ago
parent
commit
e2455902ae

File diff suppressed because it is too large
+ 1 - 10517
package-lock.json


+ 1 - 0
package.json

@@ -44,6 +44,7 @@
     "qrcode": "^1.5.1",
     "qrcode.vue": "^3.3.3",
     "query-string": "^7.1.1",
+    "swiper": "^11.0.5",
     "tcplayer.js": "^4.8.0",
     "umi-request": "^1.4.0",
     "vant": "^3.4.6",

+ 4 - 1
src/components/col-header/index.tsx

@@ -129,7 +129,8 @@ export default defineComponent({
     }
   },
   render() {
-    return (
+    // 只有app里面才显示头部
+    return browser().isApp ? (
       <div>
         {this.$slots.content ? (
           <div
@@ -175,6 +176,8 @@ export default defineComponent({
           </>
         )}
       </div>
+    ) : (
+      <div></div>
     )
   }
 })

+ 9 - 3
src/helpers/request.ts

@@ -30,10 +30,11 @@ const request = extend({
 // 是否是初始化接口
 let initRequest = false
 let toast: ReturnType<typeof setTimeout>
+let hideErrorMessage = false // 是否隐藏报错信息
 
 request.interceptors.request.use(
   (url, options: any) => {
-    // openLoading();
+    hideErrorMessage = options.hideErrorMessage
     if (!options.hideLoading) {
       clearTimeout(toast)
       Toast.loading({
@@ -81,7 +82,8 @@ request.interceptors.response.use(
     if (res.status > 299 || res.status < 200) {
       clearTimeout(toast)
       const msg = '服务器错误,状态码' + res.status
-      Toast(msg)
+      Toast.clear()
+      !hideErrorMessage && Toast(msg)
       throw new Error(msg)
     }
     const data = await res.clone().json()
@@ -97,7 +99,11 @@ request.interceptors.response.use(
       }
       if (!(data.code === 403 || data.code === 401)) {
         clearTimeout(toast)
-        Toast(msg)
+        Toast.clear()
+        !hideErrorMessage && Toast(msg)
+      }
+      if (data.code === 409) {
+        msg = msg + '409'
       }
       const browserInfo = browser()
       if (data.code === 403) {

+ 7 - 0
src/router/routes-tenant.ts

@@ -70,6 +70,13 @@ const noLoginRouter = [
     meta: {
       title: '作品详情'
     }
+  },
+  {
+    path: '/tenantStudentRejest',
+    component: () => import('@/views/tenantStudentRejest/index'),
+    meta: {
+      title: '机构学员注册'
+    }
   }
 ]
 

+ 1 - 1
src/tenant/activation-code/index.tsx

@@ -151,7 +151,7 @@ export default defineComponent({
                 {state.list.map((item: any) => (
                   <Row>
                     <Col span={5}>{item.activationCode}</Col>
-                    <Col span={5}>{item.purchaseCycle}个月</Col>
+                    <Col span={5}>{item.purchaseCycle}</Col>
                     <Col
                       span={5}
                       class={item.activationStatus ? styles.c1 : styles.c2}

+ 42 - 5
src/tenant/layout/login.tsx

@@ -19,7 +19,8 @@ export default defineComponent({
       countDownStatus: true, // 是否发送验证码
       countDownTime: 1000 * 120, // 倒计时时间
       countDownRef: null as any, // 倒计时实例
-      imgCodeStatus: false
+      imgCodeStatus: false,
+      isTrainGroup: false // 是否直接注册机构小组
     }
   },
   computed: {
@@ -34,8 +35,13 @@ export default defineComponent({
     }
   },
   mounted() {
+    if (this.$route.query.returnUrl === '/train-tool') {
+      this.isTrainGroup = true
+    }
     removeAuth()
     this.directNext()
+
+    console.log(this.$route.query)
   },
   methods: {
     directNext() {
@@ -55,6 +61,7 @@ export default defineComponent({
         if (this.loginType === 'PWD') {
           res = await request.post('/api-auth/usernameLogin', {
             requestType: 'form',
+            hideErrorMessage: this.isTrainGroup,
             data: {
               username: this.username,
               password: this.password,
@@ -65,6 +72,7 @@ export default defineComponent({
         } else {
           res = await request.post('/api-auth/smsLogin', {
             requestType: 'form',
+            hideErrorMessage: this.isTrainGroup,
             data: {
               clientId: 'student',
               clientSecret: 'student',
@@ -77,13 +85,42 @@ export default defineComponent({
         const { authentication } = res.data
         setAuth(authentication.token_type + ' ' + authentication.access_token)
 
-        let userCash = await request.get('/api-student/student/queryUserInfo', {
-          initRequest: true // 初始化接口
-        })
+        const userCash = await request.get(
+          '/api-student/student/queryUserInfo',
+          {
+            initRequest: true // 初始化接口
+          }
+        )
+
+        // 专辑购买
+        if (this.isTrainGroup) {
+          const { tenantGroupId, tenantId } = this.$route.query
+          if (
+            tenantGroupId != userCash.data.tenantGroupId ||
+            tenantId != userCash.data.tenantId
+          ) {
+            setTimeout(() => {
+              Toast('您的所在小组不可购买该教程')
+            }, 100)
+            return
+          }
+        }
         setLogin(userCash.data)
 
         this.directNext()
-      } catch {}
+      } catch (e: any) {
+        // 说明用户不存在
+
+        if (e.message.indexOf('409') > -1) {
+          const { returnUrl, isRegister, ...rest } = this.$route.query
+          this.$router.replace({
+            path: '/tenantStudentRejest',
+            query: {
+              ...rest
+            }
+          })
+        }
+      }
     },
     async onSendCode() {
       // 发送验证码

BIN
src/tenant/music/train-list/icons/icon-select.png


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

@@ -44,6 +44,10 @@
 
     }
 
+    .van-haptics-feedback:active {
+      opacity: 1 !important;
+    }
+
   }
 
   .titleActive {
@@ -51,6 +55,79 @@
   }
 }
 
+
+.albumSearchSection {
+  :global {
+    .van-dropdown-menu__bar {
+      padding-right: 0;
+    }
+  }
+}
+
+.albumSearchTitle {
+  color: #F41E4B;
+  font-size: 14px;
+  background-color: #fff;
+  padding: 6px 21px 2px 8px !important;
+  border-radius: 30px;
+
+  &>div {
+    max-width: 70px;
+  }
+
+  &::after {
+    right: 8px;
+    border-color: transparent transparent #F41E4B #F41E4B !important;
+  }
+}
+
+.albumSearchResult {
+  padding: 14px 10px;
+}
+
+.albumSearchCell {
+  padding: 10px;
+
+  .albumLogo {
+    width: 48px;
+    height: 48px;
+    border-radius: 12px;
+    margin-right: 10px;
+  }
+
+  .albumContent {
+    text-align: left;
+
+    h2 {
+      font-size: 15px;
+      font-weight: 600;
+      color: #131415;
+      line-height: 21px;
+    }
+
+    p {
+      font-size: 12px;
+      color: #777777;
+      line-height: 17px;
+    }
+  }
+
+  &.albumSearchCellActive {
+    border-radius: 10px;
+    background: #FFEAF3;
+
+    .iconSelect {
+      background: url('./icons/icon-select.png') no-repeat center;
+      background-size: contain;
+    }
+  }
+
+  .iconSelect {
+    width: 18px;
+    height: 18px;
+  }
+}
+
 .listContainer {
   padding-top: 2px;
   height: 42px;

+ 63 - 2
src/tenant/music/train-list/index.tsx

@@ -1,5 +1,15 @@
 import { defineComponent, nextTick, onMounted, reactive, ref } from 'vue'
-import { List, DropdownMenu, DropdownItem, Tag, Sticky, Button } from 'vant'
+import {
+  List,
+  DropdownMenu,
+  DropdownItem,
+  Tag,
+  Image,
+  Button,
+  Cell,
+  Radio,
+  RadioGroup
+} from 'vant'
 import Search from '@/components/col-search'
 import request from '@/helpers/request'
 import { useRoute, useRouter } from 'vue-router'
@@ -133,7 +143,58 @@ export default defineComponent({
                 border={false}
                 title={title}
                 color="#131415"
-              />
+              >
+                {{
+                  right: () => (
+                    <DropdownMenu class={styles.albumSearchSection}>
+                      <DropdownItem
+                        titleClass={styles.albumSearchTitle}
+                        title="宫崎骏合集 | 一起感受宫崎骏的"
+                      >
+                        <div
+                          class={styles.albumSearchResult}
+                          style={{ maxHeight: '45vh', overflowY: 'auto' }}
+                        >
+                          <Cell
+                            class={[
+                              styles.albumSearchCell,
+                              styles.albumSearchCellActive
+                            ]}
+                            center
+                          >
+                            {{
+                              icon: () => <Image class={styles.albumLogo} />,
+                              title: () => (
+                                <div class={styles.albumContent}>
+                                  <h2>宫崎骏合集 | 一起感受宫崎骏的夏…</h2>
+                                  <p>到期时间:2025-03-14</p>
+                                </div>
+                              ),
+                              'right-icon': () => (
+                                <div class={styles.iconSelect}></div>
+                              )
+                            }}
+                          </Cell>
+                          <Cell class={styles.albumSearchCell} center>
+                            {{
+                              icon: () => <Image class={styles.albumLogo} />,
+                              title: () => (
+                                <div class={styles.albumContent}>
+                                  <h2>宫崎骏合集 | 一起感受宫崎骏的夏…</h2>
+                                  <p>到期时间:2025-03-14</p>
+                                </div>
+                              ),
+                              'right-icon': () => (
+                                <div class={styles.iconSelect}></div>
+                              )
+                            }}
+                          </Cell>
+                        </div>
+                      </DropdownItem>
+                    </DropdownMenu>
+                  )
+                }}
+              </ColHeader>
               <Search
                 onSearch={onSearch}
                 type="tenant"

BIN
src/tenant/music/train-tool/images/botom-shdow.png


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


BIN
src/tenant/music/train-tool/images/tip_bg.png


+ 184 - 226
src/tenant/music/train-tool/index.module.less

@@ -1,13 +1,15 @@
 .musicContent {
   position: absolute;
   top: 0;
-  height: 265px;
+  height: 365px;
   width: 100%;
   padding-top: 55px;
   z-index: 10;
-  background-color: rgba(0, 0, 0, 0.2);
-  backdrop-filter: blur(20px);
-  -webkit-backdrop-filter: blur(20px);
+  // background-color: rgba(0, 0, 0, 0.2);
+  // backdrop-filter: blur(20px);
+  // -webkit-backdrop-filter: blur(20px);
+
+  background: linear-gradient(270deg, #F5E6B4 0%, #F7A699 100%), linear-gradient(180deg, rgba(246, 246, 246, 0) 0%, #F6F6F6 100%);
 }
 
 
@@ -26,31 +28,126 @@
 .bg {
   position: relative;
   height: 100%;
-  padding: 16px 16px 12px;
+  padding: 16px 0 0;
   z-index: 11;
 }
 
 .alumWrap {
   position: relative;
-  display: flex;
-  align-items: center;
-  flex-direction: column;
-  margin-bottom: 76px;
+  // display: flex;
+  // align-items: center;
+  // flex-direction: column;
+  // margin-bottom: 76px;
+
+  .singleAlbum {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    padding-bottom: 2px;
+    min-height: 130px;
+  }
+
+  :global {
+    .swiper {
+      --swiper-theme-color: #FE2451 !important;
+      --swiper-pagination-bottom: 0px !important;
+      padding-bottom: 15px;
+      min-height: 130px;
+    }
+
+    .swiper-container {
+      width: 100%;
+      height: 100%;
+    }
+
+    .swiper-slide {
+      text-align: center;
+      font-size: 18px;
+      // background: #fff;
+      display: -webkit-box;
+      display: -ms-flexbox;
+      display: -webkit-flex;
+      display: flex;
+      -webkit-box-pack: center;
+      -ms-flex-pack: center;
+      -webkit-justify-content: center;
+      justify-content: center;
+      -webkit-box-align: center;
+      -ms-flex-align: center;
+      -webkit-align-items: center;
+      align-items: center;
+      transition: 300ms;
+      transform: scale(0.8) !important;
+      width: 50%;
+    }
+
+
+    .swiper-slide-active,
+    .swiper-slide-duplicate-active {
+      transform: scale(1) !important;
+    }
+  }
+
+  .quota {
+    position: absolute;
+    right: 0;
+    top: 0;
+    z-index: 11;
+    font-size: 12px;
+    font-weight: 500;
+    color: #FFFFFF;
+    background: linear-gradient(270deg, #FF7B57 0%, #FF3460 100%);
+    border-radius: 0px 0px 0px 6px;
+    padding: 3px 6px 2px;
+  }
 
   .img {
-    width: 118px;
-    height: 118px;
+    margin-bottom: 10px;
+    position: relative;
+    width: 130px;
+    height: 130px;
     flex-shrink: 0;
     border-radius: 6px;
     position: relative;
     z-index: 9;
 
-    --van-image-error-icon-size: 118px;
+    --van-image-error-icon-size: 130px;
+
+
+
+    &::after {
+      content: '';
+      position: absolute;
+      bottom: -4px;
+      left: -9px;
+      width: 148px;
+      height: 10px;
+      background: url('./images/botom-shdow.png') no-repeat center;
+      background-size: contain;
+      z-index: 1;
+    }
+
+    :global {
+      .van-image {
+        position: relative;
+        z-index: 2;
+
+        &::before {
+          content: '';
+          position: absolute;
+          left: 0;
+          top: 0;
+          bottom: 0;
+          width: 9px;
+          background: linear-gradient(270deg, rgba(0, 0, 0, 0.18) 0%, rgba(255, 255, 255, 0) 100%);
+        }
+      }
+    }
   }
 
   .iconPian {
     position: absolute;
-    right: -40px;
+    right: -22px;
     top: 8px;
     z-index: -1;
     width: 110px;
@@ -61,14 +158,14 @@
     background: url('./images/icon-pian.png') no-repeat center;
     background-size: contain;
 
-    :global {
-      .van-image {
-        width: 60px !important;
-        height: 60px !important;
-        border-radius: 50%;
-        overflow: hidden;
-      }
-    }
+    // :global {
+    //   .van-image {
+    //     width: 60px !important;
+    //     height: 60px !important;
+    //     border-radius: 50%;
+    //     overflow: hidden;
+    //   }
+    // }
   }
 
   .numContent {
@@ -93,25 +190,77 @@
   }
 
   .alumTitle {
+    padding-bottom: 8px;
     font-size: 16px;
     font-weight: 600;
-    color: #fff;
+    color: #000000;
     line-height: 24px;
-    padding-bottom: 8px;
   }
 
   .alumDes {
-    position: absolute;
-    bottom: -80px;
-    z-index: 99;
-    width: calc(100% - 96px);
-    padding-top: 16px;
+    width: 100%;
+    padding-top: 10px;
+    padding-bottom: 12px;
     text-align: center;
+    min-height: 64px;
 
-    .des {
 
+    .des {
+      padding: 0 16px;
       font-size: 12px;
-      color: rgba(255, 255, 255, 0.5);
+      color: #000000;
+      line-height: 20px;
+    }
+  }
+}
+
+.albumPriceGroup {
+  margin: 0 13px 12px;
+  height: 36px;
+  background: url('./images/tip_bg.png') no-repeat center;
+  background-size: cover;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  font-size: 13px;
+  padding: 0 12px;
+
+
+  .albumTimer {
+    display: flex;
+    align-items: center;
+    font-weight: 500;
+    color: #5E3314;
+    line-height: 1;
+  }
+
+  .iconTimer {
+    width: 16px;
+    height: 16px;
+    margin-right: 6px;
+  }
+
+
+  .originPrice {
+    font-weight: 500;
+    color: rgba(38, 38, 38, 0.4);
+    line-height: 18px;
+  }
+
+  .currentPrice {
+    padding: 4px 7px;
+    border-radius: 20px;
+    background: #262626;
+
+    margin-left: 6px;
+
+    span {
+      font-weight: 500;
+      color: #FFE1AE;
+      line-height: 18px;
+      background: linear-gradient(180deg, #FFFFFF 0%, #FFC76C 100%);
+      -webkit-background-clip: text;
+      -webkit-text-fill-color: transparent;
     }
   }
 }
@@ -167,7 +316,11 @@
 }
 
 .btnGroup {
-  // background-color: #fff;
+  border-top: 1px solid #F2F2F2;
+  background-color: #fff;
+  padding-top: 12px;
+  padding-left: 25px;
+  padding-right: 25px;
   padding-bottom: calc(12px + env(safe-area-inset-bottom));
 
   :global {
@@ -176,199 +329,4 @@
       font-weight: 500;
     }
   }
-}
-
-
-.system-list::-webkit-scrollbar {
-  display: none;
-  /* Chrome Safari */
-}
-
-.system-list {
-  width: 100%;
-  overflow-x: auto;
-  overflow-y: hidden;
-  display: flex;
-  position: relative;
-  user-select: none;
-  box-sizing: content-box;
-  margin-bottom: 25px;
-  height: auto;
-  transition: all .2s;
-
-  &.systemHide {
-    height: 0;
-    transition: all .2s;
-    margin-bottom: 0px;
-  }
-}
-
-.system-item {
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  justify-content: center;
-  flex: 1 0 auto;
-  width: 96px;
-  min-height: 120px;
-  box-sizing: border-box;
-  background: #ffffff;
-  border-radius: 12px;
-  border: 1px solid #e5e5e5;
-  margin-left: 10px;
-
-  &:last-child {
-    margin-right: 10px;
-  }
-
-  .title {
-    font-size: 14px;
-    font-weight: 500;
-    color: #333333;
-    line-height: 20px;
-  }
-
-  .price {
-    color: #EF2F56;
-    font-size: 25px;
-    line-height: 1.5;
-    font-family: DINAlternate-Bold, DINAlternate;
-    font-weight: bold;
-
-    span {
-      font-size: 16px;
-    }
-  }
-
-  .originalPrice {
-    color: #999999;
-    font-size: 13px;
-  }
-
-  &.active {
-    background: linear-gradient(223deg, #FEECE3 0%, #FEE4E3 52%, #FFDCE6 100%);
-    border: 1px solid #FF4264;
-    position: relative;
-
-    .title {
-      color: #EF2F56;
-    }
-
-
-    .originalPrice {
-      color: #EF2F56;
-    }
-
-    &::before {
-      content: ' ';
-      font: 14px/1 'vant-icon';
-      width: 27px;
-      height: 18px;
-
-      position: absolute;
-      top: -1px;
-      right: -1px;
-      background: url('./images/icon-selected.png') no-repeat center;
-      background-size: contain;
-    }
-  }
-}
-
-.bottom_function {
-  background: url('./images/price-bg.png') no-repeat top center #fff;
-  background-size: contain;
-  box-shadow: inset 0px 1px 0px 0px #FFFFFF;
-  border-radius: 16px 16px 0px 0px;
-  // border: none;
-
-  .iconRightTop {
-    position: absolute;
-    top: -51px;
-    right: 9px;
-    width: 144px;
-    height: 154px;
-  }
-
-  .iconClose {
-    position: absolute;
-    top: -51px;
-    right: 9px;
-    width: 32px;
-    height: 32px;
-    background: url('./images/icon-close.png') no-repeat center;
-    background-size: contain;
-    display: inline-block;
-    z-index: 99;
-  }
-}
-
-
-.popupStatus {
-  overflow-y: initial;
-}
-
-.memberMeal {
-  .titleMeal {
-    display: flex;
-    align-items: center;
-    justify-content: space-between;
-    font-size: 18px;
-    font-weight: 600;
-    color: #131415;
-    line-height: 22px;
-    padding: 26px 24px 26px 13px;
-
-    .iconArrowLine {
-      display: inline-block;
-      width: 14px;
-      height: 14px;
-      background: url('./images/icon-arrow-line.png') no-repeat center;
-      background-size: contain;
-    }
-  }
-}
-
-.btnGroup {
-  // position: fixed;
-  // bottom: 0;
-  // left: 0;
-  // right: 0;
-  // z-index: 100;
-  // background-color: #fff;
-  display: flex;
-  align-items: center;
-  padding: 0 16px 12px;
-  justify-content: space-between;
-
-  .btn {
-    padding: 0 22px;
-    height: 44px;
-    color: #fff !important;
-    background: linear-gradient(270deg, #FF204B 0%, #FE5B71 100%);
-    border-radius: 39px;
-    font-size: 18px;
-    font-weight: bold;
-    border: none;
-
-    .unit {
-      font-size: 14px;
-    }
-  }
-
-  .priceSection {
-    display: flex;
-    align-items: center;
-    font-size: 16px;
-    color: #1a1a1a;
-
-    .price {
-      font-size: 18px;
-      font-weight: bold;
-      color: #ff3535;
-
-      .priceUnit {
-        font-size: 14px;
-      }
-    }
-  }
 }

+ 248 - 279
src/tenant/music/train-tool/index.tsx

@@ -1,5 +1,16 @@
-import { defineComponent, onMounted, reactive, ref } from 'vue'
-import { Image, Tabs, Tab, List, Button, Popup, Dialog, Sticky } from 'vant'
+import { computed, defineComponent, onMounted, reactive, ref, watch } from 'vue'
+import {
+  Image,
+  Tabs,
+  Tab,
+  List,
+  Button,
+  Popup,
+  Dialog,
+  Sticky,
+  Swipe,
+  SwipeItem
+} from 'vant'
 import styles from './index.module.less'
 import TheSticky from '@/components/the-sticky'
 import ColHeader from '@/components/col-header'
@@ -8,6 +19,7 @@ import request from '@/helpers/request'
 import iconMenu from './images/icon-menu.png'
 import iconRightTop from './images/icon-right-top.png'
 import iconAlbumCover from '../../images/icon-album-cover.png'
+import iconTimer from './images/icon-timer.png'
 import { state as baseState } from '@/state'
 import Song from '../component/song'
 import { useRoute, useRouter } from 'vue-router'
@@ -15,6 +27,13 @@ import ColResult from '@/components/col-result'
 import { moneyFormat } from '@/helpers/utils'
 import { orderStatus } from '@/views/order-detail/orderStatus'
 import { postMessage } from '@/helpers/native-message'
+// Import Swiper Vue.js components
+// import Swiper core and required modules
+import { Pagination } from 'swiper/modules'
+import { Swiper, SwiperSlide } from 'swiper/vue'
+// Import Swiper styles
+import 'swiper/css'
+import 'swiper/css/pagination'
 
 export default defineComponent({
   name: 'train-tool',
@@ -36,50 +55,14 @@ export default defineComponent({
       list: [] as any,
       popupStatus: false,
       selectMember: {} as any, // 购买的月份
-      buyList: [
-        {
-          purchaseCycle: 6,
-          salePrice: 0,
-          costPrice: 0,
-          status: true
-        },
-        {
-          purchaseCycle: 12,
-          salePrice: 0,
-          costPrice: 0,
-          status: false
-        },
-        {
-          purchaseCycle: 18,
-          salePrice: 0,
-          costPrice: 0,
-          status: false
-        },
-        {
-          purchaseCycle: 24,
-          salePrice: 0,
-          costPrice: 0,
-          status: false
-        }
-        // {
-        //   purchaseCycle: 30,
-        //   salePrice: 0,
-        //   costPrice: 0,
-        //   status: false
-        // },
-        // {
-        //   purchaseCycle: 36,
-        //   salePrice: 0,
-        //   costPrice: 0,
-        //   status: false
-        // }
-      ],
       ensembleCounts: false,
       musicCounts: false,
       subjectCounts: false,
       tenantAlbumStatus: 0 as any,
       ablumStatus: false,
-      heightV: 0
+      heightV: 0,
+      hasBuyStatus: true, // 是否能继续购买
+      albumList: [] // 专辑列表
     })
     const params = reactive({
       page: 1,
@@ -89,29 +72,44 @@ export default defineComponent({
       baseState.platformType === 'STUDENT' ? '/api-student' : '/api-teacher'
     )
 
+    const isSingleAlbum = computed(() => {
+      const query = route.query
+      if (query.taId || query.albumId) {
+        return true
+      } else {
+        return false
+      }
+    })
+
     const getDetails = async () => {
       try {
-        let url = apiSuffix.value + '/userTenantAlbumRecord/detail'
-        if (state.albumId) {
-          url = url + '?albumId=' + state.albumId
-        }
-        const { data } = await request.post(url)
-        state.details = data || {}
-        state.tenantAlbumStatus = data.tenantAlbumStatus
-        state.ablumStatus = data.status
-        state.buyList.forEach((item: any, index: number) => {
-          item.salePrice = (index + 1) * data.salePrice
-          item.costPrice = (index + 1) * data.costPrice
-        })
-
-        state.selectMember = {
-          ...state.buyList[0]
+        // tenantGroupAlbum/buyAlbumInfo
+        const url =
+          apiSuffix.value +
+          '/tenantGroupAlbum/buyAlbumInfo?tenantGroupAlbumId=' +
+          (route.query.taId || '')
+        // if (state.albumId) {
+        //   url = url + '?albumId=' + state.albumId
+        // }
+        const { data } = await request.get(url)
+        state.albumList = data || []
+        if (state.albumList.length > 0) {
+          state.details = state.albumList[0]
         }
 
-        state.ensembleCounts = data.ensembleCounts <= 0 ? false : true
-        state.subjectCounts = data.subjectCounts <= 0 ? false : true
-        state.musicCounts = data.musicCounts <= 0 ? false : true
+        // state.tenantAlbumStatus = data.tenantAlbumStatus
+        // state.ablumStatus = data.status
+      } catch {
+        //
+      }
+    }
 
+    watch(
+      () => state.details,
+      () => {
+        state.ensembleCounts = state.details?.ensembleCounts <= 0 ? false : true
+        state.subjectCounts = state.details?.subjectCounts <= 0 ? false : true
+        state.musicCounts = state.details?.musicCounts <= 0 ? false : true
         if (state.subjectCounts) {
           state.activeTab = 'SUBJECT'
         } else if (state.musicCounts) {
@@ -138,16 +136,23 @@ export default defineComponent({
         } else if (subjectType == 'ENSEMBLE' && state.ensembleCounts) {
           state.activeTab = 'ENSEMBLE'
         }
-      } catch {
-        //
+
+        if (state.details.buyTimesFlag) {
+          if (state.details.buyedTimes >= state.details.buyTimes) {
+            state.hasBuyStatus = false
+          } else {
+            state.hasBuyStatus = true
+          }
+        } else {
+          state.hasBuyStatus = true
+        }
       }
-    }
+    )
 
     const FetchList = async () => {
       if (state.loading) {
         return
       }
-      console.log(state.details, 'state.details')
       state.loading = true
       state.isError = false
       const tempParams = {
@@ -205,12 +210,12 @@ export default defineComponent({
     })
 
     const onSubmit = async () => {
-      const album = state.selectMember
+      const album = state.details
       const details = state.details
       orderStatus.orderObject.orderType = 'TENANT_ALBUM'
       orderStatus.orderObject.orderName = details.name
       orderStatus.orderObject.orderDesc = details.name
-      orderStatus.orderObject.actualPrice = album.salePrice
+      orderStatus.orderObject.actualPrice = album.actualPrice
       // orderStatus.orderObject.recomUserId = route.query.recomUserId || 0
       // orderStatus.orderObject.activityId = route.query.activityId || 0
       orderStatus.orderObject.orderNo = ''
@@ -218,9 +223,8 @@ export default defineComponent({
         {
           orderType: 'TENANT_ALBUM',
           goodsName: details.name,
-          actualPrice: album.salePrice,
-          // recomUserId: route.query.recomUserId || 0,
-          price: album.salePrice,
+          actualPrice: album.actualPrice,
+          price: album.actualPrice,
           ...details,
           ...album
         }
@@ -289,56 +293,35 @@ export default defineComponent({
 
     return () => (
       <div class={styles.trainTool}>
-        {(state.tenantAlbumStatus === 0 || !state.ablumStatus) &&
-        state.buy != '1' ? (
-          <>
-            <TheSticky
-              position="top"
-              onBarHeight={(height: any) => {
-                console.log(height, 'height', height)
-                state.heightV = height
-              }}
-            >
-              <ColHeader border={false} isFixed={false} />
-            </TheSticky>
-            {!state.loading && (
-              <div
-                style={{
-                  height: 'calc(100vh - var(--header-height))',
-                  display: 'flex',
-                  alignItems: 'center'
-                }}
-              >
-                <ColResult
-                  tips="暂无曲目"
-                  classImgSize="SMALL"
-                  btnStatus={false}
-                />
-              </div>
-            )}
-          </>
-        ) : (
-          <>
-            <TheSticky
-              position="top"
-              onBarHeight={(height: any) => {
-                console.log(height, 'height', height)
-                state.heightV = height
-              }}
-            >
-              <ColHeader
-                background={background.value}
-                border={false}
-                isFixed={false}
-                color={color.value}
-                backIconColor="white"
-              />
-            </TheSticky>
-            <img class={styles.bgImg} src={state.details?.coverImg} />
-            <div class={styles.musicContent}></div>
-            <div class={styles.bg}>
-              <div class={styles.alumWrap}>
+        {!route.query.taId && (
+          <TheSticky
+            position="top"
+            onBarHeight={(height: any) => {
+              state.heightV = height
+            }}
+          >
+            <ColHeader
+              background={background.value}
+              border={false}
+              isFixed={false}
+              color={color.value}
+              backIconColor="white"
+            />
+          </TheSticky>
+        )}
+        {/* <img class={styles.bgImg} src={state.details?.coverImg} /> */}
+        <div class={styles.musicContent}></div>
+        <div class={styles.bg}>
+          <div class={styles.alumWrap}>
+            {isSingleAlbum.value ? (
+              <div class={styles.singleAlbum}>
                 <div class={styles.img}>
+                  {state.details?.buyTimesFlag && (
+                    <span class={styles.quota}>
+                      限购:{state.details?.buyedTimes}/{state.details?.buyTimes}
+                      次
+                    </span>
+                  )}
                   <Image
                     class={styles.image}
                     width="100%"
@@ -347,181 +330,167 @@ export default defineComponent({
                     src={state.details?.coverImg || iconAlbumCover}
                     errorIcon={iconAlbumCover}
                   />
-                  {/* <span class={styles.numContent}>
-                    <img src={iconMenu} class={styles.iconMenu} />共
-                    {state.details?.musicNum}首
-                  </span> */}
-
-                  <div class={styles.iconPian}>
-                    <Image
-                      class={styles.image}
-                      width="100%"
-                      height="100%"
-                      fit="cover"
-                      src={state.details?.coverImg || iconAlbumCover}
-                    />
-                  </div>
-                </div>
-                <div class={styles.alumDes}>
-                  <div class={[styles.alumTitle, 'van-ellipsis']}>
-                    {state.details?.name}
-                  </div>
-                  <div
-                    class={[styles.des, 'van-multi-ellipsis--l2']}
-                    style={{
-                      height: '32px',
-                      lineHeight: '16px'
-                    }}
-                  >
-                    {state.details?.describe}
-                  </div>
+                  <div class={styles.iconPian}></div>
                 </div>
               </div>
-            </div>
-
-            <div class={styles.musicList}>
-              <Sticky position="top" offsetTop={state.heightV}>
-                <Tabs
-                  color="var(--van-primary)"
-                  background="transparent"
-                  lineWidth={20}
-                  shrink
-                  v-model:active={state.activeTab}
-                  onChange={val => {
-                    state.activeTab = val
-
-                    params.page = 1
-                    state.list = []
-                    FetchList()
-                  }}
-                >
-                  {state.subjectCounts && (
-                    <Tab title="声部练习" name="SUBJECT"></Tab>
-                  )}
-                  {state.musicCounts && (
-                    <Tab title="独奏曲目" name="MUSIC"></Tab>
-                  )}
-                  {state.ensembleCounts && (
-                    <Tab title="合奏练习" name="ENSEMBLE"></Tab>
-                  )}
-                </Tabs>
-              </Sticky>
+            ) : (
+              <Swiper
+                watchSlidesProgress={true}
+                slidesPerView={'auto'}
+                centeredSlides={true}
+                modules={[Pagination]}
+                pagination={{ clickable: true }}
+                onSlideChange={(swiper: any) => {
+                  state.details = state.albumList[swiper.activeIndex]
+                }}
+                onTransitionEnd={() => {
+                  params.page = 1
+                  state.list = []
+                  FetchList()
+                }}
+              >
+                {state.albumList.map((album: any) => (
+                  <SwiperSlide>
+                    <div class={styles.img}>
+                      {album.buyTimesFlag && (
+                        <span class={styles.quota}>
+                          限购:{album.buyedTimes}/{album.buyTimes}次
+                        </span>
+                      )}
 
-              <div class={styles.alumnList}>
-                <List
-                  loading={state.loading}
-                  finished={state.finished}
-                  finished-text={' '}
-                  onLoad={FetchList}
-                  immediateCheck={false}
-                  error={state.isError}
-                >
-                  {state.list && state.list.length ? (
-                    <Song
-                      showNumber
-                      list={state.list}
-                      onDetail={(item: any) => {
-                        sessionStorage.setItem(
-                          'tool-subject-type',
-                          state.activeTab as any
-                        )
-                        router.push({
-                          path: '/music-detail',
-                          query: {
-                            id: item.id
-                            // albumId: route.params.id
-                          }
-                        })
-                      }}
-                    />
-                  ) : (
-                    !state.loading && (
-                      <ColResult
-                        tips="暂无曲目"
-                        classImgSize="SMALL"
-                        btnStatus={false}
+                      <Image
+                        class={styles.image}
+                        width="100%"
+                        height="100%"
+                        fit="cover"
+                        src={album?.coverImg || iconAlbumCover}
+                        errorIcon={iconAlbumCover}
                       />
-                    )
-                  )}
-                </List>
+                      <div class={styles.iconPian}></div>
+                    </div>
+                  </SwiperSlide>
+                ))}
+              </Swiper>
+            )}
+
+            <div class={styles.alumDes}>
+              <div class={[styles.alumTitle, 'van-ellipsis']}>
+                {state.details?.name}
+              </div>
+              <div
+                class={[styles.des, 'van-multi-ellipsis--l2']}
+                style={{
+                  height: '32px',
+                  lineHeight: '16px'
+                }}
+              >
+                {state.details?.describe}
               </div>
             </div>
-            {baseState.platformType === 'STUDENT' && state.buy != '1' && (
-              <TheSticky position="bottom">
-                <div class={styles.btnGroup}>
-                  <Button
-                    round
-                    block
-                    disabled={state.details?.musicNum <= 0}
-                    color="linear-gradient(270deg, #FF204B 0%, #FE5B71 100%)"
-                    onClick={() => (state.popupStatus = true)}
-                  >
-                    购买教程
-                  </Button>
+
+            {state.buy != '1' && (
+              <div class={styles.albumPriceGroup}>
+                <div class={styles.albumTimer}>
+                  <img src={iconTimer} class={styles.iconTimer} />
+                  <span>有效期:{state.details?.purchaseNum || 0}天</span>
                 </div>
-              </TheSticky>
-            )}
-          </>
-        )}
+                <div class={styles.albumPriceList}>
+                  {(state.details?.originalPrice || 0) >
+                    (state.details?.actualPrice || 0) && (
+                    <span class={styles.originPrice}>
+                      原价:¥{moneyFormat(state.details?.originalPrice || 0)}
+                    </span>
+                  )}
 
-        <Popup
-          v-model:show={state.popupStatus}
-          position="bottom"
-          round
-          zIndex={9999}
-          safe-area-inset-bottom
-          closeable={false}
-          class={styles.popupStatus}
-          onClose={() => (state.popupStatus = false)}
-          // onClosed={() => (this.openStatus = false)}
-        >
-          <div class={styles.bottom_function}>
-            <i
-              class={styles.iconClose}
-              onClick={() => (state.popupStatus = false)}
-            ></i>
-            <img src={iconRightTop} class={styles.iconRightTop} />
-            <div class={styles.memberMeal}>
-              <div class={styles.titleMeal}>
-                <span>请选择教程购买周期</span>
+                  <span class={styles.currentPrice}>
+                    <span>¥{moneyFormat(state.details?.actualPrice || 0)}</span>
+                  </span>
+                </div>
               </div>
+            )}
+          </div>
+        </div>
 
-              <div class={styles['system-list']}>
-                {state.buyList.map((item: any) => (
-                  <div
-                    class={[
-                      styles['system-item'],
-                      item.status && styles.active
-                    ]}
-                    onClick={() => {
-                      state.buyList.forEach((item: any) => {
-                        item.status = false
-                      })
-                      item.status = true
-                      state.selectMember = item
-                    }}
-                  >
-                    <p class={styles.title}>{item.purchaseCycle}个月</p>
-                    <p class={styles.price}>
-                      <span>¥</span>
-                      {moneyFormat(item.salePrice, '0,0[.]00')}
-                    </p>
-                    {item.salePrice < item.costPrice && (
-                      <del class={styles.originalPrice}>
-                        ¥{moneyFormat(item.costPrice, '0,0[.]00')}
-                      </del>
-                    )}
-                  </div>
-                ))}
-              </div>
-            </div>
+        <div class={styles.musicList}>
+          <Sticky position="top" offsetTop={state.heightV}>
+            <Tabs
+              color="var(--van-primary)"
+              background="transparent"
+              lineWidth={20}
+              shrink
+              v-model:active={state.activeTab}
+              onChange={val => {
+                state.activeTab = val
+
+                params.page = 1
+                state.list = []
+                FetchList()
+              }}
+            >
+              {state.subjectCounts && (
+                <Tab title="声部练习" name="SUBJECT"></Tab>
+              )}
+              {state.musicCounts && <Tab title="独奏曲目" name="MUSIC"></Tab>}
+              {state.ensembleCounts && (
+                <Tab title="合奏练习" name="ENSEMBLE"></Tab>
+              )}
+            </Tabs>
+          </Sticky>
+
+          <div class={styles.alumnList}>
+            <List
+              loading={state.loading}
+              finished={state.finished}
+              finished-text={' '}
+              onLoad={FetchList}
+              immediateCheck={false}
+              error={state.isError}
+            >
+              {state.list && state.list.length ? (
+                <Song
+                  showNumber
+                  list={state.list}
+                  onDetail={(item: any) => {
+                    sessionStorage.setItem(
+                      'tool-subject-type',
+                      state.activeTab as any
+                    )
+                    router.push({
+                      path: '/music-detail',
+                      query: {
+                        id: item.id
+                        // albumId: route.params.id
+                      }
+                    })
+                  }}
+                />
+              ) : (
+                !state.loading && (
+                  <ColResult
+                    tips="暂无曲目"
+                    classImgSize="SMALL"
+                    btnStatus={false}
+                  />
+                )
+              )}
+            </List>
+          </div>
+        </div>
+        {baseState.platformType === 'STUDENT' && state.buy != '1' && (
+          <TheSticky position="bottom">
             <div class={styles.btnGroup}>
-              <Button round block class={styles.btn} onClick={onSubmit}>
-                点击购买
+              <Button
+                round
+                block
+                disabled={state.details?.musicNum <= 0 && !state.hasBuyStatus}
+                color="linear-gradient(270deg, #FF204B 0%, #FE5B71 100%)"
+                onClick={onSubmit}
+              >
+                购买教程
               </Button>
             </div>
-          </div>
-        </Popup>
+          </TheSticky>
+        )}
       </div>
     )
   }

+ 1 - 1
src/tenant/trade/detail.tsx

@@ -84,7 +84,7 @@ export default defineComponent({
                             <>
                               {orderDetail.goodType === 'TENANT_ALBUM' ? (
                                 <span class={styles.t}>
-                                  x{orderDetail.bizInfo?.bizValidTime}个月
+                                  x{orderDetail.bizInfo?.bizValidTime}
                                 </span>
                               ) : (
                                 <span class={styles.t}>永久</span>

+ 1 - 1
src/tenant/trade/index.tsx

@@ -272,7 +272,7 @@ export default defineComponent({
                                   <>
                                     {orderDetail.goodType === 'TENANT_ALBUM' ? (
                                       <span class={styles.t}>
-                                        x{orderDetail.bizInfo?.bizValidTime}个月
+                                        x{orderDetail.bizInfo?.bizValidTime}
                                       </span>
                                     ) : (
                                       <span class={styles.t}>永久</span>

+ 1 - 1
src/tenant/trade/tradeOrder.ts

@@ -146,7 +146,7 @@ export const formatOrderDetail = async (item: any, amount?: IAmount) => {
             orderType: item.goodType,
             goodName: item.goodName,
             ...res,
-            purchaseCycle: item.bizInfo?.bizValidTime || res.purchaseCycle
+            purchaseNum: item.bizInfo?.bizValidTime || res.purchaseCycle
           }
         } catch (e: any) {
           throw new Error(e.message)

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

@@ -13,13 +13,13 @@ export default defineComponent({
   },
   render() {
     const item = this.item
-    console.log(item)
+    // console.log(item)
     return (
       <>
         <div class={styles.album}>
           <Image class={styles.img} src={item.coverImg} />
 
-          {/* <span class={styles.albumType}>{item.purchaseCycle}个月</span> */}
+          {/* <span class={styles.albumType}>{item.purchaseCycle}</span> */}
 
           <div class={styles.content}>
             <h4 class="van-ellipsis">{item.name}</h4>
@@ -31,7 +31,7 @@ export default defineComponent({
 
         <div class={styles.albumWeek}>
           <span class={styles.albumTitle}>购买周期</span>
-          <span class={styles.albumNum}>{item.purchaseCycle}个月</span>
+          <span class={styles.albumNum}>{item.purchaseNum}天</span>
         </div>
       </>
     )

+ 4 - 2
src/views/order-detail/orderStatus.ts

@@ -167,16 +167,18 @@ export const orderTenantInfos = () => {
       }
       params.bizId = item.id
     } else if (item.orderType === 'TENANT_ALBUM') {
+      console.log(item, 'item')
       params.bizContent = {
         tenantAlbumId: item.id,
         actualPrice: item.actualPrice || 0,
         buyNumber: 1,
-        buyMultiple: item.purchaseCycle / 6,
+        buyMultiple: 1,
         clientType: state.platformType
       }
+      params.tenantGroupAlbumId = item.tenantGroupAlbumId
       params.bizId = item.id
       params.buyNumber = 1
-      params.buyMultiple = item.purchaseCycle / 6
+      params.buyMultiple = 1
     } else if (item.orderType === 'LIVE') {
       params.bizContent = {
         groupId: item.courseGroupId

+ 50 - 13
src/views/tenantStudentRejest/index.tsx

@@ -1,12 +1,5 @@
-import ColHeader from '@/components/col-header'
-import ColSearch from '@/components/col-search'
 import {
-  Sticky,
-  Image,
-  List,
   Popup,
-  Icon,
-  Area,
   Field,
   Form,
   CellGroup,
@@ -14,8 +7,7 @@ import {
   Toast,
   Picker,
   DatetimePicker,
-  Overlay,
-  Dialog
+  Overlay
 } from 'vant'
 import ImgCode from '@/components/col-img-code'
 import { defineComponent, onMounted, reactive } from 'vue'
@@ -26,18 +18,20 @@ import rejectSchool from './images/rejest-school.png'
 import subTitle from './images/subTitle.png'
 import centerLogo from './images/center.png'
 import studentText from './images/studentText.png'
-import { useRoute } from 'vue-router'
+import { useRoute, useRouter } from 'vue-router'
 import icon_arrow from './images/icon_arrow.png'
 import rejectBtn from './images/rejectBtn.png'
 import studentSuccess from './images/studentSuccess.png'
 import request from '@/helpers/request'
 import dayjs from 'dayjs'
-import { removeAuth } from '@/helpers/utils'
+import { removeAuth, setAuth } from '@/helpers/utils'
 import { state } from '@/helpers/helpState'
+import { setLogin } from '@/state'
 export default defineComponent({
   name: 'tenantStudentRejest',
   setup() {
     const route = useRoute()
+    const router = useRouter()
     const forms = reactive({
       gender: '',
       name: '',
@@ -113,12 +107,17 @@ export default defineComponent({
           return
         }
 
+        const loginCode = route.query.taId ? true : false
         const res = await request.post('/api-tenant/open/student/save', {
-          data: { ...forms },
+          data: { ...forms, loginCode },
           hideLoading: true
         })
         if (res.code == 200) {
-          data.showSuccess = true
+          if (loginCode) {
+            onLogin(res.data)
+          } else {
+            data.showSuccess = true
+          }
         }
 
         if (res.code == 5004) {
@@ -129,6 +128,44 @@ export default defineComponent({
         //
       }
     }
+
+    const onLogin = async code => {
+      try {
+        if (!code) {
+          Toast('注册失败,请重新注册')
+          return
+        }
+        const res = await request.post('/api-auth/smsLogin', {
+          requestType: 'form',
+          data: {
+            clientId: 'student',
+            clientSecret: 'student',
+            phone: forms.phone,
+            smsCode: code
+          }
+        })
+        const { authentication } = res.data
+        setAuth(authentication.token_type + ' ' + authentication.access_token)
+
+        const userCash = await request.get(
+          '/api-student/student/queryUserInfo',
+          {
+            initRequest: true // 初始化接口
+          }
+        )
+        setLogin(userCash.data)
+
+        router.replace({
+          path: '/train-tool',
+          query: {
+            ...route.query
+          }
+        })
+      } catch {
+        //
+      }
+    }
+
     const getSubjectList = async () => {
       try {
         const res = await request.get('/api-tenant/open/subject/queryPage', {

+ 2 - 2
vite.config.ts

@@ -12,8 +12,8 @@ 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 = 'http://192.168.3.143:8000/'
+const proxyUrl = 'https://dev.colexiu.com/'
+// const proxyUrl = 'http://192.168.3.14:8000/'
 export default defineConfig({
   base: './',
   plugins: [

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