Przeglądaj źródła

feat: pc端兑换中心新增第三方兑换页面

cuiyalong 10 miesięcy temu
rodzic
commit
59857fbdec

+ 37 - 1
apps/jy-pc/src/api/modules/public.js

@@ -1,5 +1,5 @@
-import request from '@/api'
 import qs from 'qs'
+import request from '@/api'
 
 // 短信校验
 export function checkCaptcha(data) {
@@ -30,3 +30,39 @@ export function supplyInfo(data) {
     data
   })
 }
+
+// 获取第三方兑换信息
+const activityId = 'Qg=='
+export function getActivityRecords() {
+  return request({
+    url: '/publicapply/activity/records',
+    method: 'post',
+    headers: {
+      activeId: activityId
+    }
+  })
+}
+
+// 获取可兑换权益列表
+export function getActivityParties(data) {
+  return request({
+    url: '/publicapply/activity/parties',
+    method: 'post',
+    headers: {
+      activeId: activityId
+    },
+    data: qs.stringify(data)
+  })
+}
+
+// 确认兑换
+export function getActivityRedeem(data) {
+  return request({
+    url: '/publicapply/activity/redeem',
+    method: 'post',
+    headers: {
+      activeId: activityId
+    },
+    data: qs.stringify(data)
+  })
+}

+ 21 - 2
apps/jy-pc/src/components/dialog/Dialog.vue

@@ -3,13 +3,15 @@
     <el-dialog
       :custom-class="customclass"
       :title="title"
-      :visible.sync="showDialog"
+      :visible="showDialog"
       :show-close="false"
       :center="center"
       :close-on-click-modal="closeClickModal"
       :close-on-press-escape="closePressEsc"
       :top="top"
       :width="width"
+      @update:visible="updateVisible"
+      @close="onClose"
     >
       <div class="dialog-content">
         <slot name="content"></slot>
@@ -22,9 +24,12 @@
           confirmBtnText
         }}</el-button>
       </div>
-      <div class="dialog-label" v-if="customclass.indexOf('file') === -1">
+      <div class="dialog-label" v-if="showDialogLabel">
         <slot name="label"></slot>
       </div>
+      <template #footer>
+        <slot name="footer"></slot>
+      </template>
     </el-dialog>
   </div>
 </template>
@@ -46,6 +51,10 @@ export default {
       type: Boolean,
       default: false
     },
+    showDialogLabel: {
+      type: Boolean,
+      default: false
+    },
     confirmBtnText: {
       type: String,
       default: '确定'
@@ -84,6 +93,12 @@ export default {
     }
   },
   methods: {
+    onClose() {
+      this.updateVisible(false)
+    },
+    updateVisible(e) {
+      this.$emit('update:showDialog', e)
+    },
     onCancel() {
       this.$emit('onCancel')
     },
@@ -111,6 +126,10 @@ export default {
     .el-dialog__body {
       padding: 0;
     }
+    .el-dialog__footer {
+      margin-top: 10px;
+      padding: 0;
+    }
     .dialog-content {
       margin-top: 20px;
       font-size: 14px;

+ 553 - 89
apps/jy-pc/src/views/equity/Exchange.vue

@@ -2,120 +2,372 @@
   <div class="equity-exchange">
     <div class="exchange-header">兑换中心</div>
     <div class="exchange-container">
-      <div class="exchange-handle">
-        <div class="ex-tips" v-if="showTips">
-          <i class="j-icon icon-orange-phone"></i>
-          <span
-            >兑换权益与当前用户权益不对等,无法兑换。请直接联系吕经理:<a
-              class="tel"
-              href="tel:15136295365"
-              >151 3629 5365</a
-            >。</span
-          >
-        </div>
-        <div class="ex-input">
-          <span class="ex-input-label">兑换码</span>
-          <el-input
-            :class="{ 'error-input': showTips }"
-            v-model="code"
-            placeholder="请输入兑换码"
-            clearable
-            @input="onInput"
-          ></el-input>
-          <span class="status-text error-status" v-show="errorStatus"
-            ><i class="j-icon icon-error-status"></i>{{ errorMsg }}</span
-          >
-          <span class="status-text success-status" v-show="successStatus"
-            ><i class="j-icon icon-success-status"></i>恭喜兑换成功</span
-          >
-        </div>
-        <el-button class="ex-btn" type="primary" @click="onExchange"
-          >立即兑换</el-button
-        >
-        <div class="ex-desc">
-          <p>说明</p>
-          <p>1.输入兑换码即可兑换;</p>
-          <p>
-            2.如遇到问题请联系剑鱼标讯客服;若兑换码来源为从【淘宝/天猫/京东/拼多多】平台内的店铺购买商品获得,请联系对应店铺内的客服进行办理。
-          </p>
-        </div>
-      </div>
-      <div class="exchange-list">
-        <div class="list-title">我的兑换记录</div>
-        <div class="list-table" v-if="list && list.length > 0">
-          <div class="t-thead">
-            <span>兑换码</span>
-            <span>兑换权益</span>
-            <span>兑换时间</span>
+      <el-tabs v-model="activeName">
+        <el-tab-pane label="兑换剑鱼会员" name="1">
+          <div class="tab-pane-content">
+            <div class="exchange-handle">
+              <div class="ex-tips" v-if="jianyuExchange.showTips">
+                <i class="j-icon icon-orange-phone"></i>
+                <span
+                  >兑换权益与当前用户权益不对等,无法兑换。请直接联系吕经理:<a
+                    class="tel"
+                    href="tel:15136295365"
+                    >151 3629 5365</a
+                  >。</span
+                >
+              </div>
+              <div class="ex-input">
+                <span class="ex-input-label">兑换码</span>
+                <el-input
+                  :class="{ 'error-input': jianyuExchange.showTips }"
+                  v-model="jianyuExchange.code"
+                  placeholder="请输入兑换码"
+                  clearable
+                  @input="onJyExchangeInput"
+                ></el-input>
+                <span
+                  class="status-text error-status"
+                  v-show="jianyuExchange.errorStatus"
+                  ><i class="j-icon icon-error-status"></i
+                  >{{ jianyuExchange.errorMsg }}</span
+                >
+                <span
+                  class="status-text success-status"
+                  v-show="jianyuExchange.successStatus"
+                  ><i class="j-icon icon-success-status"></i>恭喜兑换成功</span
+                >
+              </div>
+              <el-button class="ex-btn" type="primary" @click="onJyExchange"
+                >立即兑换</el-button
+              >
+              <div class="ex-desc">
+                <p>说明</p>
+                <p>1.输入兑换码即可兑换;</p>
+                <p>
+                  2.如遇到问题请联系剑鱼标讯客服;若兑换码来源为从【淘宝/天猫/京东/拼多多】平台内的店铺购买商品获得,请联系对应店铺内的客服进行办理。
+                </p>
+              </div>
+            </div>
+            <div class="exchange-list">
+              <div class="list-title">我的兑换记录</div>
+              <div
+                class="list-table"
+                v-if="jianyuExchange.list && jianyuExchange.list.length > 0"
+              >
+                <div class="t-thead">
+                  <span>兑换码</span>
+                  <span>兑换权益</span>
+                  <span>兑换时间</span>
+                </div>
+                <div class="t-body">
+                  <p
+                    class="t-list"
+                    v-for="item in jianyuExchange.list"
+                    :key="item.EquityCode"
+                  >
+                    <span>{{ item.EquityCode }}</span>
+                    <span>{{ item.EquityName }}</span>
+                    <span>{{ formatDate(item.Date) }}</span>
+                  </p>
+                </div>
+              </div>
+              <Empty v-else>
+                <p>暂无兑换记录</p>
+              </Empty>
+            </div>
           </div>
-          <div class="t-body">
-            <p class="t-list" v-for="item in list" :key="item.EquityCode">
-              <span>{{ item.EquityCode }}</span>
-              <span>{{ item.EquityName }}</span>
-              <span>{{ formatDate(item.Date) }}</span>
-            </p>
+        </el-tab-pane>
+        <el-tab-pane label="获取第三方会员兑换码" name="2">
+          <div class="tab-pane-content">
+            <div class="waiting-exchange-container e-card-container">
+              <div class="e-card-header">
+                <div class="e-card-title">待获取兑换码订单列表</div>
+                <div class="e-card-actions">
+                  <el-link
+                    class="third-activity-rule"
+                    type="info"
+                    :underline="false"
+                    @click="goThirdActivityRule"
+                    >活动规则</el-link
+                  >
+                </div>
+              </div>
+              <div
+                class="e-card-content"
+                v-loading="thirdPartyExchange.loading"
+              >
+                <div
+                  class="list-table third-pending-table"
+                  v-if="
+                    thirdPartyExchange.pending &&
+                    thirdPartyExchange.pending.length > 0 &&
+                    thirdPartyExchange.loaded
+                  "
+                >
+                  <div class="t-thead">
+                    <span>购买产品</span>
+                    <span>购买时间</span>
+                    <span>获取兑换码</span>
+                  </div>
+                  <div class="t-body">
+                    <p
+                      class="t-list"
+                      v-for="item in thirdPartyExchange.pending"
+                      :key="item.account_id"
+                    >
+                      <span>{{ item.name }}</span>
+                      <span>{{ item.create_date }}</span>
+                      <span>
+                        <el-link
+                          type="primary"
+                          :underline="false"
+                          @click="getThirdCodeNow(item)"
+                          >立即获取</el-link
+                        >
+                      </span>
+                    </p>
+                  </div>
+                </div>
+                <Empty v-else>
+                  <p>暂无数据</p>
+                </Empty>
+              </div>
+            </div>
+            <div class="exchange-list">
+              <div class="exchange-list-hd">
+                <div class="list-title">我的兑换记录</div>
+                <div class="exchange-list-actions">
+                  <el-button
+                    type="primary"
+                    plain
+                    size="small"
+                    class="to-exchange-button"
+                    @click="thirdExchangeNow"
+                    >去兑换</el-button
+                  >
+                </div>
+              </div>
+              <div
+                class="list-table third-processed-table"
+                v-loading="thirdPartyExchange.loading"
+                v-if="
+                  thirdPartyExchange.processed &&
+                  thirdPartyExchange.processed.length > 0 &&
+                  thirdPartyExchange.loaded
+                "
+              >
+                <div class="t-thead">
+                  <span>购买产品</span>
+                  <span>购买时间</span>
+                  <span>获取状态</span>
+                  <span>获取权益</span>
+                </div>
+                <div class="t-body">
+                  <p
+                    class="t-list"
+                    v-for="item in thirdPartyExchange.processed"
+                    :key="item.ex_code"
+                  >
+                    <span>{{ item.name }}</span>
+                    <span>{{ item.create_date }}</span>
+                    <span>{{
+                      item.state === -1 ? '超期未获取' : '已获取'
+                    }}</span>
+                    <span>
+                      <p>会员名称:{{ item.party_name }}</p>
+                      <p>兑换码:{{ item.ex_code }}</p>
+                    </span>
+                  </p>
+                </div>
+              </div>
+              <Empty v-else>
+                <p>暂无兑换记录</p>
+              </Empty>
+            </div>
+          </div>
+        </el-tab-pane>
+      </el-tabs>
+    </div>
+    <CustomDialog
+      title="三方会员列表"
+      class="exchange-dialog"
+      top="30vh"
+      :showDialog.sync="thirdPartyExchange.inventoryListDialog"
+      confirmBtnText="立即获取兑换码"
+      closePressEsc
+      closeClickModal
+      :disabled="thirdExchangePartyConfirmDisabled"
+      @onConfirm="onExchangeThirdDialogConfirm"
+    >
+      <div slot="content" class="third-power-content">
+        <div class="third-power-select-list">
+          <div
+            class="third-power-select-item"
+            v-for="item in thirdPartyExchange.thirdPowerList"
+            :key="item.prize_id"
+            @click="thirdPartyExchange.thirdPowerCheck = item.prize_id"
+            :class="{
+              active: thirdPartyExchange.thirdPowerCheck === item.prize_id,
+              disabled: item.state === 0
+            }"
+          >
+            <span class="t-p-s-item-label">{{ item.name }}</span>
+            <span class="t-p-s-item-check">
+              <i class="el-icon-check"></i>
+            </span>
           </div>
         </div>
-        <Empty v-else>
-          <p>暂无兑换记录</p>
-        </Empty>
       </div>
-    </div>
+      <div slot="footer" class="third-no-stock-tip" v-if="showThirdNotStockTip">
+        三方会员库存不足,请联系客服
+      </div>
+    </CustomDialog>
+    <CustomDialog
+      title="获取成功"
+      top="30vh"
+      class="exchange-dialog"
+      :showDialog.sync="thirdPartyExchange.successAlert"
+      :showCancelBtn="false"
+      confirmBtnText="我知道了"
+      @onConfirm="thirdPartyExchange.successAlert = false"
+    >
+      <div slot="content" class="third-exchange-success-list">
+        <p class="info-item">
+          会员名称:{{ thirdPartyExchange.alertInfo.name }}
+        </p>
+        <p class="info-item">兑换码:{{ thirdPartyExchange.alertInfo.code }}</p>
+        <p class="info-item">
+          兑换链接:{{ thirdPartyExchange.alertInfo.address }}
+        </p>
+      </div>
+    </CustomDialog>
   </div>
 </template>
 
 <script>
-import { Input } from 'element-ui'
+import { Input, Tabs, TabPane, Button, Link } from 'element-ui'
 import { equityExchange, equityList } from '@/api/modules/pay'
+import {
+  getActivityRecords,
+  getActivityParties,
+  getActivityRedeem
+} from '@/api/modules/public'
 import Empty from '@/components/empty/Empty.vue'
+import CustomDialog from '@/components/dialog/Dialog.vue'
 export default {
-  name: 'equityExchangeComponent ',
+  name: 'equityExchangeComponent',
   components: {
     [Input.name]: Input,
+    [Tabs.name]: Tabs,
+    [TabPane.name]: TabPane,
+    [Button.name]: Button,
+    [Link.name]: Link,
+    CustomDialog,
     Empty
   },
   data() {
     return {
-      code: '',
-      list: [],
-      errorMsg: '',
-      showTips: false,
-      successStatus: false,
-      errorStatus: false
+      activeName: '1',
+      jianyuExchange: {
+        code: '',
+        list: [],
+        loading: false,
+        loaded: false,
+        errorMsg: '',
+        showTips: false,
+        successStatus: false,
+        errorStatus: false
+      },
+      thirdPartyExchange: {
+        inventoryListDialog: false,
+        successAlert: false,
+        loading: false,
+        loaded: false,
+        // 兑换地址
+        address: '',
+        // 待兑换
+        pending: [],
+        // 已兑换
+        processed: [],
+        // 活动规则
+        rule: [],
+        getCodeNow: {},
+        thirdPowerList: [],
+        thirdPowerCheck: '',
+        alertInfo: {
+          name: '',
+          code: '',
+          address: ''
+        }
+      }
+    }
+  },
+  computed: {
+    // 是否所有三方兑换都无库存
+    showThirdNotStockTip() {
+      const arr = this.thirdPartyExchange.thirdPowerList
+      if (arr.length > 0) {
+        const calc = [] // 无库存列表
+        arr.forEach((item) => {
+          // 0为无库存
+          calc.push(item.state === 0)
+        })
+        if (calc.includes(false)) {
+          return false
+        } else {
+          return true
+        }
+      } else {
+        return false
+      }
+    },
+    thirdExchangePartyConfirmDisabled() {
+      return (
+        this.showThirdNotStockTip || !this.thirdPartyExchange.thirdPowerCheck
+      )
     }
   },
   created() {
-    this.getList()
+    this.getQuery()
+    this.getJyExchangeList()
+    this.getThirdExchangeList()
   },
   methods: {
-    async getList() {
+    getQuery() {
+      const { tab } = this.$route.query
+      if (tab) {
+        this.activeName = tab
+      }
+    },
+    async getJyExchangeList() {
       const { data } = await equityList()
       if (data) {
-        this.list = data?.records || []
+        this.jianyuExchange.list = data?.records || []
       }
     },
-    async onExchange() {
-      if (!this.code) return
+    async onJyExchange() {
+      const code = this.jianyuExchange.code
+      if (!code) return
       const { success, errMsg } = await equityExchange({
-        code: this.code
+        code: code
       })
       if (success) {
-        this.errorMsg = errMsg
-        this.successStatus = true
-        this.errorStatus = false
-        this.showTips = false
-        this.getList()
+        this.jianyuExchange.errorMsg = errMsg
+        this.jianyuExchange.successStatus = true
+        this.jianyuExchange.errorStatus = false
+        this.jianyuExchange.showTips = false
+        this.getJyExchangeList()
       } else {
         // (1)兑换人已有产品权益大于要兑换的权益
         // (2)兑换人已有产品权益小于要兑换的权益
-        this.successStatus = false
+        this.jianyuExchange.successStatus = false
         if (errMsg.indexOf('无法兑换') > -1) {
-          this.showTips = true
-          this.errorStatus = false
+          this.jianyuExchange.showTips = true
+          this.jianyuExchange.errorStatus = false
         } else {
-          this.errorMsg = errMsg
-          this.showTips = false
-          this.errorStatus = true
+          this.jianyuExchange.errorMsg = errMsg
+          this.jianyuExchange.showTips = false
+          this.jianyuExchange.errorStatus = true
         }
       }
     },
@@ -123,27 +375,140 @@ export default {
       if (!val) return '-'
       return val.replace(/-/g, '.')
     },
-    onInput(val) {
+    onJyExchangeInput(val) {
       if (!val) {
-        this.successStatus = false
-        this.errorStatus = false
-        this.showTips = false
+        this.jianyuExchange.successStatus = false
+        this.jianyuExchange.errorStatus = false
+        this.jianyuExchange.showTips = false
       }
+    },
+    async getThirdExchangeList() {
+      this.thirdPartyExchange.loading = true
+      try {
+        const r = await getActivityRecords()
+        const { error_code: code, data } = r
+        if (code === 0 && data) {
+          this.thirdPartyExchange.pending = data.pending || []
+          this.thirdPartyExchange.processed = data.processed || []
+          this.thirdPartyExchange.rule = data.rule || []
+          this.thirdPartyExchange.address = data.address || ''
+        }
+      } catch (error) {
+        console.log(error)
+      } finally {
+        this.thirdPartyExchange.loaded = true
+        this.thirdPartyExchange.loading = false
+      }
+    },
+    async getActivityParties() {
+      const payload = {
+        product_id: this.thirdPartyExchange.getCodeNow.product_id
+      }
+      this.thirdPartyExchange.thirdPowerCheck = ''
+      try {
+        const r = await getActivityParties(payload)
+        const { error_code: code, data } = r
+        if (code === 0 && Array.isArray(data)) {
+          this.thirdPartyExchange.thirdPowerList = data || []
+          // 默认选中赋值
+          if (data.length > 0) {
+            // do something
+          } else {
+            this.$toast('暂未获取到兑换列表')
+          }
+        } else {
+          this.$toast('响应异常')
+        }
+      } catch (error) {
+        console.log(error)
+        this.$toast('响应异常')
+      }
+    },
+    getThirdCodeNow(row) {
+      this.thirdPartyExchange.getCodeNow = row
+      this.thirdPartyExchange.inventoryListDialog = true
+      this.getActivityParties()
+    },
+    thirdExchangeNow() {
+      const address = this.thirdPartyExchange.address
+      if (address) {
+        window.open(this.thirdPartyExchange.address)
+      }
+    },
+    getCurrentThirdPartySelected() {
+      const selectedId = this.thirdPartyExchange.thirdPowerCheck
+      const arr = this.thirdPartyExchange.thirdPowerList
+      const target = arr.find((item) => item.prize_id === selectedId)
+      if (target) {
+        return target
+      } else {
+        return {}
+      }
+    },
+    async onExchangeThirdDialogConfirm() {
+      const currentAccount = this.thirdPartyExchange.getCodeNow
+      const currentSelected = this.getCurrentThirdPartySelected()
+      const payload = {
+        prize_id: currentSelected.prize_id,
+        account_id: currentAccount.account_id
+      }
+      try {
+        const r = await getActivityRedeem(payload)
+        const { error_code: code, data, error_msg: msg } = r
+        if (code === 0 && data) {
+          Object.assign(this.thirdPartyExchange.alertInfo, data)
+          this.thirdPartyExchange.inventoryListDialog = false
+          this.thirdPartyExchange.successAlert = true
+          this.getActivityRecords()
+        } else {
+          this.$toast(msg || '响应异常')
+        }
+      } catch (error) {
+        console.log(error)
+        this.$toast('响应异常')
+      }
+    },
+    goThirdActivityRule() {
+      window.open('/swordfish/page_big_pc/free/terms/activity?id=Qg==')
     }
   }
 }
 </script>
 
 <style lang="scss" scoped>
+::v-deep {
+  .el-tabs__header {
+    background-color: #fff;
+    border-radius: 8px 8px 0 0;
+    margin: 0;
+  }
+  .el-tabs__item {
+    height: 50px;
+    line-height: 50px;
+  }
+  .el-tabs__nav-wrap {
+    padding-left: 40px;
+  }
+}
+
+.exchange-dialog {
+  ::v-deep {
+    .jy-custom-dialog {
+      width: 316px !important;
+    }
+  }
+}
+
+%flex {
+  display: flex;
+  align-items: center;
+}
 .equity-exchange {
   %bg {
     border-radius: 8px;
     background: $white;
   }
-  %flex {
-    display: flex;
-    align-items: center;
-  }
+
   %title {
     font-size: 16px;
     line-height: 24px;
@@ -160,8 +525,14 @@ export default {
     line-height: 36px;
     color: #1d1d1d;
   }
+  .exchange-list-hd {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+  }
   .exchange-handle {
-    @extend %bg;
+    background: $white;
+    border-radius: 0 0 8px 8px;
     padding: 16px 16px 32px;
   }
   .ex-tips {
@@ -255,6 +626,27 @@ export default {
         color: #686868;
       }
     }
+    &.third-processed-table {
+      span {
+        &:nth-of-type(1) {
+          width: 328px;
+        }
+        &:nth-of-type(2) {
+          width: 208px;
+        }
+        &:nth-of-type(3) {
+          width: 208px;
+        }
+        &:nth-of-type(4) {
+          width: 320px;
+        }
+      }
+      .t-list {
+        display: flex;
+        align-items: center;
+      }
+    }
+
     .t-body {
       margin-top: 12px;
     }
@@ -273,4 +665,76 @@ export default {
     }
   }
 }
+
+.to-exchange-button {
+  padding: 4px 24px;
+  font-size: 14px;
+  line-height: 22px;
+  border-radius: 4px;
+  border-color: $color_main;
+  background: transparent;
+}
+.e-card-container {
+  padding: 16px 40px;
+  background: #fff;
+  border-radius: 8px;
+  .e-card-header {
+    @extend %flex;
+    justify-content: space-between;
+  }
+  .e-card-title {
+    font-size: 16px;
+    line-height: 24px;
+    color: #1d1d1d;
+  }
+  .e-card-content {
+    margin-top: 12px;
+  }
+}
+.third-activity-rule {
+  color: #686868;
+}
+.waiting-exchange-container {
+  border-radius: 0 0 8px 8px;
+}
+
+.third-power-select-list {
+  .third-power-select-item {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 8px 24px;
+    font-size: 14px;
+    line-height: 22px;
+    border-radius: 8px;
+    color: #1d1d1d;
+    border: 1px solid rgba(224, 224, 224, 1);
+    cursor: pointer;
+    &:not(:last-of-type) {
+      margin-bottom: 12px;
+    }
+    .el-icon-check {
+      font-size: 20px;
+      display: none;
+    }
+
+    &.active {
+      color: $color_main;
+      border-color: $color_main;
+      .el-icon-check {
+        display: block;
+      }
+    }
+    &.disabled {
+      color: #999;
+      background-color: #f5f6f7;
+      cursor: no-drop;
+    }
+  }
+}
+.third-no-stock-tip {
+  color: #ff3a20;
+  font-size: 14px;
+  line-height: 22px;
+}
 </style>

+ 1 - 0
apps/jy-pc/src/views/issued/Index.vue

@@ -34,6 +34,7 @@
         :showCancelBtn="dialog.showCancelBtn"
         :confirmBtnText="dialog.confirmBtnText"
         cancelBtnText="取消"
+        showDialogLabel
         @onConfirm="onConfirmDialogBtn"
         @onCancel="onCancelDialogBtn"
       >