فهرست منبع

新增兑换中心,首页清除商品缓存

phperli 3 سال پیش
والد
کامیت
51930fe3c9

+ 1 - 1
src/pages/index/index.vue

xqd
@@ -136,7 +136,7 @@
 			const updateManager = wx.getUpdateManager();
 			if (updateManager) {
 				updateManager.onCheckForUpdate(function(res) {
-					// 请求完新版本信息的回调
+					//请求完新版本信息的回调
 				})
 				updateManager.onUpdateReady(function() {
 					wx.showModal({

+ 513 - 0
src/plugins/exchange/detail/detail.vue

xqd
@@ -0,0 +1,513 @@
+<template>
+    <app-layout>
+        <view class="code-info" :style="{backgroundImage: 'url('+ exchangeImg.bg + ')',backgroundColor: getTheme.background}">
+            <view class="code">{{code}}</view>
+            <view v-if="exchange == 0">该兑换码包含{{list.length}}种礼品,您可以{{mode == 0 ? '全部':'任选一件'}}兑换:</view>
+            <view v-if="exchange == 1">于{{r_raffled_at}}兑换以下礼品</view>
+        </view>
+        <view>
+            <view class="rewards" v-for="(item,index) in list" :key="index">
+                <view class="rewards-top dir-left-nowrap cross-center" :class="mode == 1 ? 'active-item':''">
+                    <app-radio width="88" :height="item.type == 'integral' || item.type == 'balance' || item.type == 'svip' ? '36':'140'"  @click="toggle" :value="item.active" :item="item" :theme="getTheme" type="round" v-if="mode == 1">
+                    </app-radio>
+                    <view v-if="item.type == 'goods'" class="dir-left-nowrap card goods">
+                        <image class="card-img" mode="aspectFill" :src="item.goods_info.cover_pic"></image>
+                        <view class="card-info">
+                            <view class="t-omit-two card-name">{{item.goods_info.name}}</view>
+                            <view class="attr">{{item.goods_info.attr_str}}</view>
+                            <view class="dir-right-nowrap">
+                                <div class="goods-num" :style="{'color': getTheme.color}">x{{item.goods_num}}</div>
+                            </view>
+                        </view>
+                    </view>
+                    <view v-if="item.type == 'card'" class="dir-left-nowrap card">
+                        <image class="card-img" mode="aspectFill" v-if="item.card_info.pic_url" :src="item.card_info.pic_url"></image>
+                        <view class="card-info">
+                            <view class="dir-left-nowrap">
+                                <image src="./../image/card.png"></image>
+                                <view class="t-omit-two card-name">{{item.card_info.name}}</view>
+                            </view>
+                            <view class="main-between cross-center">
+                                <div class="card-number" :style="{'color': getTheme.color,'background-color': getTheme.background_o}">剩余{{item.card_info.number}}次</div>
+                                <div class="card-num" :style="{'color': getTheme.color}">x{{item.card_num}}</div>
+                            </view>
+                        </view>
+                    </view>
+                    <view v-if="item.type == 'coupon'" class="dir-left-nowrap card">
+                        <view class="card-info">
+                            <view class="dir-left-nowrap">
+                                <image src="./../image/coupon.png"></image>
+                                <view class="t-omit-two card-name">{{item.coupon_info.name}}</view>
+                            </view>
+                            <view class="main-between cross-center">
+                                <div v-if="item.coupon_info.type == 1" class="card-number" :style="{'color': getTheme.color,'background-color': getTheme.background_o}">{{item.coupon_info.discount}}折 满{{item.coupon_info.min_price == 0 ? '任意金额': '¥'+item.coupon_info.min_price}}可用 <text style="margin-left: 10rpx" v-if="item.coupon_info.discount_limit">优惠上限¥{{item.coupon_info.discount_limit}}</text></div>
+                                <div v-if="item.coupon_info.type == 2" class="card-number" :style="{'color': getTheme.color,'background-color': getTheme.background_o}">¥{{item.coupon_info.sub_price}} 满{{item.coupon_info.min_price == 0 ? '任意金额': '¥'+item.coupon_info.min_price}}可用</div>
+                                <div class="card-num" :style="{'color': getTheme.color}">x{{item.coupon_num}}</div>
+                            </view>
+                        </view>
+                    </view>
+                    <view v-if="item.type == 'integral' || item.type == 'balance' || item.type == 'svip'" class="dir-left-nowrap balance">
+                        <view class="balance-info cross-center main-between">
+                            <view class="dir-left-nowrap cross-center">
+                                <image v-if="item.type == 'integral'" src="./../image/point.png"></image>
+                                <image v-if="item.type == 'balance'" src="./../image/balance.png"></image>
+                                <image v-if="item.type == 'svip'" src="./../image/svip.png"></image>
+                                <view class="balance-name">{{item.name}}</view>
+                            </view>
+                            <view v-if="item.type == 'integral'" :style="{'color': getTheme.color}">{{item.integral_num}}</view>
+                            <view v-if="item.type == 'balance'" :style="{'color': getTheme.color}">¥{{item.balance}}</view>
+                            <view v-if="item.type == 'svip'" :style="{'color': getTheme.color}">{{item.svip_info.discount}}折</view>
+                        </view>
+                    </view>
+                </view>
+                <view v-if="exchange == 1" class="rewards-bottom dir-right-nowrap cross-center">
+                    <view v-if="item.is_send == 0" @click="apply(item)" :style="{'background-color': getTheme.background}" class="rewards-submit">立即领取</view>
+                    <view v-if="item.is_send == 1" class="rewards-submit over">已领取</view>
+                    <view v-if="item.goods_id > 0 || (item.user_coupon_id && item.user_coupon_id.length > 0) || (item.user_card_id && item.user_card_id.length > 0)" @click="toDetail(item)" :style="{'color': getTheme.color, 'border-color': getTheme.border}" class="rewards-detail">查看详情</view>
+                </view>
+            </view>
+        </view>
+        <view v-if="exchange == 0" class="placeholder"></view>
+        <view v-if="exchange == 0 && list.length > 0" class="apply safe-area-inset-bottom">
+            <view class="apply-btn" @click="submit" :style="{'background-color': getTheme.background}">立即兑换</view>
+        </view>
+        <u-mask :show="dialog" :maskClickAble="false" :zoom="false">
+            <view class="dialog">
+                <image class="dialog-img" src="./../image/error.png"></image>
+                <view class="dialog-msg">
+                    <text>{{msg}}</text>
+                </view>
+                <view class="dialog-other">{{other}}</view>
+                <view @click="goback"  :style="{'background-color': getTheme.background}" class="dialog-button">我知道了</view>
+            </view>
+        </u-mask>
+    </app-layout>
+</template>
+
+<script>
+    import {mapGetters, mapState} from 'vuex';
+    import uMask from '../../../components/basic-component/u-mask/u-mask.vue';
+    import appIphoneX from '../../../components/basic-component/app-iphone-x/app-iphone-x.vue';
+    import appRadio from '../../../components/basic-component/app-radio/app-radio.vue';
+
+    export default {
+        name: "index",
+        data() {
+            return {
+                first: true,
+                loading: false,
+                code: '',
+                dialog: false,
+                msg: '',
+                other: '',
+                r_raffled_at: '',
+                list: [],
+                mode: 0,
+                exchange: 0,
+                token: ''
+            };
+        },
+        components:{
+            'app-radio': appRadio,
+            uMask,
+            'app-iphone-x': appIphoneX,
+        },
+        onLoad(options) { this.$commonLoad.onload(options);
+            let that = this;
+            that.code = options.code;
+            that.exchange = options.exchange == 1 ? 1 : 0;
+            that.$showLoading({
+                type: 'global',
+                text: '加载中...'
+            });
+            that.getList();
+        },
+        onShow() {
+            if(this.exchange == 1 && !this.first) {
+                this.getList()
+            }
+        },
+        computed: {
+            ...mapGetters('mallConfig', {
+                getTheme: 'getTheme',
+            }),
+            ...mapState({
+                exchangeImg: state => state.mallConfig.__wxapp_img.exchange
+            })
+        },
+        methods: {
+            toDetail(item) {
+                if(item.type == 'goods') {
+                    uni.navigateTo({
+                        url: `/pages/goods/goods?id=${item.goods_id}&code=${this.code}&token=${item.token}&attr=${item.goods_info.attr_str}&attr_id=${item.attr_id}&goods_num=${item.goods_num}&exchange=${item.is_send}`
+                    });
+                }else if(item.type == 'coupon') {
+                    uni.navigateTo({
+                        url: `/pages/coupon/details/details-no-share?person=1&id=${item.user_coupon_id[0]}`
+                    });
+                }else if(item.type == 'card') {
+                    uni.navigateTo({
+                        url: `/pages/card/details/details?id=${item.user_card_id[0]}`
+                    });
+                }
+            },
+            goback() {
+                this.dialog = false;
+                uni.navigateBack();
+            },
+            apply(item) {
+                let that = this;
+                uni.showLoading({
+                    mask: true,
+                    title: '领取中...'
+                });
+                if(item.type != 'goods') {
+                    that.$request({
+                        url: that.$api.exchange.covert,
+                        data: {
+                            code: this.code,
+                            token: item.token
+                        },
+                        method: 'post'
+                    }).then(response=>{
+                        uni.hideLoading();
+                        if(response.code == 0) {
+                            uni.showToast({
+                                title: response.msg,
+                                duration: 1000
+                            });
+                            this.getList();
+                        }else {
+                            uni.showToast({
+                                title: response.msg,
+                                icon: 'none',
+                                duration: 1000
+                            });
+                        }
+                    }).catch(response => {
+                        uni.hideLoading();
+                    });
+                }else {
+                    let mch_list = [{
+                        mch_id: 0,
+                        goods_list: [{
+                            id: item.goods_id,
+                            attr: item.goods_info.attr_str,
+                            num: item.goods_num,
+                            cat_id: 0,
+                            goods_attr_id: item.attr_id
+                        }],
+                        code: this.code,
+                        token: item.token,
+                    }];
+                    let url = `/pages/order-submit/order-submit?mch_list=${JSON.stringify(mch_list)}`;
+                    url += `&preview_url=${encodeURIComponent(this.$api.exchange.exchange_preview)}&submit_url=${encodeURIComponent(this.$api.exchange.exchange_submit)}&plugin=exchange`;
+                    uni.navigateTo({
+                        url: url
+                    })
+                }
+            },
+            toggle(e) {
+                for(let item of this.list) {
+                    if(item.token == e.item.token) {
+                        item.active = e.active;
+                        this.token = e.item.token
+                    }else {
+                        item.active = false;
+                    }
+                }
+                this.$forceUpdate();
+            },
+            submit() {
+                let that = this;
+                if(that.mode == 1 && !that.token) {
+                    uni.showToast({
+                        title: '请选择想要兑换的礼品',
+                        icon: 'none',
+                        duration: 1000
+                    });
+                    return false
+                }
+                if(this.loading) {
+                    return false
+                }
+                this.loading = true;
+                uni.showLoading({
+                    mask: true,
+                    title: '领取中...'
+                });
+                that.$request({
+                    url: that.$api.exchange.unite,
+                    data: {
+                        code: this.code,
+                        token: this.token
+                    },
+                    method: 'post'
+                }).then(response=>{
+                    this.loading = false;
+                    uni.hideLoading();
+                    if(response.code == 0) {
+                        this.exchange = 1;
+                        this.mode = 0;
+                        this.getList();
+                    }else {
+                        uni.showToast({
+                            title: response.msg,
+                            icon: 'none',
+                            duration: 1000
+                        });
+                    }
+                }).catch(response => {
+                    uni.hideLoading();
+                });
+            },
+            getList() {
+                let that = this;
+                that.$request({
+                    url: that.exchange == 1 ? that.$api.exchange.log_detail : that.$api.exchange.info,
+                    data: {
+                        code: that.code
+                    }
+                }).then(response=>{
+                    that.$hideLoading();
+                    uni.hideLoading();
+                    that.first = false;
+                    if(response.code == 0) {
+                        if(that.exchange == 0) {
+                            that.list = response.list.rewards;
+                            that.mode = response.list.mode;
+                            if(that.mode == 1) {
+                                for(let item of that.list) {
+                                    item.active = false;
+                                }
+                            }
+                        }else {
+                            that.r_raffled_at = response.data.codeModel.r_raffled_at
+                            that.list = response.data.rewards;
+                        }
+                    }else {
+                        if(that.exchange == 0) {
+                            that.msg = response.msg;
+                            that.other = '';
+                            if(response.msg == '该兑换码未到使用时间!') {
+                                that.other = response.data.valid_start_time + '-' + response.data.valid_end_time + ' 可用'
+                            }
+                            that.dialog = true;
+                        }else {
+                            uni.showToast({
+                                title: response.msg,
+                                icon: 'none',
+                                duration: 1000
+                            });
+                        }
+                    }
+                }).catch(response => {
+                    that.$hideLoading();
+                    uni.hideLoading();
+                });
+            }
+        }
+    }
+</script>
+
+<style scoped lang="scss">
+    .dialog {
+        margin: 270rpx auto;
+        background-color: #fff;
+        border-radius: 16rpx;
+        width: 600rpx;
+        padding: 60rpx 0;
+        text-align: center;
+        .dialog-img {
+            width: 200rpx;
+            height: 200rpx;
+            margin: 0 auto 20rpx;
+        }
+        .dialog-msg {
+            font-size: 32rpx;
+            color: #353535;
+        }
+        .dialog-other {
+            font-size: 24rpx;
+            color: #999999;
+        }
+        .dialog-button {
+            font-size: 26rpx;
+            width: 520rpx;
+            height: 90rpx;
+            border-radius: 45rpx;
+            line-height: 90rpx;
+            text-align: center;
+            color: #fff;
+            margin: 50rpx auto 0;
+        }
+    }
+    .code-info {
+        width: 702rpx;
+        height: 240rpx;
+        border-radius: 16rpx;
+        background-size: 100% 100%;
+        margin: 24rpx;
+        text-align: center;
+        color: #fff;
+        font-size: 24rpx;
+        .code {
+            margin-top: 50rpx;
+            display: inline-block;
+            font-size: 38rpx;
+            text-align: center;
+            padding: 24rpx 95rpx;
+            border-radius: 60rpx;
+            color: #fff;
+            background-color: rgba(255,255,255,.2);
+            margin-bottom: 20rpx;
+        }
+    }
+    .rewards {
+        background-color: #fff;
+        border-radius: 16rpx;
+        width: 702rpx;
+        margin: 24rpx auto 0;
+        .rewards-top {
+            padding: 34rpx 40rpx;
+            &.active-item {
+                padding-left: 0;
+            }
+            .active {
+                width: 88rpx;
+                height: 140rpx;
+                text-align: center;
+                flex-shrink: 0;
+                image {
+                    width: 32rpx;
+                    height: 32rpx;
+                    margin-top: 54rpx;
+                    border-radius: 16rpx;
+                }
+                &.small {
+                    height: 36rpx;
+                    image {
+                        margin-top: 2rpx;
+                    }
+                }
+            }
+            .goods-num {
+                font-size: 28rpx;
+            }
+            .balance {
+                width: 100%;
+                .balance-info {
+                    width: 100%;
+                    image {
+                        width: 30rpx;
+                        height: 30rpx;
+                        margin-right: 14rpx;
+                    }
+                    .balance-name {
+                        font-size: 28rpx;
+                        color: #353535;
+                    }
+                }
+            }
+            .card {
+                width: 100%;
+                &.goods {
+                    .card-info {
+                        .card-name {
+                            margin-top: 0;
+                            margin-bottom: 10rpx;
+                        }
+                    }
+                }
+                .card-img {
+                    height: 140rpx;
+                    width: 140rpx;
+                    border-radius: 8rpx;
+                    margin-right: 20rpx;
+                    flex-shrink: 0;
+                }
+                .card-info {
+                    width: 100%;
+                    image {
+                        width: 30rpx;
+                        height: 30rpx;
+                        margin-right: 14rpx;
+                    }
+                    .attr {
+                        font-size: 24rpx;
+                        color: #999;
+                    }
+                    .card-name {
+                        margin-top: -5rpx;
+                        font-size: 28rpx;
+                        color: #353535;
+                        margin-bottom: 30rpx;
+                    }
+                    .card-number {
+                        padding: 12rpx 20rpx;
+                        font-size: 24rpx;
+                        border-radius: 30rpx;
+                    }
+                    .card-num {
+                        font-size: 28rpx;
+                    }
+                }
+            }
+        }
+        .rewards-bottom {
+            border-top: #{2rpx} solid #e2e2e2;
+            height: #{118rpx};
+            width: 100%;
+            padding: 0 #{30rpx};
+            .rewards-submit {
+                height: #{68rpx};
+                line-height: #{68rpx};
+                text-align: center;
+                padding: 0 #{30rpx};
+                border-radius: #{40rpx};
+                color: #fff;
+                font-size: #{28rpx};
+                &.over {
+                    background-color: #f7f7f7;
+                    color: #999999;
+                }
+            }
+            .rewards-detail {
+                height: #{68rpx};
+                line-height: #{68rpx};
+                text-align: center;
+                padding: 0 #{30rpx};
+                border-radius: #{40rpx};
+                background-color: #fff;
+                font-size: #{28rpx};
+                border: #{2rpx} solid;
+                margin-right: #{18rpx};
+            }
+        }
+    }
+    .placeholder {
+        height: #{178rpx};
+        width: 100%;
+    }
+
+    .apply {
+        position: fixed;
+        bottom: 0;
+        left: 0;
+        z-index: 2;
+        height: #{154rpx};
+        width: 100%;
+        background-color: #fff;
+        padding-top: #{26rpx};
+        padding-left: #{24rpx};
+        .apply-btn {
+            width: #{702rpx};
+            height: #{88rpx};
+            line-height: #{88rpx};
+            border-radius: #{44rpx};
+            text-align: center;
+            color: #fff;
+            font-size: #{32rpx};
+        }
+    }
+</style>

+ 292 - 0
src/plugins/exchange/gift/gift.vue

xqd
@@ -0,0 +1,292 @@
+<template>
+    <app-layout>
+        <scroll-view scroll-y :style="{'height':`${windowHeight}px`}">
+            <view class="app-goods" v-show="loading">
+                <view class="banner">
+                    <app-banner
+                        :videoUrl="goods.video_url"
+                        :picList="goods.pic_list"
+                        :goods_id="goods.id"
+                        :isCart="false"
+                        sign="exchange"
+                    ></app-banner>
+                </view>
+                <view class="other-info">
+                    <view class="t-omit-two goods-name">{{goods.name}}</view>
+                    <view class="code" :style="{'color': status == 'unused' ? getTheme.color : '#999999','background-color': status == 'unused' ? getTheme.background_o : '#f5f5f5'}">{{code}}</view>
+                    <view v-if="status == 'unused'" class="app-share">
+                        <app-form-id @click="shareShow = true">
+                            <image class="app-icon" src="../../../static/image/icon/icon-share.png"></image>
+                            <text class="app-text">赠送</text>
+                        </app-form-id>
+                    </view>
+                </view>
+                <app-share-qr-code v-model="shareShow"
+                                   :url="url"
+                                   title="生成赠送海报"
+                                   :goods="goods"
+                                   @share="hShareAppMessage"
+                                   :theme="getTheme"
+                                   :has-poster-nav="false"
+                ></app-share-qr-code>
+                <!-- 商品详情 -->
+                <bd-detail :detail="goods.detail"></bd-detail>
+                <!-- 底部空格 -->
+                <view class="safe-area-inset-bottom">
+                    <view class="u-bottom-height"></view>
+                </view>
+                <!-- 底部按钮 -->
+                <view class="safe-area-inset-bottom u-bottom-fixed">
+                    <view class="buttons dir-left-nowrap">
+                        <view class="app-button main-center cross-center">
+                            <view @click="copy" v-if="status == 'unused'" class="app-exhange" :style="{'background': getTheme.background_s_gradient_o,'color': getTheme.secondary_text}">
+                                复制兑换码
+                            </view>
+                            <view @click="toExchange" v-if="status == 'unused'" class="app-exhange" :style="{'background': getTheme.background_gradient_o,'color': getTheme.main_text}">
+                                立即兑换
+                            </view>
+                            <view class="app-over" v-if="status != 'unused'">
+                                {{status == 'used' ? '已兑换': '已失效'}}
+                            </view>
+                        </view>
+                    </view>
+                </view>
+            </view>
+        </scroll-view>
+    </app-layout>
+</template>
+
+<script>
+    import {mapGetters, mapState} from 'vuex';
+    import appBanner from '../../../components/page-component/goods/app-goods-banner.vue';
+    import appShareQrCode from '../../../components/page-component/app-share-qr-code-poster/app-share-qr-code-poster.vue';
+    import bdDetail from '@/components/page-component/goods/bd-detail.vue';
+
+    export default {
+        name: 'goods',
+        data() {
+            return {
+                shareShow: false,
+                goods: {},
+                url: this.$api.exchange.qrcode,
+                show: false,
+                list: [],
+                code: null,
+                id: null,
+                status: '',
+                windowHeight: 667,
+                loading: false,
+                first: true,
+            }
+        },
+        onLoad(options) { this.$commonLoad.onload(options);
+            let that = this;
+            that.code = options.code;
+            that.windowHeight = uni.getSystemInfoSync().windowHeight;
+            that.$showLoading({
+                type: 'global',
+                text: '加载中...'
+            });
+            that.request({
+                url: that.$api.exchange.me_detail,
+                data: {
+                    code: that.code,
+                }
+            }).then(response => {
+                if(response) {
+                    that.first = false;
+                    let { goods_attr, code,status } = response;
+                    that.url = that.url + '&code=' + code;
+                    that.goods = goods_attr;
+                    that.code = code;
+                    that.status = status;
+                    that.loading = true;
+                    that.$hideLoading();
+                }
+            });
+        },
+        onShow() {
+            if(this.first) {
+                return false
+            }
+            this.$showLoading();
+            this.$nextTick(() => {
+                let that = this;
+                that.request({
+                    url: that.$api.exchange.me_detail,
+                    data: {
+                        code: that.code,
+                    }
+                }).then(response => {
+                    let { goods_attr, code,status } = response;
+                    that.goods = goods_attr;
+                    that.code = code;
+                    that.status = status;
+                    that.loading = true;
+                    that.$hideLoading();
+                });
+            })
+        },
+        computed: {
+            ...mapState('gConfig',{
+                iphone: (data) => {
+                    return data.iphone;
+                },
+                iphoneHeight: (state) =>{
+                    return  state.iphoneHeight;
+                },
+            }),
+            ...mapGetters('mallConfig', {
+                getTheme: 'getTheme',
+            }),
+            ...mapState({
+                mall: state => state.mallConfig.mall,
+                userInfo: state => state.user.info
+            })
+        },
+        // #ifdef MP
+        onShareAppMessage() {
+            return this.hShareAppMessage();
+        },
+        // #endif
+        methods: {
+            hShareAppMessage(s = false) {
+                return this.$shareAppMessage({
+                    path: '/plugins/exchange/gift/gift',
+                    title: this.goods.app_share_title ? this.goods.app_share_title : this.goods.name,
+                    imageUrl: this.goods.app_share_pic ? this.goods.app_share_pic : '',
+                    params: {
+                        code: this.code,
+                    }
+                }, s);
+            },
+            copy() {
+                this.$utils.uniCopy({
+                    data: this.code,
+                    success() {
+                        //#ifndef MP-WEIXIN
+                        uni.showToast({title: '复制成功'});
+                        // #endif
+                    },
+                });
+            },
+            toExchange() {
+                uni.navigateTo({
+                    url: '/plugins/exchange/detail/detail?code=' + this.code
+                })
+            },
+            async request({url, data}) {
+                const response = await this.$request({
+                    url: url,
+                    data: data,
+                });
+                if (response.code === 0) {
+                    return response.data;
+                }else {
+                    uni.showModal({
+                        title: '提示',
+                        content: response.msg,
+                        showCancel: false,
+                        success: function (res) {
+                            uni.navigateBack();
+                        }
+                    });
+                }
+            }
+        },
+        components: {
+            'app-banner': appBanner,
+            'app-share-qr-code': appShareQrCode,
+            bdDetail
+        }
+    }
+</script>
+
+<style scoped lang="scss">
+    .other-info {
+        background-color: #fff;
+        padding-top: 24rpx;
+        padding-bottom: 24rpx;
+        margin-bottom: 24rpx;
+        position: relative;
+        .goods-name {
+            font-size: #{32rpx};
+            color: #353535;
+            margin: 0 #{24rpx} #{50rpx};
+        }
+        .code {
+            margin-left: 24rpx;
+            display: inline-block;
+            padding: 16rpx 46rpx;
+            border-radius: 40rpx;
+            font-size: 32rpx;
+            font-weight: 600;
+            &.default {
+                background-color: #F5F5F5;
+                color: #999999;
+            }
+        }
+        .app-share {
+            width: #{40rpx};
+            height: #{102rpx};
+            position: absolute;
+            right: #{24rpx};
+            bottom: #{26rpx};
+            .app-icon {
+                width: #{40rpx};
+                height: #{40rpx};
+            }
+            .app-text {
+                color: #666666;
+                font-size: #{20rpx};
+                position: absolute;
+                top: #{50rpx};
+                left: 0;
+            }
+        }
+    }
+
+    .app-goods {
+        background-color: #f7f7f7;
+    }
+    .buttons {
+        width: #{750rpx};
+        height: #{110rpx};
+        border-top: #{1rpx} solid #e2e2e2;
+        .app-button {
+            width: 100%;
+            height: #{110rpx};
+            text-align: center;
+            line-height: #{110rpx};
+            background-color: #fff;
+            .app-over {
+                background: #e9e9e9;
+                width: #{702rpx};
+                border-radius: #{41rpx};
+                color: #999999;
+                height: #{82rpx};
+                line-height: #{82rpx};
+                font-size: #{28rpx};
+            }
+            .app-exhange {
+                margin: 0 10rpx;
+                width: 340rpx;
+                border-radius: 41rpx;
+                height: 82rpx;
+                line-height: 82rpx;
+                font-size: 28rpx;
+            }
+        }
+    }
+    .u-bottom-fixed {
+        position: fixed;
+        bottom: 0;
+        left: 0;
+        width: 100%;
+        z-index: 1602;
+        background-color: #ffffff;
+    }
+    .u-bottom-height {
+        height: 110upx;
+    }
+</style>

+ 460 - 0
src/plugins/exchange/goods/goods.vue

xqd
@@ -0,0 +1,460 @@
+<template>
+    <app-layout>
+        <view v-if="!goods" class="u-goods-detail"></view>
+        <view class="app-goods" v-show="loading" v-if="goods">
+            <app-banner
+                :videoUrl="goods.video_url"
+                :share="goods.share"
+                :picList="goods.pic_url"
+                :goods_id="goods_id"
+                :isCart="false"
+                sign="exchange"
+            ></app-banner>
+            <bd-info
+                :theme="getTheme"
+                :name="goods.name"
+                :is-negotiable="goods.is_negotiable"
+                :subtitle="goods.subtitle"
+                :level-show="goods.level_show"
+                :price="goods.price"
+                :original-price="goods.original_price"
+                :price-max="goods.price_max"
+                :price-min="goods.price_min"
+                :price-member-max="goods.price_member_max"
+                :price-member-min="goods.price_member_min"
+                :discount='discount'
+                :is-vip-card-user="is_vip_card_user"
+                :sales="goods.sales"
+                :unit="goods.unit"
+                :is-sales="goods.is_sales"
+                :is-vip="is_vip"
+                :flash-sale="flash_sale"
+                :goods-id="goods.id"
+                :extra-quick-share="goods.extra_quick_share"
+                :app-share-pic="goods.app_share_pic"
+                :app-share-title="goods.app_share_title"
+                :poster-config="posterConfig"
+                :poster-generate="posterGenerate"
+                :has-poster-nav="true"
+                v-bind:goods="goods"
+                :share-url="url"
+                :has-underline-price="false"
+                @share="hShareAppMessage"
+				:min-number="0"
+				:limit-buy="goods.limit_buy"
+            >
+            </bd-info>
+            <bd-coupon v-if="goods.goods_coupon_center" @change="setCoupon" :theme="getTheme" :coupons="goods.goods_coupon_center"></bd-coupon>
+            <bd-xbc
+                v-if="goods"
+                :coAttr="false"
+                :guarantee-title="goods.guarantee_title"
+                :guarantee-pic="goods.guarantee_pic"
+                :param_content="goods.param_content"
+                :param_name="goods.param_name"
+                :services="goods.services"
+            ></bd-xbc>
+            <!--商品信息-->
+            <bd-hc
+                v-if="goods.goods_marketing_award"
+                :integral="goods.goods_marketing_award.integral"
+                :coupon="goods.goods_marketing_award.coupon"
+                :card="goods.goods_marketing_award.card"
+                :balance="goods.goods_marketing_award.balance"
+                :theme="getTheme"
+            ></bd-hc>
+            <bd-comments v-if="goods_id > 0" :goods-id="goods_id"></bd-comments>
+            <bd-detail :detail="goods.detail"></bd-detail>
+            <!-- 底部空格 -->
+            <view class="safe-area-inset-bottom">
+                <view :class="[uBottomHeight]"></view>
+            </view>
+            <!-- 底部按钮 -->
+            <view v-if="is_open" class="safe-area-inset-bottom u-bottom-fixed">
+                <view v-if="full_reduce">
+                    <app-goods-full-reduce
+                        :theme="getTheme"
+                        :full_reduce="full_reduce"
+                    >
+                    </app-goods-full-reduce>
+                </view>
+				<view v-if="goods.sell_time > 0">
+					<app-sell-tip :time="goods.sell_time" @changeTime="changeTime"></app-sell-tip>
+				</view>
+				<app-jump-button form>
+                <view  class="buttons dir-left-nowrap">
+                    <view class="app-button main-center cross-center">
+                        <view @click="toExchange" v-if="goods.goods_num > 0 && !goods.is_finish_sell" class="app-exhange" :style="{'background': !goods || goods.buy_goods_auth ? getTheme.background_gradient_btn : '#999999'}">
+                            {{rightRemindText}}
+                        </view>
+                        <view class="app-over" :class="[disableBtn]" v-else>
+                            {{disableBtnText}}
+                        </view>
+                    </view>
+                </view>
+				</app-jump-button>
+            </view>
+        </view>
+        <app-close v-if="showClose" :modal="false" @update="getMall"></app-close>
+    </app-layout>
+</template>
+
+<script>
+    import {mapGetters, mapState} from 'vuex';
+    import appBanner from '../../../components/page-component/goods/app-goods-banner.vue';
+    import appGoodsFullReduce from '../../../components/page-component/goods/app-goods-full-reduce.vue';
+    import appClose from '@/components/basic-component/app-close/app-close.vue';
+    import bdInfo from '@/components/page-component/goods/bd-info';
+    import bdCoupon from '@/components/page-component/goods/bd-coupon.vue';
+    import bdXbc from '@/components/page-component/goods/bd-xbc.vue';
+    import bdKb from '@/components/page-component/goods/bd-kb.vue';
+    import bdHc from '@/components/page-component/goods/bd-hc.vue';
+    import bdDetail from '@/components/page-component/goods/bd-detail.vue';
+    import bdComments from '@/components/page-component/goods/bd-comments.vue';
+    import appSellTip from '@/components/page-component/goods/app-sell-tip.vue';
+	import goodsMixin from '@/core/goods-mixin.js';
+
+    export default {
+        name: 'goods',
+		mixins: [goodsMixin],
+        data() {
+            return {
+                showClose: false,
+                is_open: false,
+                goods: {
+                    id: '',
+                    name: '',
+                    cover_pic: '',
+                    price: '',
+                },
+                posterConfig: this.$api.exchange.poster_config,
+                posterGenerate: this.$api.exchange.poster_generate,
+                url: '',
+                is_vip: false,
+                is_vip_card_user: 0,
+                show: false,
+                list: [],
+                goods_id: -1,
+                loading: false,
+                first: true,
+                discount: null,
+                flash_sale: null,
+                full_reduce: null,
+				disable: 'disable',
+            }
+        },
+        onLoad(options) { this.$commonLoad.onload(options);
+            // #ifdef MP-WEIXIN
+            wx.showShareMenu({
+                menus: ['shareAppMessage', 'shareTimeline']
+            })
+            // #endif
+            this.goods_id = +options.goods_id;
+            this.posterConfig = this.posterConfig + '&goods_id=' + this.goods_id;
+            this.posterGenerate = this.posterGenerate + '&goods_id=' + this.goods_id;
+            this.$showLoading({
+                type: 'global',
+                text: '加载中...'
+            });
+            this.request({
+                url: this.$api.exchange.detail,
+                data: {
+                    id: this.goods_id,
+                }
+            }).then(response => {
+                if(response) {
+                    this.first = false;
+                    let { goods } = response;
+                    this.goods = goods;
+                    this.loading = true;
+                    this.url = `${this.$api.goods.poster}&goods_id=${this.goods.id}`;
+                    if(this.goods.vip_card_appoint.discount) {
+                        this.is_vip = true;
+                        this.discount = this.goods.vip_card_appoint.discount
+                    }
+                    this.full_reduce = goods.goods_activity.full_reduce;
+                    this.flash_sale = this.goods.plugin_extra.flash_sale;
+                    this.is_vip_card_user = this.goods.vip_card_appoint.is_vip_card_user;
+                    // #ifdef H5
+                    this.hShareAppMessage();
+                    // #endif
+                    this.$hideLoading();
+                }
+            });
+        },
+        onShow() {
+            this.showClose = false;
+            setTimeout(()=>{
+                this.showClose = true;
+            })
+            if(this.first) {
+                return false
+            }
+            this.$showLoading();
+            this.$nextTick(() => {
+                this.request({
+                    url: this.$api.exchange.detail,
+                    data: {
+                        id: this.goods_id,
+                    }
+                }).then(response => {
+                    let { goods } = response;
+                    this.goods = goods;
+                    this.loading = true;
+                    this.full_reduce = goods.goods_activity.full_reduce;
+                    this.url = `${this.$api.goods.poster}&goods_id=${this.goods.id}`;
+                    if(this.goods.vip_card_appoint.discount) {
+                        this.is_vip = true;
+                        this.discount = this.goods.vip_card_appoint.discount
+                    }
+                    this.flash_sale = this.goods.plugin_extra.flash_sale;
+                    this.is_vip_card_user = this.goods.vip_card_appoint.is_vip_card_user;
+                    this.$hideLoading();
+                });
+            })
+        },
+        computed: {
+            ...mapState('gConfig',{
+                iphone: (data) => {
+                    return data.iphone;
+                },
+                iphoneHeight: (state) =>{
+                    return  state.iphoneHeight;
+                },
+            }),
+            ...mapGetters('mallConfig', {
+                getTheme: 'getTheme',
+            }),
+            ...mapState({
+                mall: state => state.mallConfig.mall,
+                userInfo: state => state.user.info,
+				isTip: state => state.mallConfig.mall.setting.is_remind_sell_time
+            }),
+            themeObject:function() {
+                return {
+                    back: this.getTheme + '-m-back ' + this.getTheme,
+                    backO: this.getTheme + '-m-back-o ' + this.getTheme,
+                    theme: this.getTheme,
+                    color: this.getTheme + '-m-text ' + this.getTheme,
+                    sBack: this.getTheme + '-s-back ' + this.getTheme
+                }
+            },
+			buyBtn() {
+				if (!this.goods || this.goods.buy_goods_auth) {
+					return this.getTheme + '-m-gradient-o ' + this.getTheme
+				} else {
+					return this.disable + '-m-back ' + this.disable;
+				}
+			},
+			uBottomHeight() {
+				if (this.full_reduce && this.goods.sell_time > 0) {
+					return 'u-bottom-height-2';
+				} else if (this.full_reduce || this.goods.sell_time > 0) {
+					return 'u-bottom-height-1';
+				} else {
+					return 'u-bottom-height-0';
+				}
+			},
+			leftTip() {
+				let leftTip = '';
+				if (!(this.isTip == 0 && this.goods.sell_time > 0)) {
+					leftTip = 'bd-btn-left bd-btn-half';
+				} else {
+					leftTip = 'box-grow-1';
+				}
+				return this.goods && this.goods.type === 'goods' ? leftTip : '';
+			},
+			disableBtn() {
+				if (this.goods.is_finish_sell || this.goods.sell_time > 0) {
+					return 'btn-finish-sell';
+				} else {
+					return 'bd-oversell-btn';
+				}
+			},
+			disableBtnText() {
+				if (this.goods.is_finish_sell) {
+					return '商品已下架';
+				} else if (this.goods.sell_time > 0) {
+					return '商品未开售';
+				} else {
+					return '已售罄';
+				}
+			},
+			remindParams() {
+				return {
+					sell_time: this.goods.sell_time,
+					goods_id: this.goods.id,
+					template_message_list: this.goods.template_message_list,
+					buy_text: '立即购买'
+				};
+			},
+        },
+        // #ifdef MP-WEIXIN
+        onShareTimeline() {
+            // 分享朋友圈beta
+            return this.$shareTimeline({
+                title: this.goods.app_share_title ? this.goods.app_share_title : this.goods.name,
+                imageUrl: this.goods.pic_url[0].pic_url,
+                query: {
+                    goods_id: this.goods.id
+                }
+            });
+        },
+        // #endif
+        // #ifdef MP
+        onShareAppMessage() {
+            return this.hShareAppMessage();
+        },
+        // #endif
+        methods: {
+            hShareAppMessage(s = false){
+                return this.$shareAppMessage({
+                    path: '/plugins/exchange/goods/goods',
+                    title: this.goods.app_share_title ? this.goods.app_share_title : this.goods.name,
+                    imageUrl: this.goods.app_share_pic ? this.goods.app_share_pic : this.goods.pic_url[0].pic_url,
+                    desc: this.goods.subtitle,
+                    params: {
+                        goods_id: this.goods.id,
+                    }
+                },s);
+            },
+            getMall(e) {
+                this.is_open = e.is_open == 1 ? true : false;
+            },
+            toExchange() {
+				if (!this.goods.buy_goods_auth) {
+					this.$tips.showToast({
+						title: '您暂无权限购买该商品',
+						icon: 'none'
+					});
+					return;
+				}
+				if (this.goods.sell_time > 0) {
+					this.rightTip();
+					return ;
+				}
+				if (typeof this.goods.limit_buy !== 'undefined' && this.goods.limit_buy.status == 1 && this.goods.limit_buy.rest_number < 1) {
+                    this.$tips.showToast({
+                        title: this.goods.limit_buy.text,
+                        icon: 'none'
+                    });
+					return false;
+				}
+                let attr = [];
+                for (let i in this.goods.attr[0].attr_list) {
+                    attr.push({
+                        attr_id: this.goods.attr[0].attr_list[i].attr_id,
+                        attr_group_id: this.goods.attr[0].attr_list[i].attr_group_id
+                    });
+                }
+                let mch_list = [{
+                    mch_id: 0,
+                    goods_list: [{
+                        id: this.goods.id,
+                        attr: attr,
+                        num: 1,
+                        cat_id: 0,
+                        goods_attr_id: this.goods.attr[0].id
+                    }]
+                }];
+                let url = `/pages/order-submit/order-submit?mch_list=${JSON.stringify(mch_list)}`;
+                url += `&preview_url=${encodeURIComponent(this.$api.exchange.order_preview)}&submit_url=${encodeURIComponent(this.$api.exchange.order_submit)}&plugin=exchange`;
+                uni.navigateTo({
+                    url: url
+                })
+            },
+            async request({url, data}) {
+                const response = await this.$request({
+                    url: url,
+                    data: data,
+                });
+                if (response.code === 0) {
+                    return response.data;
+                }else {
+                    uni.showModal({
+                        title: '提示',
+                        content: response.msg,
+                        showCancel: false,
+                        success: function (res) {
+                            uni.navigateBack();
+                        }
+                    });
+                }
+            },
+            setCoupon(index) {
+                this.$set(this.goods.goods_coupon_center[index], 'is_receive', 1);
+            },
+			changeTime(time) {
+				this.goods.sell_time = time;
+			},
+        },
+        components: {
+            'app-banner': appBanner,
+            appClose,
+            appGoodsFullReduce,
+            bdInfo,
+            bdCoupon,
+            bdXbc,
+            bdKb,
+            bdHc,
+            bdDetail,
+            bdComments,
+			appSellTip
+        }
+    }
+</script>
+
+<style lang="scss">
+    .buttons {
+        width: #{750rpx};
+        height: #{110rpx};
+        border-top: #{1rpx} solid #e2e2e2;
+        .app-button {
+            width: 100%;
+            height: #{110rpx};
+            text-align: center;
+            line-height: #{110rpx};
+            background-color: #fff;
+            .app-exhange {
+                width: #{702rpx};
+                color: #fff;
+                border-radius: #{41rpx};
+                height: #{82rpx};
+                line-height: #{82rpx};
+                font-size: #{28rpx};
+            }
+            .app-over {
+                width: #{702rpx};
+                border-radius: #{41rpx};
+                height: #{82rpx};
+                line-height: #{82rpx};
+                font-size: #{28rpx};
+            }
+			.bd-oversell-btn {
+				background: #e9e9e9;
+                color: #999999;
+			}
+			.btn-finish-sell {
+				background: linear-gradient(to right, rgba(153, 153, 153, 1), rgba(153, 153, 153, 0.7)) ;
+				color: #ffffff;
+			}
+        }
+    }
+    .u-bottom-height-0 {
+        height: 110upx;
+    }
+    .u-bottom-height-1 {
+        height: 190upx;
+    }
+    .u-bottom-fixed {
+        position: fixed;
+        bottom: 0;
+        left: 0;
+        width: 100%;
+        z-index: 1602;
+        background-color: #ffffff;
+    }
+    .u-bottom-height-2 {
+        height: 270upx;
+    }
+</style>

BIN
src/plugins/exchange/image/balance.png


BIN
src/plugins/exchange/image/card.png


BIN
src/plugins/exchange/image/coupon.png


BIN
src/plugins/exchange/image/error.png


BIN
src/plugins/exchange/image/point.png


BIN
src/plugins/exchange/image/scan.png


BIN
src/plugins/exchange/image/svip.png


+ 681 - 0
src/plugins/exchange/index/index.vue

xqd
@@ -0,0 +1,681 @@
+<template>
+    <app-layout>
+        <app-tab-nav :setTop="0" :border="false" :shadow="false" :height="100" :tabList="tabList" :padding="0" :activeItem="activeTab" @click="tabStatus" :theme="getTheme"></app-tab-nav>
+        <view v-if="activeTab == '0'" class="scan">
+            <view>输入兑换码或者扫码兑换二维码开始兑换</view>
+            <view class="scan-input">
+                <input @focus="hiddenBottom=false" @blur="hiddenBottom=true" placeholder="请输入兑换码" v-model="code" type="text">
+                <image v-if="!is_not_wechat" @click="scan" src="./../image/scan.png"></image>
+            </view>
+            <view @click="clerk" class="scan-button" :style="{'background-color': code.length > 0 ? getTheme.background : '#d6d6d6','color' : code.length > 0 ? '#fff' : '#b2b2b2'}">兑换</view>
+        </view>
+        <view v-if="activeTab == '1'">
+            <view v-if="list.length > 0" class="item" v-for="(item,index) in list" :key="index">
+                <view class="main-between cross-center status">
+                    <view class="item-code" :style="{'background-color': item.status == 2 ? getTheme.background_o : '#F5F5F5','color' : item.status == 2 ? getTheme.color : '#999999'}">{{item.code}}</view>
+                    <view @click="toDetail(item)" class="dir-left-nowrap cross-center item-status" :style="{'color': item.status == 2 ? getTheme.color : '#999999'}">
+                        <view>{{item.status == 2 ? item.last_num + '项待领取' : '已全部领取'}}</view>
+                        <i v-if="item.status == 2" :style="{'color': getTheme.color}" class="iconfont icon-right">&#xe7eb;</i>
+                        <image v-else src="/static/image/icon/right.png"></image>
+                    </view>
+                </view>
+                <view class="item-time">兑换时间:{{item.r_raffled_at}}</view>
+            </view>
+            <view style="padding-top: 30%" v-if="list.length == 0">
+                <app-no-goods title="暂无兑换记录" :is_image="1" background="#f7f7f7"></app-no-goods>
+            </view>
+        </view>
+        <view @click="showRule" class="use-info" :style="{'color': getTheme.color}" :class="[`${tabbarbool? 'tabbarbool':''}`]" v-if="setting.is_rules == 1 && activeTab == '0' && hiddenBottom">使用说明</view>
+        <u-mask :show="dialog" :maskClickAble="false" :zoom="false">
+            <view class="dialog">
+                <image class="dialog-img" src="./../image/error.png"></image>
+                <view class="dialog-msg">
+                    <text>{{msg}}</text>
+                </view>
+                <view class="dialog-other">{{other}}</view>
+                <view @click="dialog=false;code=''" :style="{'background-color': getTheme.background}" class="dialog-button">我知道了</view>
+            </view>
+        </u-mask>
+        <view v-if="showRules" class="dialog-bg">
+            <view class="u-rules" :animation="animationData" :style="{bottom: bottom}" :class="[`${tabbarbool? 'tabbarbool':''}`,`${iphone_x? 'iphone_x':''}`]">
+                <view class="u-rules-top dir-right-nowrap">
+                    <view v-if="over" @click="showRules=false;bottom='-998rpx';animationData={}" class="end-close main-center cross-center">
+                        <image src="/static/image/icon/icon-close.png"></image>
+                    </view>
+                </view>
+
+                <view class="u-rules-content">
+                    <parse :content="setting.rules"></parse>
+                </view>
+            </view>
+        </view>
+        <view @click="toGift" v-if="setting.is_to_gift == 1 && hiddenBottom" class="jump-dialog cross-center dir-top-nowrap main-center" :class="[`${tabbarbool? 'tabbarbool':''}`]">
+            <image :src="setting.to_gift_pic"></image>
+            <view>礼品卡</view>
+        </view>
+    </app-layout>
+</template>
+<script>
+    import appTabNav from "../../../components/basic-component/app-tab-nav/app-tab-nav.vue";
+    import uMask from '../../../components/basic-component/u-mask/u-mask.vue';
+    import parse from "../../../components/basic-component/app-rich/parse.vue";
+    import appNoGoods from '../../../components/page-component/app-no-goods/app-no-goods.vue';
+    import { mapState, mapGetters } from "vuex";
+
+    export default {
+        name: "index",
+        data() {
+            return {
+                currentRoute: this.$platDiff.route(),
+                tabbarbool: false,
+                iphone_x: false,
+                tabList: [
+                    {id:0, name: '兑换礼品'},
+                    {id:1, name: '兑换记录'}
+                ],
+                over: false,
+                hiddenBottom: true,
+                code: '',
+                bottom: '-998rpx',
+                activeTab: '0',
+                list: [],
+                setting: {},
+                animationData: {},
+                showRules: false,
+                dialog: false,
+                more: false,
+                loading: false,
+                is_not_wechat: false,
+                msg: '',
+                other: '',
+                page: 1,
+            };
+        },
+        watch: {
+            tabBarNavs: {
+                handler: function() {
+                    this.b();
+                },
+                immediate: true,
+            }
+        },
+        components: {
+            "app-tab-nav": appTabNav,
+            parse,
+            "app-no-goods": appNoGoods,
+            "u-mask": uMask
+        },
+        computed: {
+            ...mapState({
+                tabBarNavs: state => state.mallConfig.navbar.navs,
+            }),
+            ...mapGetters('mallConfig', {
+                getTheme: 'getTheme'
+            })
+        },
+        // #ifdef MP
+        onShareAppMessage() {
+            return this.$shareAppMessage({
+                title: this.$children[0].navigationBarTitle,
+                path: "/plugins/exchange/index/index",
+            });
+        },
+        // #endif
+        // #ifdef MP-WEIXIN
+        onShareTimeline() {
+          // 分享朋友圈beta
+          return this.$shareTimeline({
+            title: this.$children[0].navigationBarTitle,
+            query: {} // 此处填写页面的参数
+          });
+        },
+        // #endif
+        onReachBottom() {
+            if(this.more) {
+                this.page++;
+                this.getMore();
+            }
+        },
+        onLoad(options) { this.$commonLoad.onload(options);
+            let that = this;
+            // #ifdef H5
+            this.is_not_wechat = !this.$jwx.isWechat();
+            // #endif
+            if(options.code) {
+                that.code = options.code
+            }
+            if(options.token && options.library_id && options.created_at) {
+                that.getActive(options.token, options.library_id, options.created_at)
+            }
+            // #ifdef MP-WEIXIN
+            wx.showShareMenu({
+              menus: ['shareAppMessage', 'shareTimeline']
+            })
+            // #endif
+            uni.getSystemInfo({
+                success: function (res) {
+                    that.height = -res.screenHeight;
+                    if(res.model.indexOf('iPhone X') > -1 || res.model.indexOf('iPhone 11') > -1 || res.model.indexOf('iPhone11') > -1 || res.model.indexOf('iPhone12') > -1 || res.model.indexOf('Unknown Device') > -1) {
+                        that.iphone_x = true;
+                    }
+                }
+            });
+            that.$request({
+                url: that.$api.exchange.setting,
+            }).then(response=>{
+                if(response.code == 0) {
+                    that.setting = response.data;
+                }else {
+                    uni.showToast({
+                        title: response.msg,
+                        icon: 'none',
+                        duration: 1000
+                    });
+                }
+            })
+        },
+        onShow() {
+            if(this.activeTab == '1') {
+                this.getList();
+            }
+        },
+        methods: {
+            getActive(token, library_id, created_at) {
+                let that = this;
+                uni.showLoading({
+                    mask: true,
+                    title: '获取兑换码...'
+                });
+                that.$request({
+                    url: that.$api.exchange.code,
+                    data: {
+                        token: token,
+                        library_id: library_id,
+                        created_at: created_at,
+                    }
+                }).then(response=>{
+                    uni.hideLoading();
+                    this.loading = false;
+                    if(response.code == 0) {
+                        this.code = response.data.code
+                    }else {
+                        this.msg = response.msg;
+                        this.other = '';
+                        this.dialog = true;
+                    }
+                }).catch(response => {
+                    uni.hideLoading();
+                });
+            },
+            b() {
+                // #ifndef H5
+                let currentRoute = this.currentRoute;
+                for (let i = 0; i < this.tabBarNavs.length; i++) {
+                    if(currentRoute.includes(this.tabBarNavs[i].url.split('?')[0])) {
+                        return this.tabbarbool = true;
+                    }
+                }
+                // #endif
+                return  this.tabbarbool = false;
+            },
+            showRule() {
+                let that = this;
+                that.over = false;
+                that.showRules = true;
+                var animation = uni.createAnimation({
+                    duration: 1000,
+                    timingFunction: 'ease',
+                })
+                that.animationData = animation
+                setTimeout(function(){
+                    let num = 0;
+                    if(that.tabbarbool) {
+                        num += 55
+                    }
+                    animation.bottom(-500).bottom(num).step()
+                    that.animationData = animation.export();
+                    setTimeout(function(){
+                        that.bottom = num *2 + 'rpx';
+                        that.over = true;
+                    },1200)
+                },200)
+            },
+            scan() {
+                let that = this;
+                // #ifndef MP-ALIPAY || H5
+                uni.scanCode({
+                    success(res) {
+                        if(res.scanType == "CODE_128" || (res.result && res.result.length == 12)) {
+                            that.code = res.result
+                        } else {
+                            if(res.path) {
+                                uni.showLoading({
+                                    mask: true,
+                                    title: '获取兑换码...'
+                                });
+                                let path = res.path
+                                path = path.split('?');
+                                let scene = path[1];
+                                let reg = new RegExp("scene=", "g");
+                                scene = path[1].replace(reg, "");
+                                that.$request({
+                                    url: that.$api.default.qrcode_parameter,
+                                    data: {
+                                        token: scene
+                                    }
+                                }).then(response => {
+                                    if (response.code === 0) {
+                                        if(response.data.detail && response.data.detail.data.type == 'auto') {
+                                            that.getActive(response.data.detail.data.token, response.data.detail.data.library_id, response.data.detail.data.created_at)
+                                        }else {
+                                            uni.hideLoading();
+                                            uni.showToast({
+                                                title: '未获取到兑换码',
+                                                icon: 'none',
+                                                duration: 1000
+                                            });
+                                            that.code = response.data.detail.data.code;
+                                        }
+                                    }
+                                });
+                            }else {
+                                uni.showToast({
+                                    title: '暂不支持此二维码,请使用应用内扫一扫功能',
+                                    icon: 'none',
+                                    duration: 1000
+                                });
+                            }
+                        }
+                    }
+                })
+                // #endif
+                // #ifdef MP-ALIPAY
+                my.ap.navigateToAlipayPage({
+                    appCode:'alipayScan',
+                    success:(res) => {
+                    },
+                    fail:(res) => {
+                        my.alert({content:'失败:'+JSON.stringify(res)});
+                    }
+                });
+                // #endif
+                // #ifdef H5
+                if (this.$jwx.isWechat()) {
+                    this.$jwx.scanQRCode({
+                        success(res) {
+                            if(res.resultStr) {
+                                if(res.resultStr.indexOf(',') > 0){
+                                 //条形码时返回的格式类似为【code128,123456789】      
+                                     var dealserialNumber=res.resultStr.split(',')[1];          
+                                     dealserialNumber = dealserialNumber.replace(/[^a-z\d]/ig, "");//处理条形码扫描的字符
+                                     that.code = dealserialNumber;//扫描结果传递到的处理页面
+                                }else{
+                                    //二维码时
+                                    location.href=res.resultStr;//扫描结果传递到的处理页面
+                                }
+                            }else if(res.scanType == "CODE_128" || (res.result && res.result.length == 12)) {
+                                that.code = res.result
+                            } else {
+                                if(res.path) {
+                                    uni.showLoading({
+                                        mask: true,
+                                        title: '获取兑换码...'
+                                    });
+                                    let path = res.path
+                                    path = path.split('?');
+                                    let scene = path[1];
+                                    let reg = new RegExp("scene=", "g");
+                                    scene = path[1].replace(reg, "");
+                                    that.$request({
+                                        url: that.$api.default.qrcode_parameter,
+                                        data: {
+                                            token: scene
+                                        }
+                                    }).then(response => {
+                                        if (response.code === 0) {
+                                            if(response.data.detail.data.type == 'auto') {
+                                                that.getActive(response.data.detail.data.token, response.data.detail.data.library_id, response.data.detail.data.created_at)
+                                            }else {
+                                                uni.hideLoading();
+                                                that.code = response.data.detail.data.code;
+                                            }
+                                        }
+                                    });
+                                }else {
+                                    uni.showToast({
+                                        title: '暂不支持此二维码,请使用应用内扫一扫功能',
+                                        icon: 'none',
+                                        duration: 1000
+                                    });
+                                }
+                            }
+                        }
+                    })
+                }else {
+                    uni.showToast({
+                        title: '暂不支持浏览器点击扫码,请应用扫一扫功能',
+                        icon: 'none',
+                        duration: 1000
+                    });
+                }
+                // #endif
+            },
+            tabStatus(e) {
+                if(this.loading) {
+                    return false
+                }
+                this.list = [];
+                this.page = 1;
+                this.activeTab = e.currentTarget.dataset.id;
+                this.getList();
+            },
+            getMore() {
+                let that = this;
+                if(this.loading) {
+                    return false
+                }
+                this.loading = true;
+                that.more = false;
+                uni.showLoading({
+                    mask: true,
+                    title: '加载中...'
+                });
+                that.$request({
+                    url: that.$api.exchange.log,
+                    data: {
+                        page: that.page
+                    }
+                }).then(response=>{
+                    uni.hideLoading();
+                    this.loading = false;
+                    if(response.code == 0) {
+                        that.list = that.list.concat(response.data.list);
+                        if(that.list.length == response.data.pagination.pageSize) {
+                            that.more = true;
+                        }
+                    }else {
+                        uni.showToast({
+                            title: response.msg,
+                            icon: 'none',
+                            duration: 1000
+                        });
+                    }
+                }).catch(response => {
+                    uni.hideLoading();
+                });
+            },
+            getList() {
+                let that = this;
+                if(this.loading) {
+                    return false
+                }
+                this.loading = true;
+                that.page = 1;
+                that.more = false;
+                uni.showLoading({
+                    mask: true,
+                    title: '加载中...'
+                });
+                that.$request({
+                    url: that.$api.exchange.log
+                }).then(response=>{
+                    this.loading = false;
+                    uni.hideLoading();
+                    if(response.code == 0) {
+                        that.list = response.data.list;
+                        if(that.list.length == response.data.pagination.pageSize) {
+                            that.more = true;
+                        }
+                    }else {
+                        uni.showToast({
+                            title: response.msg,
+                            icon: 'none',
+                            duration: 1000
+                        });
+                    }
+                }).catch(response => {
+                    uni.hideLoading();
+                });
+            },
+            toDetail(item) {
+                uni.navigateTo({
+                    url: '/plugins/exchange/detail/detail?code=' + item.code + '&exchange=1'
+                })
+            },
+            toGift() {
+                uni.navigateTo({
+                    url: '/plugins/exchange/list/list'
+                })
+            },
+            clerk() {
+                let that = this;
+                if(this.loading || !this.code) {
+                    return false
+                }
+                uni.showLoading({
+                    mask: true,
+                    title: '兑换中...'
+                });
+                this.loading = true;
+                let code = this.code;
+                that.$request({
+                    url: that.$api.exchange.info,
+                    data: {
+                        code: code
+                    }
+                }).then(response=>{
+                    this.loading = false;
+                    uni.hideLoading();
+                    if(response.code == 0) {
+                        this.code = '';
+                        uni.navigateTo({
+                            url: '/plugins/exchange/detail/detail?code=' + code
+                        })
+                    }else {
+                        this.msg = response.msg;
+                        this.other = '';
+                        if(response.msg == '该兑换码未到使用时间!') {
+                            this.other = response.data.valid_start_time + '-' + response.data.valid_end_time + ' 可用'
+                        }
+                        this.dialog = true;
+                    }
+                }).catch(response => {
+                    uni.hideLoading();
+                });
+            }
+        }
+    }
+</script>
+
+<style scoped lang="scss">
+    .dialog-bg {
+        position: fixed;
+        top: 0;
+        left: 0;
+        width: 100%;
+        height: 100%;
+        background-color: rgba(0,0,0,.3);
+        z-index: 101;
+    }
+    .jump-dialog {
+        position: fixed;
+        bottom: 120rpx;
+        right: 24rpx;
+        width: 100rpx;
+        height: 100rpx;
+        border-radius: 50%;
+        background-color: rgba(0,0,0,.3);
+        font-size: 16rpx;
+        color: #fff;
+        z-index: 100;
+        &.tabbarbool {
+            bottom: 240rpx;
+        }
+        image {
+            width: 54rpx;
+            height: 54rpx;
+            margin-bottom: 3rpx;
+            display: block;
+        }
+    }
+    .use-info {
+        position: fixed;
+        bottom: 64rpx;
+        text-align: center;
+        font-size: 28rpx;
+        width: 200rpx;
+        margin: 0 auto;
+        left: 0;
+        right: 0;
+        &.tabbarbool {
+            bottom: 204rpx;
+        }
+    }
+    .scan {
+        position: absolute;
+        top: 0;
+        left: 0;
+        width: 100%;
+        height: 100%;
+        background-color: #fff;
+        text-align: center;
+        padding-top: 184rpx;
+        font-size: 28rpx;
+        color: #353535;
+        .scan-input {
+            height: 94rpx;
+            width: 580rpx;
+            margin: 40rpx auto;
+            background-color: #f9f9f9;
+            border: 2rpx solid #e2e2e2;
+                border-radius: 16rpx;
+            position: relative;
+            box-shadow: 1rpx 1rpx 4rpx 4rpx #f5f5f5;
+            input {
+                border-radius: 16rpx;
+                width: 100%;
+                height: 100%;
+                padding: 10rpx 80rpx 10rpx 20rpx;
+                text-align: left;
+            }
+            image {
+                width: 48rpx;
+                height: 44rpx;
+                position: absolute;
+                right: 24rpx;
+                top: 23rpx;
+                z-index: 2
+            }
+        }
+        .scan-button {
+            height: 300rpx;
+            width: 300rpx;
+            border-radius: 50%;
+            text-align: center;
+            line-height: 300rpx;
+            box-shadow: 2rpx 2rpx 8rpx 8rpx #f3f3f3;
+            margin: 112rpx auto;
+            font-size: 42rpx;
+            font-weight: 600;
+            color: #fff;
+        }
+    }
+    .item {
+        margin: 24rpx 24rpx 0;
+        background-color: #fff;
+        border-radius: 16rpx;
+        .status {
+            padding: 28rpx 30rpx;
+            border-bottom: 2rpx solid #e2e2e2;
+
+            .item-code {
+                padding: 16rpx 30rpx;
+                border-radius: 40rpx;
+                font-size: 28rpx;
+                font-weight: 600;
+            }
+            .item-status {
+                font-size: 28rpx;
+                view:first-of-type {
+                    margin-right: 16rpx;
+                }
+                image {
+                    height: 22rpx;
+                    width: 14rpx;
+                    display: block;
+                }
+            }
+        }
+        .item-time {
+            height: 72rpx;
+            line-height: 72rpx;
+            font-size: 28rpx;
+            color: #666666;
+            padding: 0 30rpx;
+        }
+    }
+    .dialog {
+        margin: 270rpx auto;
+        background-color: #fff;
+        border-radius: 16rpx;
+        width: 600rpx;
+        padding: 60rpx 0;
+        text-align: center;
+        .dialog-img {
+            width: 200rpx;
+            height: 200rpx;
+            margin: 0 auto 20rpx;
+        }
+        .dialog-msg {
+            font-size: 32rpx;
+            color: #353535;
+        }
+        .dialog-other {
+            font-size: 24rpx;
+            color: #999999;
+        }
+        .dialog-button {
+            font-size: 26rpx;
+            width: 520rpx;
+            height: 90rpx;
+            border-radius: 45rpx;
+            line-height: 90rpx;
+            text-align: center;
+            color: #fff;
+            margin: 50rpx auto 0;
+        }
+    }
+    .u-rules {
+        border-top-left-radius: 16rpx;
+        border-top-right-radius: 16rpx;
+        width: 100%;
+        position: fixed;
+        z-index: 1005;
+        left: 0;
+        background-color: #fff;
+        &.iphone_x.tabbarbool {
+            padding-bottom: 50rpx;
+        }
+        .u-rules-top {
+            border-top-left-radius: 16rpx;
+            border-top-right-radius: 16rpx;
+            background-color: #fff;
+            height: 80rpx;
+            .end-close {
+                width: 80rpx;
+                height: 80rpx;
+                padding: 25rpx;
+                image {
+                    width: 30rpx;
+                    height: 30rpx;
+                }
+            }
+        }
+        .u-rules-content {
+            padding: 0 20rpx;
+            min-height: 160rpx;
+            max-height: 918rpx;
+            overflow: auto;
+        }
+    }
+</style>

+ 344 - 0
src/plugins/exchange/list/list.vue

xqd
@@ -0,0 +1,344 @@
+<template>
+    <app-layout>
+        <app-tab-nav :setTop="0" :border="false" :shadow="false" :height="100" :tabList="tabList" :padding="0" :activeItem="activeTab" @click="tabStatus" :theme="getTheme"></app-tab-nav>
+        <view v-if="activeTab == '0'" class="goods dir-left-wrap">
+            <view style="width: 100%" v-if="list.length > 0">
+                <app-product-list sign="exchange" :theme="getTheme" @routeGo="jump" :listStyle="listStyle" :goods_list="list"></app-product-list>
+            </view>
+            <view style="padding-top: 30%;width: 100%;" v-if="list.length == 0">
+                <app-no-goods title="暂无可购买的礼品卡" background="#f7f7f7"></app-no-goods>
+            </view>
+        </view>
+        <view v-if="activeTab == '1'">
+            <view class="item" v-for="(item,index) in list" :key="index">
+                <view class="dir-left-nowrap cross-center status">
+                    <view class="item-cover">
+                        <app-image :img-src="item.cover_pic" width="140rpx" height="140rpx"
+                                   :border-radius="`8rpx 8rpx 0 0`"></app-image>
+                    </view>
+                    <view class="t-omit-two item-name">{{item.name}}</view>
+                </view>
+                <view class="item-time main-between cross-center">
+                    <view>购买时间:{{item.created_at}}</view>
+                    <view v-if="item.status == 'unused'" @click="apply(item)" :style="{'background-color': getTheme.background}" class="rewards-submit">立即使用</view>
+                    <view v-else-if="item.status == 'used'" @click="apply(item)" class="rewards-submit over">已使用</view>
+                    <view @click="apply(item)" v-else class="rewards-submit over">已失效</view>
+                </view>
+            </view>
+            <view style="padding-top: 30%" v-if="list.length == 0">
+                <app-no-goods title="暂无已获得的礼品卡" background="#f7f7f7"></app-no-goods>
+            </view>
+        </view>
+        <view @click="toIndex" v-if="setting.is_to_exchange == 1" class="jump-dialog cross-center dir-top-nowrap main-center" :class="[`${tabbarbool? 'tabbarbool':''}`]">
+            <image :src="setting.to_exchange_pic"></image>
+            <view>兑换中心</view>
+        </view>
+    </app-layout>
+</template>
+
+<script>
+    import appTabNav from "../../../components/basic-component/app-tab-nav/app-tab-nav.vue";
+    import appProductList from '../../../components/page-component/app-product-list/app-product-list.vue';
+    import appPrice from '../../../components/page-component/goods/app-price.vue';
+    import appNoGoods from '../../../components/page-component/app-no-goods/app-no-goods.vue';
+    import uMask from '../../../components/basic-component/u-mask/u-mask.vue';
+    import { mapState, mapGetters } from "vuex";
+
+    export default {
+        name: "index",
+        data() {
+            return {
+                currentRoute: this.$platDiff.route(),
+                tabbarbool: false,
+                tabList: [
+                    {id:0, name: '购买礼品卡'},
+                    {id:1, name: '我的礼品卡'}
+                ],
+                code: '',
+                activeTab: '0',
+                list: [],
+                setting: {},
+                listStyle: false,
+                loading: false,
+                more: false,
+                dialog: false,
+                msg: '',
+                page: 1,
+            };
+        },
+        computed: {
+            ...mapState({
+                appImg: state => state.mallConfig.__wxapp_img.mall,
+                appSetting: state => state.mallConfig.mall.setting,
+                tabBarNavs: state => state.mallConfig.navbar.navs,
+                platform: function(state) {
+                    return state.gConfig.systemInfo.platform;
+                }
+            }),
+            ...mapGetters('mallConfig', {
+                getTheme: 'getTheme'
+            }),
+            ...mapGetters('mallConfig', {
+                getVideo: 'getVideo'
+            })
+        },
+        components: {
+            "app-tab-nav": appTabNav,
+            'app-product-list': appProductList,
+            appPrice,
+            appNoGoods,
+            "u-mask": uMask
+        },
+        watch: {
+            tabBarNavs: {
+                handler: function() {
+                    this.b();
+                },
+                immediate: true,
+            }
+        },
+        // #ifdef MP
+        onShareAppMessage() {
+            return this.$shareAppMessage({
+                title: this.$children[0].navigationBarTitle,
+                path: "/plugins/exchange/list/list",
+            });
+        },
+        // #endif
+        // #ifdef MP-WEIXIN
+        onShareTimeline() {
+          // 分享朋友圈beta
+          return this.$shareTimeline({
+            title: this.$children[0].navigationBarTitle,
+            query: {} // 此处填写页面的参数
+          });
+        },
+        // #endif
+        onLoad(options) { this.$commonLoad.onload(options);
+            // #ifdef MP-WEIXIN
+            wx.showShareMenu({
+              menus: ['shareAppMessage', 'shareTimeline']
+            })
+            // #endif
+            if(options.tab > 0) {
+                this.activeTab = options.tab.toString();
+            }
+            this.$showLoading({
+                type: 'global',
+                text: '加载中...'
+            });
+            this.$request({
+                url: this.$api.exchange.setting,
+            }).then(response=>{
+                if(response.code == 0) {
+                    this.setting = response.data;
+                    this.getList();
+                }else {
+                    uni.showToast({
+                        title: response.msg,
+                        icon: 'none',
+                        duration: 1000
+                    });
+                }
+            })
+        },
+        onShow() {
+            if(this.activeTab == '1') {
+                this.getList();
+            }
+        },
+        onReachBottom() {
+            if(this.more) {
+                this.page++;
+                this.getMore();
+            }
+        },
+        methods: {
+            b() {
+                // #ifndef H5
+                let currentRoute = this.currentRoute;
+                for (let i = 0; i < this.tabBarNavs.length; i++) {
+                    if(currentRoute.includes(this.tabBarNavs[i].url.split('?')[0])) {
+                        return this.tabbarbool = true;
+                    }
+                }
+                // #endif
+                return  this.tabbarbool = false;
+            },
+            toIndex() {
+                uni.navigateTo({
+                    url: '/plugins/exchange/index/index'
+                })
+            },
+            getMore() {
+                let that = this;
+                if(this.loading) {
+                    return false
+                }
+                this.loading = true;
+                this.more = false;
+                that.$request({
+                    url: that.activeTab == '0' ? that.$api.exchange.list : that.$api.exchange.me_list,
+                    data: {
+                        page: this.page
+                    }
+                }).then(response=>{
+                    that.$hideLoading();
+                    uni.hideLoading();
+                    this.loading = false;
+                    if(response.code == 0) {
+                        that.list = that.list.concat(response.data.list);
+                        if(response.data.list.length == response.data.pagination.pageSize) {
+                            this.more = true;
+                        }
+                    }else {
+                        uni.showToast({
+                            title: response.msg,
+                            icon: 'none',
+                            duration: 1000
+                        });
+                    }
+                }).catch(response => {
+                    that.$hideLoading();
+                    uni.hideLoading();
+                });
+            },
+            jump(data) {
+                // #ifndef MP-BAIDU
+                if (data.video_url && this.getVideo == 1) {
+                    // #ifdef MP
+                    uni.navigateTo({
+                        url: `/pages/goods/video?goods_id=${data.id}&sign=exchange`
+                    });
+                    // #endif
+                    // #ifdef H5
+                    uni.navigateTo({
+                        url: `/plugins/exchange/goods/goods?goods_id=${data.id}`
+                    });
+                    // #endif
+                } else {
+                    uni.navigateTo({
+                        url: `/plugins/exchange/goods/goods?goods_id=${data.id}`
+                    });
+                }
+                // #endif
+
+                // #ifdef MP-BAIDU
+                uni.navigateTo({
+                    url: `/plugins/exchange/goods/goods?goods_id=${data.id}`
+                });
+                // #endif
+            },
+            apply(goods) {
+                uni.navigateTo({
+                    url: '/plugins/exchange/gift/gift?code=' + goods.code
+                })
+            },
+            tabStatus(e) {
+                if(this.loading) {
+                    return false
+                }
+                this.list = [];
+                this.page = 1;
+                this.activeTab = e.currentTarget.dataset.id;
+                uni.showLoading({
+                    mask: true,
+                    title: '加载中...'
+                });
+                this.getList();
+            },
+            getList() {
+                let that = this;
+                if(this.loading) {
+                    return false
+                }
+                this.loading = true;
+                this.page = 1;
+                this.more = false;
+                that.$request({
+                    url: that.activeTab == '0' ? that.$api.exchange.list : that.$api.exchange.me_list
+                }).then(response=>{
+                    that.$hideLoading();
+                    uni.hideLoading();
+                    this.loading = false;
+                    if(response.code == 0) {
+                        that.list = response.data.list;
+                        if(that.list.length == response.data.pagination.pageSize) {
+                            this.more = true;
+                        }
+                    }else {
+                        uni.showToast({
+                            title: response.msg,
+                            icon: 'none',
+                            duration: 1000
+                        });
+                    }
+                }).catch(response => {
+                    that.$hideLoading();
+                    uni.hideLoading();
+                });
+            },
+        }
+    }
+</script>
+
+<style scoped lang="scss">
+    .jump-dialog {
+        position: fixed;
+        bottom: 120rpx;
+        right: 24rpx;
+        width: 100rpx;
+        height: 100rpx;
+        border-radius: 50%;
+        background-color: rgba(0,0,0,.3);
+        font-size: 16rpx;
+        color: #fff;
+        z-index: 100;
+        &.tabbarbool {
+            bottom: 240rpx;
+        }
+        image {
+            width: 54rpx;
+            height: 54rpx;
+            margin-bottom: 3rpx;
+            display: block;
+        }
+    }
+    .item {
+        margin: 24rpx 24rpx 0;
+        background-color: #fff;
+        border-radius: 16rpx;
+        .status {
+            padding: 28rpx 30rpx;
+            border-bottom: 2rpx solid #e2e2e2;
+            .item-cover {
+                width: 140rpx;
+                flex-shrink: 0;
+                margin-right: 30rpx;
+            }
+            .item-name {
+                font-size: 28rpx;
+                color: #353535;
+            }
+        }
+        .item-time {
+            height: 112rpx;
+            font-size: 28rpx;
+            color: #666666;
+            padding: 0 30rpx;
+            .rewards-submit {
+                height: 68rpx;
+                line-height: 68rpx;
+                text-align: center;
+                padding: 0 30rpx;
+                border-radius: 40rpx;
+                color: #fff;
+                font-size: #{28rpx};
+                &.over {
+                    background-color: #f7f7f7;
+                    color: #999999;
+                }
+            }
+        }
+    }
+</style>