Jelajahi Sumber

Merge branch 'colxiu-style-update'

lex 1 tahun lalu
induk
melakukan
f5b7023bb4

+ 9 - 6
src/teacher/share-page/share-mall/index.tsx

@@ -42,7 +42,7 @@ export default defineComponent({
   },
   computed: {
     getPrice() {
-      let item = this.skuStockList.filter(n => n.id == this.radio) as any
+      const item = this.skuStockList.filter(n => n.id == this.radio) as any
       if (item && Array.isArray(item) && item.length) {
         return item[0].price
       }
@@ -61,7 +61,8 @@ export default defineComponent({
           },
           query
         )
-        params.promoterId = query.userType && query.userType == 'STUDENT' ? '' : params.promoterId
+        params.promoterId =
+          query.userType && query.userType == 'STUDENT' ? '' : params.promoterId
         // 自动跳转到学生端商品详情
         if (browser().ios) {
           window.location.replace(
@@ -94,7 +95,9 @@ export default defineComponent({
       const query = this.$route.query
       const str =
         origin +
-        `/student/#/goodsDetail?id=${query.bizId}&promoterId=${query.userType && query.userType == 'STUDENT' ? '' : query.userId}`
+        `/student/#/goodsDetail?id=${query.bizId}&promoterId=${
+          query.userType && query.userType == 'STUDENT' ? '' : query.userId
+        }&p=${query.p}`
       shareCall(str, {})
     }
   },
@@ -171,7 +174,7 @@ export default defineComponent({
       }
       let startPosition = 0
       const domList = document.querySelectorAll('.msgWrap img')
-      let imgList = Array.from(domList).map((item: any, index: number) => {
+      const imgList = Array.from(domList).map((item: any, index: number) => {
         if (target.srcElement == item) {
           startPosition = index
         }
@@ -193,9 +196,9 @@ export default defineComponent({
       }
       const { origin } = location
       const query = this.$route.query
-      let str =
+      const str =
         origin +
-        `/student/#/goodsDetail?id=${query.bizId}&promoterId=${query.userId}`
+        `/student/#/goodsDetail?id=${query.bizId}&promoterId=${query.userId}&p=${query.p}`
       shareCall(str, {})
       setTimeout(() => {
         location.href = origin + '/student/#/download'

+ 312 - 280
src/views/shop-mall/goods-detail/index.module.less

@@ -1,280 +1,312 @@
-.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 {
-  img {
-    width: 100%;
-    vertical-align: middle;
-  }
-}
-
-.goodsDetail {
-  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;
-    }
-  }
-}
+.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 {
+  img {
+    width: 100%;
+    vertical-align: middle;
+  }
+}
+
+.goodsDetail {
+  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;
+    }
+  }
+}
+
+.cartDisabled {
+  opacity: 0.5;
+}

+ 446 - 431
src/views/shop-mall/goods-detail/index.tsx

@@ -1,431 +1,446 @@
-import request from '@/helpers/request'
-import { browser, moneyFormat } from '@/helpers/utils'
-import {
-  Swipe,
-  SwipeItem,
-  Image,
-  CellGroup,
-  Cell,
-  ImagePreview,
-  RadioGroup,
-  Radio,
-  Tag,
-  Row,
-  Col,
-  Sticky,
-  ActionBar,
-  ActionBarButton,
-  ActionBarIcon,
-  Icon,
-  Badge,
-  Toast,
-  Popup,
-  SubmitBar,
-  Card
-} from 'vant'
-import { defineComponent } from 'vue'
-import styles from './index.module.less'
-import iconShopCart from '../images/icon-shop-cart.png'
-import AddGoodsCart from '../modal/add-goods-cart'
-import ColHeader from '@/components/col-header'
-import iconShare from '../images/icon-share.svg'
-import ColShare from '@/components/col-share'
-import { state } from '@/state'
-import { useEventTracking } from '@/helpers/hooks'
-
-export default defineComponent({
-  name: 'goods-detail',
-  data() {
-    const query = this.$route.query
-    return {
-      id: query.id,
-      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() {
-      let item = this.skuStockList.filter(n => n.id == this.radio) as any
-      if (item && Array.isArray(item) && item.length) {
-        return item[0].price
-      }
-      return 0
-    },
-
-    shareUrl() {
-      // 分享链接
-      const productId = this.product.id as any
-      if (browser().isApp) {
-        return `${location.origin}/teacher/#/shareMall?bizId=${productId}&userId=${state.user.data.userId}&userType=${state.platformType}`
-      } else {
-        return `${location.origin}/teacher.html#/shareMall?bizId=${productId}&userId=${state.user.data.userId}&userType=${state.platformType}`
-      }
-    }
-  },
-  async mounted() {
-    try {
-      this.loading = true
-      const res = await request.get(
-        `/api-mall-portal/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) {
-        let len = this.skuStockListTemp.length
-        for (let i = 0; i < len; i++) {
-          let item = this.skuStockListTemp[i] as any
-          if (item.stock >= 0) {
-            this.radio = item.id
-            break
-          }
-        }
-      }
-      this.detailMobileHtml = result.product.detailMobileHtml
-    } catch {}
-    this.getCartCount()
-    useEventTracking('商品详情')
-  },
-  methods: {
-    onPreview(index: number) {
-      // 图片预览
-      ImagePreview({
-        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')
-      let imgList = Array.from(domList).map((item: any, index: number) => {
-        if (target.srcElement == item) {
-          startPosition = index
-        }
-        return item.src
-      })
-
-      ImagePreview({
-        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
-    },
-    onBuy() {
-      // 购买
-      if (!this.radio) {
-        return Toast('请选择规格')
-      }
-      console.log(true)
-    },
-    async getCartCount() {
-      try {
-        let { code, data } = await request.get('/api-mall-portal/cart/list')
-        if (code === 200) {
-          this.cartCount = data.length
-        }
-      } catch (err) {}
-    }
-  },
-  render() {
-    const product = this.product
-    const selectSku = this.skuStockList.find((n: any) => n.id === this.radio)
-    const sharePic = this.product.pic + '?v=' + Date.now()
-    return (
-      <div class={styles.goodsDetail}>
-        <ColHeader
-          v-slots={{
-            right: () => (
-              <div
-                class={styles.shareBtn}
-                onClick={() => (this.shareShow = true)}
-              >
-                <Icon name={iconShare} size={14} color="#666" />
-                <span style={{ marginLeft: '3px' }}>分享</span>
-              </div>
-            )
-          }}
-        />
-        <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>
-
-        <Row class={[styles.row, 'mb12']}>
-          <Col span={4} class={styles.col}>
-            规格
-          </Col>
-          <Col span={20}>
-            {selectSku ? (
-              <div class={styles.selectWrap}>
-                {selectSku.stock <= 0
-                  ? `当前款式暂时缺货`
-                  : `已选择 ${selectSku.spDataJson}`}
-              </div>
-            ) : (
-              <div>请选择 规格</div>
-            )}
-            <RadioGroup
-              class={styles['radio-group']}
-              modelValue={this.radio}
-              onUpdate:modelValue={val => (this.radio = val)}
-            >
-              {this.skuStockList.map((item: any) => {
-                const isActive = item.id === this.radio
-                const type = isActive ? 'primary' : 'default'
-                return (
-                  <Badge
-                    position="top-right"
-                    content={item.stock <= 0 ? '缺货' : ''}
-                    color={'#999999'}
-                    class={styles.badge}
-                    offset={[-20, 0]}
-                  >
-                    <Radio
-                      class={styles.radio}
-                      name={item.id}
-                      disabled={item.stock <= 0}
-                      onClick={() => {
-                        // 判断是否有库存
-                        if (item.stock <= 0) {
-                          return
-                        }
-                        this.radio = item.id
-                      }}
-                    >
-                      <Tag size="large" plain={isActive} type={type}>
-                        {item.spDataJson}
-                      </Tag>
-                    </Radio>
-                  </Badge>
-                )
-              })}
-            </RadioGroup>
-          </Col>
-        </Row>
-        {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>
-        )}
-
-        {!this.loading && (
-          <>
-            <SubmitBar
-              class={styles.actionBar}
-              safe-area-inset-bottom
-              v-slots={{
-                button: () => (
-                  <div class={styles.buyGroup}>
-                    <ActionBarButton
-                      type="primary"
-                      class={styles.addCertBtn}
-                      text="加入购物车"
-                      onClick={() => this.onShowCart()}
-                    />
-                    <ActionBarButton
-                      type="primary"
-                      text="立即购买"
-                      onClick={() => this.onShowCart('cartConfirm')}
-                    />
-                  </div>
-                )
-              }}
-            >
-              <Badge
-                content={this.cartCount}
-                showZero={false}
-                onClick={() => {
-                  this.$router.push('/cart')
-                }}
-              >
-                <Icon name={iconShopCart} size={30} />
-              </Badge>
-            </SubmitBar>
-          </>
-        )}
-        <Popup
-          show={this.addGoodsShow}
-          closeable
-          position="bottom"
-          round
-          onClose={() => {
-            this.addGoodsShow = false
-          }}
-        >
-          <AddGoodsCart
-            show={this.addGoodsShow}
-            onGetCartCount={() => this.getCartCount()}
-            item={this.selectGoodsItem}
-            defaultRadio={this.radio}
-            showType={this.showType}
-          />
-        </Popup>
-
-        <Popup
-          style={{ background: 'transparent' }}
-          show={this.shareShow}
-          onClose={() => (this.shareShow = false)}
-        >
-          <ColShare
-            shareUrl={this.shareUrl}
-            teacherId={state.user.data.userId}
-            shareType="mall"
-          >
-            <div class={styles.shareWrap}>
-              <div class={styles.shareLeft}>
-                <img
-                  crossorigin="anonymous"
-                  class={styles.sharePic}
-                  src={sharePic}
-                ></img>
-              </div>
-              <div class={styles.shareRight}>
-                <div class={styles.shareShopTitle}>{this.product.name}</div>
-                {selectSku ? (
-                  <div class={styles.shareShopDes}>{selectSku.sku}</div>
-                ) : null}
-                <div class={styles.shareShopValue}>
-                  <span class={styles.shareShopPrice}>
-                    {moneyFormat(this.getPrice)}
-                  </span>
-                </div>
-              </div>
-              {/* <Card
-                price={this.getPrice}
-                desc={selectSku.sku}
-                title={this.product.name}
-                thumb={this.product.pic}
-              /> */}
-            </div>
-          </ColShare>
-        </Popup>
-      </div>
-    )
-  }
-})
+import request from '@/helpers/request'
+import { browser, moneyFormat } from '@/helpers/utils'
+import {
+  Swipe,
+  SwipeItem,
+  Image,
+  CellGroup,
+  Cell,
+  ImagePreview,
+  RadioGroup,
+  Radio,
+  Tag,
+  Row,
+  Col,
+  Sticky,
+  ActionBar,
+  ActionBarButton,
+  ActionBarIcon,
+  Icon,
+  Badge,
+  Toast,
+  Popup,
+  SubmitBar,
+  Card
+} from 'vant'
+import { defineComponent } from 'vue'
+import styles from './index.module.less'
+import iconShopCart from '../images/icon-shop-cart.png'
+import AddGoodsCart from '../modal/add-goods-cart'
+import ColHeader from '@/components/col-header'
+import iconShare from '../images/icon-share.svg'
+import ColShare from '@/components/col-share'
+import { state } from '@/state'
+import { useEventTracking } from '@/helpers/hooks'
+
+export default defineComponent({
+  name: 'goods-detail',
+  data() {
+    const query = this.$route.query
+    return {
+      id: query.id,
+      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
+    },
+
+    shareUrl() {
+      // 分享链接
+      const productId = this.product.id as any
+      if (browser().isApp) {
+        return `${location.origin}/teacher/#/shareMall?bizId=${productId}&userId=${state.user.data.userId}&userType=${state.platformType}&p=tenant`
+      } else {
+        return `${location.origin}/teacher.html#/shareMall?bizId=${productId}&userId=${state.user.data.userId}&userType=${state.platformType}&p=tenant`
+      }
+    },
+    platformStatus() {
+      const userInfo = state.user.data as any
+      // 是机构学生 并且 是机构老师分享
+      const query = this.$route.query
+      return userInfo.tenantId > 0 && query.p == 'tenant'
+    }
+  },
+  async mounted() {
+    try {
+      this.loading = true
+      const res = await request.get(
+        `/api-mall-portal/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
+    } catch {}
+    this.getCartCount()
+    useEventTracking('商品详情')
+  },
+  methods: {
+    onPreview(index: number) {
+      // 图片预览
+      ImagePreview({
+        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
+      })
+
+      ImagePreview({
+        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
+    },
+    onBuy() {
+      // 购买
+      if (!this.radio) {
+        return Toast('请选择规格')
+      }
+      console.log(true)
+    },
+    async getCartCount() {
+      try {
+        const { code, data } = await request.get('/api-mall-portal/cart/list')
+        if (code === 200) {
+          this.cartCount = data.length
+        }
+      } catch (err) {}
+    }
+  },
+  render() {
+    const product = this.product
+    const selectSku = this.skuStockList.find((n: any) => n.id === this.radio)
+    const sharePic = this.product.pic + '?v=' + Date.now()
+    return (
+      <div class={styles.goodsDetail}>
+        <ColHeader
+          v-slots={{
+            right: () => (
+              <div
+                class={styles.shareBtn}
+                onClick={() => (this.shareShow = true)}
+              >
+                <Icon name={iconShare} size={14} color="#666" />
+                <span style={{ marginLeft: '3px' }}>分享</span>
+              </div>
+            )
+          }}
+        />
+        <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>
+
+        <Row class={[styles.row, 'mb12']}>
+          <Col span={4} class={styles.col}>
+            规格
+          </Col>
+          <Col span={20}>
+            {selectSku ? (
+              <div class={styles.selectWrap}>
+                {selectSku.stock <= 0
+                  ? `当前款式暂时缺货`
+                  : `已选择 ${selectSku.spDataJson}`}
+              </div>
+            ) : (
+              <div>请选择 规格</div>
+            )}
+            <RadioGroup
+              class={styles['radio-group']}
+              modelValue={this.radio}
+              onUpdate:modelValue={val => (this.radio = val)}
+            >
+              {this.skuStockList.map((item: any) => {
+                const isActive = item.id === this.radio
+                const type = isActive ? 'primary' : 'default'
+                return (
+                  <Badge
+                    position="top-right"
+                    content={item.stock <= 0 ? '缺货' : ''}
+                    color={'#999999'}
+                    class={styles.badge}
+                    offset={[-20, 0]}
+                  >
+                    <Radio
+                      class={styles.radio}
+                      name={item.id}
+                      disabled={item.stock <= 0}
+                      onClick={() => {
+                        // 判断是否有库存
+                        if (item.stock <= 0) {
+                          return
+                        }
+                        this.radio = item.id
+                      }}
+                    >
+                      <Tag size="large" plain={isActive} type={type}>
+                        {item.spDataJson}
+                      </Tag>
+                    </Radio>
+                  </Badge>
+                )
+              })}
+            </RadioGroup>
+          </Col>
+        </Row>
+        {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>
+        )}
+
+        {!this.loading && (
+          <>
+            <SubmitBar
+              class={styles.actionBar}
+              safe-area-inset-bottom
+              v-slots={{
+                button: () => (
+                  <div class={styles.buyGroup}>
+                    <ActionBarButton
+                      type="primary"
+                      class={styles.addCertBtn}
+                      text="加入购物车"
+                      disabled={this.platformStatus}
+                      onClick={() => this.onShowCart()}
+                    />
+                    <ActionBarButton
+                      type="primary"
+                      text="立即购买"
+                      disabled={this.platformStatus}
+                      onClick={() => this.onShowCart('cartConfirm')}
+                    />
+                  </div>
+                )
+              }}
+            >
+              <Badge
+                content={this.cartCount}
+                showZero={false}
+                onClick={() => {
+                  if (this.platformStatus) {
+                    return
+                  }
+                  this.$router.push('/cart')
+                }}
+              >
+                <Icon
+                  name={iconShopCart}
+                  size={30}
+                  class={this.platformStatus && styles.cartDisabled}
+                />
+              </Badge>
+            </SubmitBar>
+          </>
+        )}
+        <Popup
+          show={this.addGoodsShow}
+          closeable
+          position="bottom"
+          round
+          onClose={() => {
+            this.addGoodsShow = false
+          }}
+        >
+          <AddGoodsCart
+            show={this.addGoodsShow}
+            onGetCartCount={() => this.getCartCount()}
+            item={this.selectGoodsItem}
+            defaultRadio={this.radio}
+            showType={this.showType}
+          />
+        </Popup>
+
+        <Popup
+          style={{ background: 'transparent' }}
+          show={this.shareShow}
+          onClose={() => (this.shareShow = false)}
+        >
+          <ColShare
+            shareUrl={this.shareUrl}
+            teacherId={state.user.data.userId}
+            shareType="mall"
+          >
+            <div class={styles.shareWrap}>
+              <div class={styles.shareLeft}>
+                <img
+                  crossorigin="anonymous"
+                  class={styles.sharePic}
+                  src={sharePic}
+                ></img>
+              </div>
+              <div class={styles.shareRight}>
+                <div class={styles.shareShopTitle}>{this.product.name}</div>
+                {selectSku ? (
+                  <div class={styles.shareShopDes}>{selectSku.sku}</div>
+                ) : null}
+                <div class={styles.shareShopValue}>
+                  <span class={styles.shareShopPrice}>
+                    {moneyFormat(this.getPrice)}
+                  </span>
+                </div>
+              </div>
+              {/* <Card
+                price={this.getPrice}
+                desc={selectSku.sku}
+                title={this.product.name}
+                thumb={this.product.pic}
+              /> */}
+            </div>
+          </ColShare>
+        </Popup>
+      </div>
+    )
+  }
+})