Browse Source

商城老师分享

skyblued 2 years ago
parent
commit
d7a9cdf94f

+ 8 - 0
src/router/routes-teacher.ts

@@ -30,6 +30,14 @@ const noLoginRouter = [
     meta: {
       title: '分享乐曲'
     }
+  },
+  {
+    path: '/shareMall',
+    name: 'shareMall',
+    component: () => import('@/teacher/share-page/share-mall/index'),
+    meta: {
+      title: '分享商品'
+    }
   }
 ]
 

+ 253 - 0
src/teacher/share-page/share-mall/index.module.less

@@ -0,0 +1,253 @@
+.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;
+  }
+  .shareShopTitle {
+    font-size: 16px;
+    font-weight: 400;
+    color: #333333;
+
+  }
+  .shareShopDes {
+    font-size: 14px;
+    font-weight: 400;
+    color: #999999;
+    margin: 10px 0 20px 0;
+  }
+  .shareShopValue {
+    font-size: 16px;
+    color: #ff4e19;
+  }
+  .shareShopOldPrice{
+    color: #E5E5E5;
+    margin-left: 5px;
+  }
+}

+ 283 - 0
src/teacher/share-page/share-mall/index.tsx

@@ -0,0 +1,283 @@
+import request from '@/helpers/request'
+import { browser, moneyFormat } from '@/helpers/utils'
+import {
+  Swipe,
+  SwipeItem,
+  Image,
+  CellGroup,
+  Cell,
+  ImagePreview,
+  RadioGroup,
+  Radio,
+  Tag,
+  Row,
+  Col,
+  Badge,
+  Button,
+  Dialog
+} from 'vant'
+import { defineComponent } from 'vue'
+import styles from './index.module.less'
+import ColSticky from '@/components/col-sticky'
+import { shareCall } from '../share'
+import { state } from '@/state'
+
+export default defineComponent({
+  name: 'goods-detail',
+  data() {
+    const query = this.$route.query
+    return {
+      id: query.id,
+      albumPics: [] as any[],
+      product: {} as any,
+      radio: 0,
+      skuStockList: [] as any[],
+      detailMobileHtml: '',
+      loading: false
+    }
+  },
+  computed: {
+    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 this.product.price
+    }
+  },
+  mounted() {
+    this.getProduct()
+    if (browser().isApp) {
+      if (state.platformType === 'STUDENT') {
+        const { query } = this.$route.query as any
+        // 自动跳转到学生端商品详情
+        window.location.replace(
+          `${location.origin}/student/#/goodsDetail?id=${query.bizId}&promoterId=${query.userId}`
+        )
+      } else if (state.platformType === 'TEACHER') {
+        Dialog.alert({
+          title: '提示',
+          message: '请使用酷乐秀学生端扫码打开'
+        }).then(() => {
+          postMessage({ api: 'back' })
+        })
+      }
+    }
+  },
+  methods: {
+    async getProduct() {
+      this.loading = true
+      let product = {} as any
+      let skuStockList = []
+      // 获取产品信息
+      try {
+        const result = await request.post(
+          `/api-mall-portal/open/productProfit`,
+          {
+            data: {
+              bizId: this.$route.query.bizId,
+              userId: this.$route.query.userId
+            }
+          }
+        )
+        if (result.data && result.data.productDetail) {
+          product = result.data.productDetail.product
+          skuStockList = result.data.productDetail.skuStockList || []
+        }
+      } catch {}
+      this.product = product
+      this.skuStockList = skuStockList.map((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 item
+      })
+      this.albumPics = [product.pic]
+        .concat(product.albumPics.split(','))
+        .filter(n => n)
+      this.detailMobileHtml = product.detailMobileHtml
+      this.loading = false
+    },
+    onPreview(index: number) {
+      // 图片预览
+      ImagePreview({
+        images: this.albumPics,
+        startPosition: index,
+        closeable: true
+      })
+    },
+    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
+      })
+    },
+
+    //打开APP
+    onDetail() {
+      const { origin } = location
+      const query = this.$route.query
+      let str = origin + `/student/#/goodsDetail?id=${query.bizId}&promoterId=${query.userId}`
+      shareCall(str, {})
+      setTimeout(() => {
+        this.$router.push('/download')
+      }, 3000)
+    }
+  },
+  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>
+              )
+            }}
+          />
+          <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 class={styles.selectWrap}>请选择 规格</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>
+        )}
+        <ColSticky position="bottom">
+          <div class={['btnGroup']} style={{ paddingTop: '12px' }}>
+            <Button block round type="primary" onClick={this.onDetail}>
+              下载酷乐秀购买商品
+            </Button>
+          </div>
+        </ColSticky>
+      </div>
+    )
+  }
+})

+ 47 - 1
src/views/shop-mall/goods-detail/index.module.less

@@ -199,9 +199,55 @@
   overflow: hidden;
   box-sizing: border-box;
 }
-.selectWrap{
+.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;
+  }
+  .shareShopTitle {
+    font-size: 16px;
+    font-weight: 400;
+    color: #333333;
+
+  }
+  .shareShopDes {
+    font-size: 14px;
+    font-weight: 400;
+    color: #999999;
+    margin: 10px 0 20px 0;
+  }
+  .shareShopValue {
+    font-size: 16px;
+    color: #ff4e19;
+  }
+  .shareShopOldPrice{
+    color: #E5E5E5;
+    margin-left: 5px;
+  }
+}

+ 62 - 14
src/views/shop-mall/goods-detail/index.tsx

@@ -1,5 +1,5 @@
 import request from '@/helpers/request'
-import { moneyFormat } from '@/helpers/utils'
+import { browser, moneyFormat } from '@/helpers/utils'
 import {
   Swipe,
   SwipeItem,
@@ -28,6 +28,8 @@ 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'
 
 export default defineComponent({
   name: 'goods-detail',
@@ -44,7 +46,8 @@ export default defineComponent({
       addGoodsShow: false,
       selectGoodsItem: {},
       cartCount: 0,
-      showType: 'cart'
+      showType: 'cart',
+      shareShow: false, // 分享弹窗
     }
   },
   computed: {
@@ -66,11 +69,16 @@ export default defineComponent({
       skuStockList.forEach((item: any) => {
         if (item.spData) {
           const spData = JSON.parse(item.spData)
-          let str = ''
-          spData.forEach((sp: any) => {
-            str += `${sp.value}`
-          })
-          item.spDataJson = str
+          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 = '默认'
         }
@@ -83,9 +91,18 @@ export default defineComponent({
         return item[0].price
       }
       return 0
+    },
+
+    shareUrl(){ // 分享链接
+      if (browser().isApp){
+        return `${location.origin}/teacher/#/shareMall?bizId=${this.product.id}&userId=${state.user.data.userId}`
+      } else {
+        return `${location.origin}/teacher.html#/shareMall?bizId=${this.product.id}&userId=${state.user.data.userId}`
+      }
     }
   },
   async mounted() {
+    
     try {
       this.loading = true
       const res = await request.get(
@@ -173,18 +190,25 @@ export default defineComponent({
           this.cartCount = data.length
         }
       } catch (err) {}
-    }
+    },
   },
   render() {
     const product = this.product
-    const selectList = this.skuStockList.filter((n: any) => n.id === this.radio)
+    const selectSku = this.skuStockList.find((n: any) => n.id === this.radio)
     return (
       <div class={styles.goodsDetail}>
         <ColHeader
-          isBack
           v-slots={{
             right: () => {
-              return <Icon name={iconShare} size={20} />
+              return (
+                <div
+                  class={styles.shareBtn}
+                  onClick={() => (this.shareShow = true)}
+                >
+                  <Icon name={iconShare} size={14} color="#666" />
+                  <span style={{ marginLeft: '3px' }}>分享</span>
+                </div>
+              )
             }
           }}
         />
@@ -244,11 +268,11 @@ export default defineComponent({
             规格
           </Col>
           <Col span={20}>
-            {selectList.length ? (
+            {selectSku ? (
               <div class={styles.selectWrap}>
-                {selectList[0].stock <= 0
+                {selectSku.stock <= 0
                   ? `当前款式暂时缺货`
-                  : `已选择 ${selectList[0].spDataJson}`}
+                  : `已选择 ${selectSku.spDataJson}`}
               </div>
             ) : (
               <div>请选择 规格</div>
@@ -356,6 +380,30 @@ export default defineComponent({
             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 class={styles.sharePic} src={this.product.pic}></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>
+                  <del class={styles.shareShopOldPrice}>
+                    {moneyFormat(product.originalPrice)}
+                  </del>
+                </div>
+              </div>
+            </div>
+          </ColShare>
+        </Popup>
       </div>
     )
   }

+ 2 - 1
src/views/shop-mall/modal/add-goods-cart/index.tsx

@@ -106,7 +106,8 @@ export default defineComponent({
         productSkuId: selectItem.id,
         quantity: this.total, // 数量
         productId: item.id,
-        hidden: this.showType === 'cart' ? 0 : 1
+        hidden: this.showType === 'cart' ? 0 : 1,
+        promoterId: this.$route.query.promoterId ? this.$route.query.promoterId : undefined
       }
       // console.log(body)
       try {