lex 2 лет назад
Родитель
Сommit
ee90bf9b6d

BIN
src/common/images/icon-address.png


+ 5 - 1
src/components/o-popup/index.tsx

@@ -9,6 +9,10 @@ export default defineComponent({
       type: String,
       default: '100%'
     },
+    width: {
+      type: String,
+      default: '100%'
+    },
     destroy: {
       type: Boolean,
       default: false
@@ -86,7 +90,7 @@ export default defineComponent({
         show={this.modelValue}
         transitionAppear={true}
         position={this.position}
-        style={{ height: this.height }}
+        style={{ height: this.height, width: this.width }}
         zIndex={this.zIndex}
         onClosed={() => {
           if (this.destroy) {

+ 278 - 0
src/student/music-group/goods-detail/index.module.less

@@ -0,0 +1,278 @@
+.swipeItemImg,
+.swipe {
+  width: 100%;
+  height: 375px;
+  vertical-align: middle;
+}
+.custom-indicator {
+  position: absolute;
+  right: 5px;
+  bottom: 5px;
+  padding: 4px 8px;
+  font-size: 14px;
+  color: #fff;
+  background: rgba(0, 0, 0, 0.5);
+  border-radius: 12px;
+}
+
+.goodsHead {
+  padding: 8px 0;
+  :global {
+    .van-cell {
+      padding-top: 5px;
+      padding-bottom: 5px;
+    }
+  }
+}
+
+.priceGroup {
+  display: flex;
+  align-items: center;
+  .price {
+    color: #ff4e19;
+    font-size: 24px;
+    font-weight: bold;
+    i {
+      font-size: 16px;
+      font-style: normal;
+    }
+  }
+  .delPrice {
+    font-size: 14px;
+    color: #999999;
+    margin-left: 12px;
+    line-height: 20px;
+  }
+
+  .stock {
+    font-size: 14px;
+    color: #999999;
+  }
+}
+
+.goodsName {
+  font-size: 16px;
+  font-weight: 500;
+  color: #333333;
+  line-height: 22px;
+}
+
+.row {
+  background-color: #fff;
+  padding: var(--van-cell-vertical-padding) var(--van-cell-horizontal-padding);
+  .col {
+    font-size: 16px;
+    color: #333333;
+  }
+}
+
+.radio-group {
+  display: flex;
+  flex-wrap: wrap;
+  // margin-top: 14px;
+}
+
+.radio {
+  margin-right: 8px;
+  margin-bottom: 8px;
+  min-width: 60px;
+  :global {
+    .van-radio__label--disabled {
+      opacity: 0.5;
+    }
+    .van-radio__icon {
+      display: none;
+    }
+    .van-tag--large {
+      height: 27px;
+      font-size: 13px;
+      text-align: center;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+    }
+    .van-tag {
+      box-sizing: border-box;
+    }
+    .van-tag--default {
+      color: #999999;
+    }
+    .van-tag--primary {
+      background-color: #f7f8f9;
+    }
+    .van-radio__label {
+      margin-left: 0;
+    }
+  }
+}
+.badge {
+  :global(.van-badge) {
+    border-radius: 6px 0px 6px 0px;
+    font-size: 12px;
+  }
+}
+
+.section {
+  background: #fff;
+  padding: 12px 0 0;
+}
+
+.detail {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: 14px;
+  color: #999999;
+  line-height: 20px;
+  margin-bottom: 12px;
+  span {
+    padding: 0 10px;
+  }
+
+  &::before,
+  &::after {
+    display: inline-block;
+    content: ' ';
+    width: 40px;
+    height: 3px;
+  }
+  &::before {
+    background: linear-gradient(90deg, rgba(238, 238, 238, 0) 0%, #d8d8d8 100%);
+  }
+  &::after {
+    background: linear-gradient(270deg, rgba(238, 238, 238, 0) 0%, #d8d8d8 100%);
+  }
+}
+
+.photoDetail {
+  padding-bottom: 20px;
+  img {
+    width: 100%;
+    vertical-align: middle;
+  }
+}
+
+.goodsDetail {
+  min-height: 100vh;
+  background-color: #f7f8f9;
+  // margin-bottom: var(--van-action-bar-height);
+}
+
+.actionBar {
+  padding-left: 5px;
+  padding-right: 5px;
+  justify-content: space-between;
+  box-shadow: 0px -10px 10px var(--box-shadow-color);
+  box-sizing: border-box;
+  :global {
+    .van-submit-bar__bar {
+      justify-content: space-between;
+      padding: 0;
+    }
+    .van-action-bar-icon {
+      align-items: center;
+    }
+    .van-action-bar-icon__icon {
+      margin-bottom: 0;
+      line-height: 0;
+    }
+    .van-badge {
+      background: #ff4e19;
+    }
+  }
+}
+
+.addCertBtn {
+  background: #fff;
+  color: var(--van-primary);
+}
+
+.buyGroup {
+  flex-basis: 60%;
+  display: flex;
+  justify-content: center;
+  border: var(--van-button-border-width) solid var(--van-button-primary-border-color) !important;
+  border-radius: 20px;
+  background-color: var(--van-primary);
+  overflow: hidden;
+  box-sizing: border-box;
+}
+.selectWrap {
+  padding-top: 1.5px;
+  font-size: 14px;
+  color: #666;
+  padding-bottom: 12px;
+}
+
+.shareBtn {
+  display: flex;
+  align-items: center;
+  font-size: 14px;
+  color: #666666;
+}
+
+.shareWrap {
+  display: flex;
+  border-radius: 10px;
+  border: 1px solid var(--van-primary);
+  overflow: hidden;
+  padding: 14px;
+  align-items: center;
+  background-color: #fff;
+  margin-top: 16px;
+  .sharePic {
+    width: 100px;
+    height: 100px;
+    border-radius: 8px;
+  }
+  .shareLeft {
+    margin-right: 10px;
+  }
+  .shareRight {
+    flex: 1;
+    overflow: hidden;
+  }
+  .shareShopTitle {
+    font-size: 16px;
+    font-weight: 400;
+    color: #333333;
+    display: -webkit-box;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    -webkit-line-clamp: 2;
+    -webkit-box-orient: vertical;
+  }
+  .shareShopDes {
+    font-size: 14px;
+    font-weight: 400;
+    color: #999999;
+    margin: 10px 0 20px 0;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+  }
+  .shareShopValue {
+    font-size: 16px;
+    color: #ff4e19;
+  }
+  .shareShopOldPrice {
+    color: #e5e5e5;
+    margin-left: 5px;
+  }
+
+  :global {
+    .van-card {
+      background: transparent;
+    }
+  }
+}
+.imagesOverlayWrap {
+  :global {
+    .van-badge__wrapper {
+      top: 40px;
+    }
+    .van-image-preview__index {
+      top: 40px;
+    }
+  }
+}

+ 219 - 0
src/student/music-group/goods-detail/index.tsx

@@ -0,0 +1,219 @@
+import request from '@/helpers/request'
+import { moneyFormat } from '@/helpers/utils'
+import { Swipe, SwipeItem, Image, CellGroup, Cell, showImagePreview } from 'vant'
+import { defineComponent } from 'vue'
+import styles from './index.module.less'
+
+export default defineComponent({
+  name: 'goods-detail',
+  props: {
+    id: {
+      type: String,
+      defualt: ''
+    }
+  },
+  data() {
+    return {
+      albumPics: [] as any[],
+      product: {} as Record<string | number | symbol, any>,
+      radio: 0,
+      skuStockListTemp: [],
+      detailMobileHtml: '',
+      loading: false,
+      addGoodsShow: false,
+      selectGoodsItem: {},
+      cartCount: 0,
+      showType: 'cart',
+      shareShow: false // 分享弹窗
+    }
+  },
+  computed: {
+    skuStockList() {
+      // 处理规格
+      const product = this.product
+      const skuStockList: any =
+        this.skuStockListTemp.length > 0
+          ? this.skuStockListTemp
+          : [
+              {
+                id: -1,
+                price: product.price,
+                pic: product.pic,
+                stock: product.stock,
+                spData: null
+              }
+            ]
+      skuStockList.forEach((item: any) => {
+        if (item.spData) {
+          const spData = JSON.parse(item.spData)
+          item.spDataJson = spData.reduce((spDataJson, value) => {
+            spDataJson += value.value
+            return spDataJson
+          }, '')
+          item.sku = spData
+            .reduce((sku, value) => {
+              sku.push(`${value.key}: ${value.value}`)
+              return sku
+            }, [])
+            .join(',')
+        } else {
+          item.spDataJson = '默认'
+        }
+      })
+      return skuStockList
+    },
+    getPrice() {
+      const item = this.skuStockList.filter((n) => n.id == this.radio) as any
+      if (item && Array.isArray(item) && item.length) {
+        return item[0].price
+      }
+      return 0
+    }
+  },
+  async mounted() {
+    try {
+      this.loading = true
+      const res = await request.get(`/api-student/open/mall/product/detail/${this.id}`)
+      this.loading = false
+      const result = res.data || {}
+      this.albumPics = [result.product.pic]
+        .concat(result.product.albumPics.split(','))
+        .filter((n) => n)
+      this.product = result.product
+      this.skuStockListTemp = result.skuStockList || []
+      if (this.skuStockListTemp.length) {
+        const len = this.skuStockListTemp.length
+        for (let i = 0; i < len; i++) {
+          const item = this.skuStockListTemp[i] as any
+          if (item.stock >= 0) {
+            this.radio = item.id
+            break
+          }
+        }
+      }
+      this.detailMobileHtml = result.product.detailMobileHtml || result.product.detailHtml
+    } catch {
+      //
+    }
+  },
+  methods: {
+    onPreview(index: number) {
+      // 图片预览
+      showImagePreview({
+        images: this.albumPics,
+        startPosition: index,
+        closeable: true,
+        className: styles.imagesOverlayWrap
+      })
+    },
+    onShowImg(target: any) {
+      const { localName } = target.srcElement
+      if (localName !== 'img') {
+        return
+      }
+      let startPosition = 0
+      const domList = document.querySelectorAll('.msgWrap img')
+      const imgList = Array.from(domList).map((item: any, index: number) => {
+        if (target.srcElement == item) {
+          startPosition = index
+        }
+        return item.src
+      })
+
+      showImagePreview({
+        images: imgList,
+        startPosition: startPosition,
+        closeable: true,
+        className: styles.imagesOverlayWrap
+      })
+    },
+    onShowCart(type = 'cart') {
+      this.selectGoodsItem = {
+        price: this.product.pic,
+        stock: this.product.stock,
+        skuStockList: this.skuStockListTemp.length ? this.skuStockListTemp : undefined,
+        brandName: this.product.brandName,
+        productCategoryId: this.product.productCategoryId,
+        name: this.product.name,
+        productSn: this.product.productSn,
+        productSubTitle: this.product.subTitle,
+        id: this.product.id
+      }
+      this.showType = type
+      // 打开购物弹框
+      this.addGoodsShow = true
+    }
+  },
+  render() {
+    const product = this.product
+    const selectSku = this.skuStockList.find((n: any) => n.id === this.radio)
+    return (
+      <div class={styles.goodsDetail}>
+        <Swipe
+          class={styles.swipe}
+          lazyRender
+          v-slots={{
+            indicator: (item: any) =>
+              item.total > 1 && (
+                <div class={styles['custom-indicator']}>
+                  {(item.active || 0) + 1} / {item.total}
+                </div>
+              )
+          }}
+        >
+          {this.albumPics.map((item: string, index: number) => (
+            <SwipeItem>
+              <Image
+                class={styles.swipeItemImg}
+                src={item}
+                onClick={() => this.onPreview(index)}
+                fit="cover"
+              />
+            </SwipeItem>
+          ))}
+        </Swipe>
+
+        <CellGroup border={false} class={[styles.goodsHead, 'mb12']}>
+          <Cell
+            center
+            border={false}
+            v-slots={{
+              title: () => (
+                <div class={styles.priceGroup}>
+                  <span class={styles.price}>
+                    <i>¥</i>
+                    {moneyFormat(this.getPrice)}
+                  </span>
+                  {/* <del class={styles.delPrice}>
+                    ¥{moneyFormat(product.originalPrice)}
+                  </del> */}
+                </div>
+              )
+              // default: () => <div class={styles.stock}>销量4件</div>
+            }}
+          />
+          <Cell
+            center
+            border={false}
+            title={product.name}
+            titleClass={[styles.goodsName, 'van-ellipsis']}
+          />
+        </CellGroup>
+
+        {this.detailMobileHtml && (
+          <div class={[styles.section]}>
+            <div class={styles.detail}>
+              <span>图文详情</span>
+            </div>
+
+            <div
+              class={[styles.photoDetail, 'msgWrap']}
+              onClick={this.onShowImg}
+              v-html={this.detailMobileHtml}
+            ></div>
+          </div>
+        )}
+      </div>
+    )
+  }
+})

+ 10 - 11
src/student/music-group/layout/login.tsx

@@ -24,7 +24,10 @@ export default defineComponent({
       imgCodeStatus: false,
       showPopup: false,
       wxAppId: '', //
-      code: '' // 授权code码
+      code: '', // 授权code码
+
+      // 是否开启微信登录(测试使用)默认为false
+      testIsWeixin: true
     }
   },
   computed: {
@@ -39,7 +42,7 @@ export default defineComponent({
     this.directNext()
 
     // 判断是否是微信,只能微信中打开
-    if (!browser().weixin) {
+    if (!browser().weixin && !this.testIsWeixin) {
       this.showPopup = true
     }
   },
@@ -68,13 +71,6 @@ export default defineComponent({
     directNext() {
       if (state.user.status === 'login' || state.user.status === 'error') {
         const { returnUrl, isRegister, ...rest } = this.$route.query
-        console.log(
-          {
-            ...rest,
-            code: this.code
-          },
-          'jump pre registration'
-        )
 
         const newUrl =
           window.location.origin +
@@ -86,8 +82,11 @@ export default defineComponent({
             ...rest
           })
         // 直接跳转到授权页面
-        this.getAppIdAndCode(newUrl)
-        // this.locationReplace(newUrl)
+        if (this.testIsWeixin) {
+          this.locationReplace(newUrl)
+        } else {
+          this.getAppIdAndCode(newUrl)
+        }
       }
     },
     locationReplace(url: any) {

+ 16 - 0
src/student/music-group/member-bao/index.tsx

@@ -0,0 +1,16 @@
+import { Image } from 'vant'
+import { defineComponent } from 'vue'
+import bg1 from '../pre-apply/images/member_bao-1.png'
+import bg2 from '../pre-apply/images/member_bao-2.png'
+
+export default defineComponent({
+  name: 'member-bao',
+  setup() {
+    return () => (
+      <>
+        <Image src={bg1} />
+        <Image src={bg2} />
+      </>
+    )
+  }
+})

+ 16 - 5
src/student/music-group/pre-apply/component/addres.tsx

@@ -1,10 +1,8 @@
-import { Cell, Icon } from 'vant'
+import { Cell, Icon, Tag } from 'vant'
 import { defineComponent, computed, PropType, reactive, onMounted } from 'vue'
 import styles from './address.module.less'
 import iconAddress from '@common/images/icon-address.png'
-import { postMessage } from '@/helpers/native-message'
 import { useRouter } from 'vue-router'
-import request from '../../request-music'
 
 export default defineComponent({
   name: 'cart-address',
@@ -46,8 +44,8 @@ export default defineComponent({
             class={styles.cell}
             is-link={props.isLink}
             onClick={() => selectAddress()}
+            titleStyle={{ marginLeft: '0' }}
             v-slots={{
-              icon: () => <Icon name={iconAddress} size={19} />,
               title: () => (
                 <div>
                   <span class={styles.userName}>{props.item.name}</span>
@@ -56,6 +54,19 @@ export default defineComponent({
                       props.item.phoneNumber &&
                       props.item.phoneNumber.replace(/^(\d{3})\d{4}(\d+)/, '$1****$2')}
                   </span>
+                  {props.item.defaultStatus && (
+                    <Tag
+                      type="primary"
+                      round
+                      style={{
+                        'vertical-align': 'text-top',
+                        marginLeft: '10px',
+                        padding: '1px 8px'
+                      }}
+                    >
+                      默认
+                    </Tag>
+                  )}
                 </div>
               ),
               label: () => <span class={styles.addressInfo}>{addressInfo.value}</span>
@@ -67,7 +78,7 @@ export default defineComponent({
             is-link={props.isLink}
             onClick={() => selectAddress()}
             v-slots={{
-              icon: () => <Icon name={iconAddress} size={19} />,
+              icon: () => <Icon name={iconAddress} size={28} />,
               title: () => <div class={styles.emtry}>去填写收货地址</div>
             }}
           ></Cell>

+ 23 - 3
src/student/music-group/pre-apply/component/address.module.less

@@ -12,11 +12,29 @@
   }
 }
 .cell {
+  position: relative;
   align-items: center;
+  padding: 13px 12px 18px;
+  &::before {
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    content: ' ';
+    display: block;
+    height: 3px;
+    width: 100%;
+    background: url('../images/icon-address-border.png') repeat center left;
+    background-size: 90%;
+  }
   :global {
     .van-cell__title {
       margin-left: 14px;
     }
+    .van-cell__right-icon {
+      font-size: 20px;
+      color: #d8d8d8;
+    }
   }
 }
 .userName {
@@ -26,13 +44,15 @@
 }
 .phone {
   font-size: 16px;
-  color: #333;
+  color: #777;
   margin-left: 14px;
 }
 .addressInfo {
   font-size: 14px;
-  color: #666;
+  color: #777;
+  line-height: 20px;
 }
 .emtry {
-  padding-top: 2px;
+  font-size: 14px;
+  color: #333;
 }

+ 113 - 23
src/student/music-group/pre-apply/component/payment.tsx

@@ -15,10 +15,14 @@ import { defineComponent, nextTick, onMounted, reactive, ref } from 'vue'
 import styles from '../index.module.less'
 import radioCheck from '@/common/images/icon-radio-check.png'
 import radioDefault from '@/common/images/icon-radio-default.png'
+import iconGives from '../images/icon-gives.png'
 import { useRoute, useRouter } from 'vue-router'
 import request from '@/helpers/request'
 import { moneyFormat } from '@/helpers/utils'
 import { CountUp } from 'countup.js'
+import OPopup from '@/components/o-popup'
+import MemberBao from '../../member-bao'
+import GoodsDetail from '../../goods-detail'
 
 export default defineComponent({
   name: 'payment',
@@ -38,7 +42,10 @@ export default defineComponent({
       orderInfo: {
         needPrice: 0,
         originalPrice: 0
-      }
+      },
+      memberBaoStatus: false, // 团练宝详情状态
+      goodsStatus: false, //
+      selectGoodsId: null as any
     })
 
     // 查询未支付订单
@@ -316,31 +323,59 @@ export default defineComponent({
                     ),
                     title: () => (
                       <div class={styles.section}>
-                        <Image class={styles.img} src={state.goodsInfo.goodsUrl} />
+                        <Image
+                          class={styles.img}
+                          src={state.goodsInfo.goodsUrl}
+                          onClick={(e: any) => {
+                            e.stopPropagation()
+                            state.selectGoodsId = state.goodsInfo.goodsId
+                            state.goodsStatus = true
+                          }}
+                        />
                         <div class={styles.sectionContent}>
                           <h2>{state.goodsInfo.goodsName}</h2>
-                          <Tag type="primary">{state.goodsInfo.brandName}</Tag>
+                          <Tag
+                            color="linear-gradient(135deg, #FF8C4A 0%, #FF531C 100%)"
+                            textColor="#fff"
+                            class={styles.brandName}
+                          >
+                            {state.goodsInfo.brandName}
+                          </Tag>
                           <p class={styles.model}>{state.goodsInfo.desciption}</p>
                         </div>
                       </div>
                     )
                   }}
                 </Cell>
-                <Cell>
+                <Cell border={false}>
                   {{
                     title: () => (
                       <div class={styles.extra}>
                         <div class={styles.sectionPrice}>
                           <p class={styles.price}>
-                            新团特惠:<span>¥{moneyFormat(state.goodsInfo.currentPrice)}</span>
+                            新团特惠:
+                            <span class={styles.numFont}>
+                              <span class={styles.numPrefix}>¥</span>
+                              {moneyFormat(state.goodsInfo.currentPrice)}
+                            </span>
                           </p>
                           <p class={styles.originPrice}>
-                            原价:<del>¥{moneyFormat(state.goodsInfo.originalPrice)}</del>
+                            原价:
+                            <del class={styles.numFont}>
+                              ¥{moneyFormat(state.goodsInfo.originalPrice)}
+                            </del>
                           </p>
                         </div>
-                        <div class={styles.sectionTips}>
-                          赠价值{state.repaireInfo.originalPrice}元乐器维保服务一年
-                        </div>
+                      </div>
+                    )
+                  }}
+                </Cell>
+                <Cell center class={styles.gives}>
+                  {{
+                    title: () => (
+                      <div class={styles.sectionTips}>
+                        <Image src={iconGives} class={styles.iconGives} />
+                        赠价值{state.repaireInfo.originalPrice}元乐器维保服务一年
                       </div>
                     )
                   }}
@@ -384,10 +419,24 @@ export default defineComponent({
                     ),
                     title: () => (
                       <div class={styles.section}>
-                        <Image class={styles.img} src={state.textBookInfo.goodsUrl} />
+                        <Image
+                          class={styles.img}
+                          src={state.textBookInfo.goodsUrl}
+                          onClick={(e: any) => {
+                            e.stopPropagation()
+                            state.selectGoodsId = state.textBookInfo.goodsId
+                            state.goodsStatus = true
+                          }}
+                        />
                         <div class={styles.sectionContent}>
                           <h2>{state.textBookInfo.goodsName}</h2>
-                          <Tag type="primary">{state.textBookInfo.brandName}</Tag>
+                          <Tag
+                            color="linear-gradient(135deg, #FF8C4A 0%, #FF531C 100%)"
+                            textColor="#fff"
+                            class={styles.brandName}
+                          >
+                            {state.textBookInfo.brandName}
+                          </Tag>
                           <p class={styles.model}>{state.textBookInfo.description}</p>
                         </div>
                       </div>
@@ -401,14 +450,26 @@ export default defineComponent({
                         <div class={styles.sectionPrice}>
                           <p class={styles.price}>
                             新团特惠:
-                            <span class={styles.free}>
-                              {state.textBookInfo.currentPrice > 0
-                                ? moneyFormat(state.textBookInfo.currentPrice)
-                                : '免费赠送'}
+                            <span
+                              class={[
+                                state.textBookInfo.currentPrice > 0 ? styles.numFont : styles.free
+                              ]}
+                            >
+                              {state.textBookInfo.currentPrice > 0 ? (
+                                <>
+                                  <span class={styles.numPrefix}>¥</span>
+                                  {moneyFormat(state.textBookInfo.currentPrice)}
+                                </>
+                              ) : (
+                                '免费'
+                              )}
                             </span>
                           </p>
                           <p class={styles.originPrice}>
-                            原价:<del>¥{moneyFormat(state.textBookInfo.originalPrice)}</del>
+                            原价:
+                            <del class={styles.numFont}>
+                              ¥{moneyFormat(state.textBookInfo.originalPrice)}
+                            </del>
                           </p>
                         </div>
                       </div>
@@ -449,10 +510,23 @@ export default defineComponent({
                     ),
                     title: () => (
                       <div class={styles.section}>
-                        <Image class={styles.img} src={state.vipInfo.goodsUrl} />
+                        <Image
+                          class={styles.img}
+                          src={state.vipInfo.goodsUrl}
+                          onClick={(e: any) => {
+                            e.stopPropagation()
+                            state.memberBaoStatus = true
+                          }}
+                        />
                         <div class={styles.sectionContent}>
                           <h2>{state.vipInfo.goodsName}</h2>
-                          <Tag type="primary">6个月</Tag>
+                          <Tag
+                            color="linear-gradient(135deg, #FF8C4A 0%, #FF531C 100%)"
+                            textColor="#fff"
+                            class={styles.brandName}
+                          >
+                            6个月
+                          </Tag>
                           <p class={styles.model}>{state.vipInfo.description}</p>
                         </div>
                       </div>
@@ -465,10 +539,17 @@ export default defineComponent({
                       <div class={styles.extra}>
                         <div class={styles.sectionPrice}>
                           <p class={styles.price}>
-                            新团特惠:<span>¥{moneyFormat(state.vipInfo.currentPrice)}</span>
+                            新团特惠:
+                            <span class={styles.numFont}>
+                              <span class={styles.numPrefix}>¥</span>
+                              {moneyFormat(state.vipInfo.currentPrice)}
+                            </span>
                           </p>
                           <p class={styles.originPrice}>
-                            原价:<del>¥{moneyFormat(state.vipInfo.originalPrice)}</del>
+                            原价:
+                            <del class={styles.numFont}>
+                              ¥{moneyFormat(state.vipInfo.originalPrice)}
+                            </del>
                           </p>
                         </div>
                       </div>
@@ -485,13 +566,14 @@ export default defineComponent({
             <div class={styles.payemntPrice}>
               <p class={styles.needPrice}>
                 支付金额:
-                <span>
-                  ¥<i style="font-style: normal" id="needPrice"></i>
+                <span class={styles.numFont}>
+                  <span>¥</span>
+                  <i style="font-style: normal" id="needPrice"></i>
                 </span>
               </p>
               <p class={styles.allPrice}>
                 总原价:
-                <del>¥{moneyFormat(state.orderInfo.originalPrice)}</del>
+                <del class={styles.numFont}>¥{moneyFormat(state.orderInfo.originalPrice)}</del>
               </p>
             </div>
             <div class={styles.paymentBtn}>
@@ -505,6 +587,14 @@ export default defineComponent({
             </div>
           </div>
         </OSticky>
+
+        <OPopup v-model:modelValue={state.memberBaoStatus} position="right">
+          <MemberBao />
+        </OPopup>
+
+        <OPopup v-model:modelValue={state.goodsStatus} position="right" destroy>
+          {state.goodsStatus && <GoodsDetail id={state.selectGoodsId} />}
+        </OPopup>
       </>
     )
   }

BIN
src/student/music-group/pre-apply/images/banner.png


BIN
src/student/music-group/pre-apply/images/icon-address-border.png


BIN
src/student/music-group/pre-apply/images/icon-gives.png


BIN
src/student/music-group/pre-apply/images/member_bao-1.png


BIN
src/student/music-group/pre-apply/images/member_bao-2.png


+ 64 - 37
src/student/music-group/pre-apply/index.module.less

@@ -44,41 +44,36 @@
   .banner {
     background: url('./images/banner.png') no-repeat center center;
     background-size: cover;
-    height: 235px;
+    height: 142px;
     width: 100%;
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    flex-direction: column;
     .orchestraName {
       display: block;
-      padding: 0 25px;
-      font-size: 24px;
-      font-weight: 600;
+      padding: 86px 18px 0;
+      max-width: 230px;
+      font-size: 16px;
       color: #ffffff;
-      line-height: 38px;
-      letter-spacing: 1px;
-      text-shadow: 2px 2px 0px #d83d00;
       text-align: justify;
-      text-align: center;
-    }
-    .tips {
-      margin-top: 24px;
-      padding: 5px 11px;
-      background-color: #fff;
-      border-radius: 16px 0 16px 0;
-      font-size: 15px;
-      font-weight: 600;
-      color: #e45729;
     }
   }
 }
 
 .applyTitle {
-  padding: 20px 13px 12px;
+  display: flex;
+  align-items: center;
+  padding: 20px 20px 12px;
   font-size: 16px;
   font-weight: 600;
   color: #333333;
+
+  &::before {
+    display: inline-block;
+    content: ' ';
+    margin-right: 6px;
+    width: 4px;
+    height: 14px;
+    background: linear-gradient(180deg, #ffb790 0%, #ff8057 100%);
+    border-radius: 3px;
+  }
 }
 .applyCellGroup {
   margin: 0 13px;
@@ -116,15 +111,11 @@
 .paymentTips {
   background: #ffffff;
   border-radius: 10px;
-  padding: 18px 12px;
-  font-size: 15px;
-  color: #333333;
-  p {
-    padding-bottom: 20px;
-    &:last-child {
-      padding-bottom: 0;
-    }
-  }
+  padding: 12px 14px;
+  font-size: 14px;
+  color: #777;
+  line-height: 20px;
+  text-align: justify;
 }
 
 .paymentContainer {
@@ -142,6 +133,10 @@
       font-size: 22px;
       font-weight: bold;
       color: #ff4e19;
+      span {
+        font-size: 18px;
+        margin-right: 2px;
+      }
     }
   }
   .allPrice {
@@ -159,6 +154,8 @@
 
 .sectionCell {
   padding: 15px 12px;
+  border-radius: 10px;
+  overflow: hidden;
   --van-checkbox-border-color: transparent;
   :global {
     .van-cell {
@@ -185,8 +182,9 @@
       font-size: 14px;
       color: #333333;
       padding-right: 12px;
+      font-weight: 400;
       span {
-        font-size: 22px;
+        font-size: 16px;
         font-weight: bold;
         color: #ff4e19;
       }
@@ -194,10 +192,25 @@
         font-size: 14px;
       }
     }
+  }
+
+  .gives {
+    margin-top: 18px;
+    padding-top: 8px;
+    border-top: 1px solid #f2f2f2;
     .sectionTips {
-      padding-top: 8px;
-      font-size: 12px;
+      display: flex;
+      align-items: center;
+      font-size: 14px;
       color: #ff4e19;
+      padding: 5px 6px;
+      background: #ffebdd;
+      border-radius: 6px;
+    }
+    .iconGives {
+      width: 32px;
+      height: 18px;
+      margin-right: 8px;
     }
   }
 
@@ -222,13 +235,20 @@
     }
   }
 }
+.numFont {
+  font-family: 'DINA';
+  .numPrefix {
+    font-size: 14px !important;
+    margin-right: 2px;
+  }
+}
 .section {
   display: flex;
   align-items: center;
 
   .img {
-    width: 90px;
-    height: 90px;
+    width: 88px;
+    height: 88px;
     border-radius: 6px;
     overflow: hidden;
     flex-shrink: 0;
@@ -242,10 +262,17 @@
     line-height: 22px;
   }
 
+  .brandName {
+    line-height: 18px;
+    font-size: 12px;
+    padding: 0 6px;
+    border-radius: 4px;
+  }
+
   .model {
     padding-top: 3px;
     font-size: 13px;
-    color: #333333;
+    color: #777;
     line-height: 18px;
   }
 }

+ 28 - 58
src/student/music-group/pre-apply/index.tsx

@@ -16,7 +16,6 @@ export default defineComponent({
   setup() {
     const route = useRoute()
     const router = useRouter()
-    const bannerRef = ref()
     const state = reactive({
       tabValue: 'apply',
       heightV: 235,
@@ -24,7 +23,10 @@ export default defineComponent({
       purchase: false, // 购买状态
       register: true, // 是否注册
       // showPopup: false,
-      code: '' as any
+      code: '' as any,
+
+      // 是否开启微信登录(测试使用)默认为false
+      testIsWeixin: true
     })
 
     const onNext = async (name: string) => {
@@ -45,20 +47,6 @@ export default defineComponent({
           '/api-student/orchestraRegister/registerStatus/' + route.query.id
         )
         state.registerInfo = data || {}
-        const name = data.orchestraName
-        // const name = '华中科技大学大学同济医学院附'
-        // console.log(name.length)
-        if (name.length > 12 && name.length / 12 > 1 && name.length / 12 <= 2) {
-          const len = name.substring(12, 24)
-          if (len.length < 5) {
-            const splitLen = Math.ceil(name.length / 2)
-            const first = name.substring(0, splitLen)
-            const last = name.substring(splitLen, name.length)
-            state.registerInfo.orchestraName = first + '<br />' + last
-          } else {
-            state.registerInfo.orchestraName = name
-          }
-        }
 
         // 判断是否报名注册过
         state.register = data.register
@@ -179,54 +167,36 @@ export default defineComponent({
     }
 
     // 先请求接口 判断是否有code
-    if (browser().weixin) {
-      // 微信公众号支付
-      //授权
-      const code = getUrlCode()
-      if (!code) {
-        getAppIdAndCode()
+    if (state.testIsWeixin) {
+      getRegisterStatus()
+    } else {
+      if (browser().weixin) {
+        // 微信公众号支付
+        //授权
+        const code = getUrlCode()
+        if (!code) {
+          getAppIdAndCode()
+        } else {
+          state.code = code
+          getRegisterStatus()
+        }
       } else {
-        state.code = code
-        getRegisterStatus()
+        setLogout()
+        const query = {
+          returnUrl: route.path,
+          ...route.query
+        } as any
+        router.replace({
+          path: '/loginMusic',
+          query: query
+        })
       }
-    } else {
-      setLogout()
-      const query = {
-        returnUrl: route.path,
-        ...route.query
-      } as any
-      router.replace({
-        path: '/loginMusic',
-        query: query
-      })
     }
 
-    // onMounted(() => {
-    // state.code = route.query.code || ''
-    // const { height } = useRect(bannerRef.value)
-    // state.heightV = height
-    // 判断是否是微信,只能微信中打开
-    // if (browser().weixin) {
-    //   // 微信公众号支付
-    //   //授权
-    //   const code = getUrlCode()
-    //   if (!code || !state.code) {
-    //     getAppIdAndCode()
-    //   } else {
-    //     state.code = code
-    //   }
-    // }
-    // })
     return () => (
       <div class={styles.preApply}>
-        <div class={styles.banner} ref={bannerRef}>
-          {state.registerInfo.orchestraName && (
-            <>
-              <p class={styles.orchestraName} v-html={state.registerInfo.orchestraName}></p>
-
-              <div class={styles.tips}>快来参加乐团报名吧!</div>
-            </>
-          )}
+        <div class={styles.banner}>
+          <p class={styles.orchestraName}>{state.registerInfo.orchestraName}</p>
         </div>
 
         <Sticky position="top">

+ 65 - 5
src/student/music-group/pre-apply/order-detail.module.less

@@ -12,8 +12,10 @@
 .cartConfirmBox {
   padding: 0;
   margin-bottom: 12px;
-  border-radius: 6px;
+  border-radius: 10px;
   overflow: hidden;
+  // border-bottom: 3px solid;
+  // border-image-source: url('./images/icon-address-border.png');
   .cartItem {
     margin: 0;
     border-radius: 0;
@@ -32,6 +34,17 @@
   margin-left: 13px;
 }
 
+.protocol {
+  box-shadow: none !important;
+  padding: 8px 0 !important;
+  background: #ffebdd;
+  :global {
+    .van-checkbox__label {
+      color: #777;
+    }
+  }
+}
+
 .paymentContainer {
   display: flex;
   align-items: center;
@@ -40,6 +53,7 @@
   padding-left: 12px;
   padding-right: 12px;
   padding-bottom: calc(20px + env(safe-area-inset-bottom));
+  box-shadow: none !important;
   .needPrice {
     display: flex;
     align-items: center;
@@ -83,17 +97,63 @@
     line-height: 24px;
   }
 
+  .numFont {
+    font-family: 'DINA';
+    .numPrefix {
+      font-size: 14px !important;
+      margin-right: 2px;
+    }
+  }
+
   .goodsContent {
+    // h2 {
+    //   font-size: 16px;
+    //   font-weight: 500;
+    //   color: #333333;
+    //   line-height: 22px;
+    // }
+    .goodsNum {
+      font-size: 18px;
+      color: #777777;
+      line-height: 20px;
+      flex-shrink: 0;
+    }
+    .goodsPrice {
+      padding-top: 4px;
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      .free {
+        font-size: 14px;
+      }
+    }
+    .goodsNums {
+      font-size: 18px;
+      font-weight: bold;
+      color: #fc1a19;
+    }
     h2 {
       font-size: 16px;
       font-weight: 500;
       color: #333333;
       line-height: 22px;
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
     }
-    .goodsNum {
-      font-size: 14px;
-      color: #777777;
-      line-height: 20px;
+
+    .brandName {
+      line-height: 18px;
+      font-size: 12px;
+      padding: 0 6px;
+      border-radius: 4px;
+    }
+
+    .model {
+      padding-top: 3px;
+      font-size: 13px;
+      color: #777;
+      line-height: 18px;
     }
   }
 }

+ 68 - 13
src/student/music-group/pre-apply/order-detail.tsx

@@ -14,6 +14,8 @@ import OProtocol from '@/components/o-protocol'
 import OPopup from '@/components/o-popup'
 import UserAuth from './component/user-auth'
 import qs from 'query-string'
+import MemberBao from '../member-bao'
+import GoodsDetail from '../goods-detail'
 
 export default defineComponent({
   name: 'order-detail',
@@ -34,7 +36,10 @@ export default defineComponent({
       freight: '', // 运费
       agreeStatus: true, //是否勾选协议
       showHeader: false,
-      authShow: false // 是否进行实名认证
+      authShow: false, // 是否进行实名认证
+      memberBaoStatus: false, // 团练宝详情状态
+      goodsStatus: false, //
+      selectGoodsId: null as any
     })
 
     const orderType = computed(() => {
@@ -381,21 +386,64 @@ export default defineComponent({
           <CellGroup style={{ margin: 0 }}>
             {state.goodsInfos &&
               state.goodsInfos.map((goods: any) => (
-                <Cell class={styles.cellItem} center>
+                <Cell
+                  class={styles.cellItem}
+                  center
+                  onClick={() => {
+                    if (goods.goodsType === 'INSTRUMENTS' || goods.goodsType === 'TEXTBOOK') {
+                      state.selectGoodsId = goods.goodsId
+                      state.goodsStatus = true
+                    } else if (goods.goodsType === 'VIP') {
+                      state.memberBaoStatus = true
+                    }
+                  }}
+                >
                   {{
                     icon: () => <Image class={styles.img} src={goods.goodsUrl} />,
                     title: () => (
                       <div class={styles.goodsContent}>
-                        <h2>{goods.goodsName}</h2>
+                        {/* <h2>{goods.goodsName}</h2>
                         <Tag type="primary">{goods.brandName}</Tag>
-                        <p class={styles.goodsNum}>{goods.goodsType === 'VIP' ? '6个月' : 'x 1'}</p>
+                        <p class={styles.goodsNum}>{goods.goodsType === 'VIP' ? '6个月' : 'x 1'}</p> */}
+
+                        <h2>
+                          <span>{goods.goodsName}</span>
+                          <span class={styles.goodsNum}>
+                            {goods.goodsType === 'VIP' ? '6个月' : 'x 1'}
+                          </span>
+                        </h2>
+                        <div class={styles.goodsPrice}>
+                          <Tag
+                            color="linear-gradient(135deg, #FF8C4A 0%, #FF531C 100%)"
+                            textColor="#fff"
+                            class={styles.brandName}
+                          >
+                            {goods.brandName}
+                          </Tag>
+                          <span
+                            class={[
+                              styles.goodsNums,
+                              goods.paymentCashAmount > 0 ? styles.numFont : styles.free
+                            ]}
+                          >
+                            {goods.paymentCashAmount > 0 ? (
+                              <>
+                                <span class={styles.numPrefix}>¥</span>
+                                {moneyFormat(goods.paymentCashAmount)}
+                              </>
+                            ) : (
+                              '免费'
+                            )}
+                          </span>
+                        </div>
+                        <p class={styles.model}>{goods.description}</p>
                       </div>
-                    ),
-                    value: () => (
-                      <span class={styles.cellPrice}>
-                        {goods.currentPrice > 0 ? '¥' + moneyFormat(goods.currentPrice) : '赠送'}
-                      </span>
                     )
+                    // value: () => (
+                    //   <span class={styles.cellPrice}>
+                    //     {goods.currentPrice > 0 ? '¥' + moneyFormat(goods.currentPrice) : '赠送'}
+                    //   </span>
+                    // )
                   }}
                 </Cell>
               ))}
@@ -404,17 +452,16 @@ export default defineComponent({
           {orderType.value === 'ORCHESTRA' && (
             <Cell class={styles.freight} title="运费" value={state.freight}></Cell>
           )}
+        </div>
 
+        <OSticky position="bottom" background="white">
           <div class={styles.protocol}>
             <OProtocol
               v-model:modelValue={state.agreeStatus}
               showHeader={state.showHeader}
-              style={{ paddingLeft: 0, paddingRight: 0 }}
+              style={{ paddingTop: 0, paddingBottom: 0 }}
             />
           </div>
-        </div>
-
-        <OSticky position="bottom" background="white">
           <div class={styles.paymentContainer}>
             <div class={styles.payemntPrice}>
               <p class={styles.needPrice}>
@@ -499,6 +546,14 @@ export default defineComponent({
         <OPopup v-model:modelValue={state.authShow}>
           <UserAuth onSuccess={onAuthSuccess} hideHeader={!browser().isApp} />
         </OPopup>
+
+        <OPopup v-model:modelValue={state.memberBaoStatus} position="right">
+          <MemberBao />
+        </OPopup>
+
+        <OPopup v-model:modelValue={state.goodsStatus} position="right" destroy>
+          {state.goodsStatus && <GoodsDetail id={state.selectGoodsId} />}
+        </OPopup>
       </>
     )
   }