任务6-4操作步骤:礼品卡功能

作者: 吴国友 | 来源:发表于2025-02-08 10:31 被阅读0次

任务六 工单4

效果图


6.4.1 礼品卡列表效果图.png

1、“礼品卡列表”界面为顾客提供了多种活动相关的优惠卡片。这些卡片基于当前的活动及节气而设计,并提供相应的折扣优惠。用户可在该界面浏览并选择需要使用的卡片进行购买。通过如图6.4.2所示的功能入口,用户能够轻松进入该界面,开始他们的卡片消费体验。


6.4.2 礼品卡界面交互处.png

       在 pages 文件夹中创建并部署 giftcard.vue 按钮位于功能列表的左侧侧边栏中。遵循项目统一的样式规范,在 pages.json 文件中完成相关配置设置。设置完成后,跳转至 主界面中的 giftCards 按钮下方,用户即可通过 @tap="giftCards" 交互进入该页面。
       mine.vue 值得注意的是,此页面已启用 disableScroll 属性,具体效果为:disableScroll 设置为 true 时,页面将彻底禁止任何上下方向的滚动操作,这一设置仅在页面配置中有效。

    {
        "path" : "pages/giftcard/giftcard",
        "style" : {
            "navigationBarTitleText": "礼品卡列表",
            "navigationBarTextStyle": "black",
            "navigationBarBackgroundColor": "#ffffff",
            "disableScroll": true
        }
    }

2、“礼品卡列表”界面内部较为复杂,可分为“购买礼品卡”功能、“我的礼品卡”功能两个板块进行研发,每个块功能通过swiper、swiper-item进行展示。购买礼品卡为第一个swiper-item,其中包含scroll-view、image、v-for循环列表。
       “礼品卡列表”界面的设计较为复杂,主要包含两个核心功能板块:一是“购买礼品卡”功能,二是“我的礼品卡”管理功能。其中,“购买礼品卡”模块采用swiper组件作为交互式展示框架,具体包括滚动视图(scroll-view)、图片展示(image)和基于v-for循环的数据展示(v-for)。第一个swiper-item中包含滚动视图、图片展示以及基于v-for循环的数据展示。效果如图6.4.3。


6.4.3 礼品卡功能.png

       通过@tap="switchTab(0)"的方式,用户点击卡片即可切换子页面,默认情况下参数为0对应“购买礼品卡”子页面,参数为1则切换至“我的礼品卡”子页面。充分利用组件库和动态class类管理功能,确保界面交互流畅且操作便捷,并通过合理的布局优化和性能调优提升了整体用户体验。

    <view class="tabbar">
        <view class="item" :class="{'active': !currentTab}" @tap="switchTab(0)">购买礼品卡</view>
        <view class="item" :class="{'active': currentTab}" @tap="switchTab(1)">我的礼品卡</view>
    </view>

       “礼品卡列表”选项卡的设计通过调用onShow生命周期阶段(onShow),在该阶段的初始阶段(construct)会启动数据获取流程。具体而言,在选项卡的显示生命周期阶段(onShow)开始时,将执行await this.$api('giftCards')的方法,以获取卡片数据集合(giftCards.category_list)。
       通过v-for循环遍历该数据集,每个卡片信息将被分解展示:卡片名称作为主标题,卡片图片和相关礼品卡活动信息作为副标题。具体来说,图片组件将根据theme.imageUrls展示卡片图片,同时配合theme.activityName字段显示相关信息。这一设计实现了卡片数据的高效获取与动态呈现,最终呈现出的效果如图6.4.4所示。


6.4.4 礼品卡列表效果.png
    <scroll-view scroll-y="true" class="h-100" style="padding-bottom: 80rpx;">
        <image :src="giftCards.img" class="w-100" mode="widthFix"/>
        <view class="pl-20 pr-20 mb-30">
            <view class="category-list mt-40" v-for="(category, index) in giftCards.category_list" :key="index">
                <view class="font-size-lg font-weight-bold">{{ category.name }}</view>
                <view class="themes-list">
                    <view class="theme" v-for="(theme, key) in category.themesList" :key="key">
                        <image :src="theme.imageUrls" class="w-100" mode="widthFix"/>
                        <view class="activity-name">{{ theme.activityName }}</view>
                    </view>
                </view>
            </view>
        </view>
    </scroll-view>

       按照设计图构建“购买礼品卡”子页面的布局方案,并结合UniApp平台的技术特性,实现卡片数据的动态获取与展示功能。
3、在“我的礼品卡”子页面中,嵌套了一个swiper组件,用于实现可使用和不可使用的卡片信息切换。该嵌套组件支持左右滑动操作,并通过@change事件监听功能,根据滑动后的结果动态切换至对应的子页面。
       当用户对嵌套swiper进行滑动操作时,会触发一个名为switchGiftCardType的事件处理函数,该函数将决定显示的是可使用的卡片还是不可使用的卡片信息(效果如图6.4.5所示)。


6.4.5 内嵌swiper.png
    switchGiftCardType(index) {
        if(this.giftCardType == index) return
        this.giftCardType = index
    }

       此外,考虑到可能需要展示多个子页面的情况(如n个子页面),在每个子页面之间嵌套一个swiper-item,从而实现多维度的信息呈现和切换效果(效果如图6.4.6所示)。


6.4.6 swiper-item内布局效果.png
    <swiper-item>
        <template v-if="!myCards.length">
            <view class="d-flex flex-column align-items-center">
                <image src="https://s3.uuu.ovh/imgs/2025/02/08/36ca6ba99601c912.png" style="width: 300rpx;margin-top: 100rpx;" mode="widthFix"/>
                <view class="font-size-sm text-color-assist">您暂时还没有礼品卡哦~</view>
            </view>
        </template>
    </swiper-item>

       按照设计图完成“我的礼品卡”子页面的布局及功能。
4、至此,本工单的相关功能开发工作结束。团队成员应运用SourceTree工具执行版本控制的提交操作,以便为本次工单的开发代码建立历史版本的记录。

giftcard.vue完整代码

<template>
    <!-- 礼品卡列表 -->
    <view class="container">
        <view class="tabbar">
            <view class="item" :class="{'active': !currentTab}" @tap="switchTab(0)">购买礼品卡</view>
            <view class="item" :class="{'active': currentTab}" @tap="switchTab(1)">我的礼品卡</view>
        </view>
        <swiper :duration="400" :disable-touch="true" class="swiper" :current="currentTab">
            <!-- 购买礼品卡 begin -->
            <swiper-item class="swiper-item-1" @touchmove.stop="handleSwiperItemChange">
                <scroll-view scroll-y="true" class="h-100" style="padding-bottom: 80rpx;">
                    <image :src="giftCards.img" class="w-100" mode="widthFix"/>
                    <view class="pl-20 pr-20 mb-30">
                        <view class="category-list mt-40" v-for="(category, index) in giftCards.category_list" :key="index">
                            <view class="font-size-lg font-weight-bold">{{ category.name }}</view>
                            <view class="themes-list">
                                <view class="theme" v-for="(theme, key) in category.themesList" :key="key">
                                    <image :src="theme.imageUrls" class="w-100" mode="widthFix"/>
                                    <view class="activity-name">{{ theme.activityName }}</view>
                                </view>
                            </view>
                        </view>
                    </view>
                </scroll-view>
                <view class="footer">
                    <view>购买须知</view>
                    <view class="divider"></view>
                    <view>礼品卡章程</view>
                </view>
            </swiper-item>
            <!-- 购买礼品卡 end -->
            <!-- 我的礼品卡 begin -->
            <swiper-item class="swiper-item-2" @touchmove.stop="handleSwiperItemChange">
                <view class="header">
                    <view class="gift-card-types">
                        <view class="item" :class="{'active': !giftCardType}" @tap="switchGiftCardType(0)">可使用(0)</view>
                        <view class="item" :class="{'active': giftCardType}" @tap="switchGiftCardType(1)">不可使用(0)</view>
                    </view>
                    <view class="d-flex align-items-center text-color-primary">兑换礼品卡</view>
                </view>
                <swiper :duration="400" class="flex-fill" :current="giftCardType" @change="e => switchGiftCardType(e.detail.current)">
                    <swiper-item>
                        <template v-if="!myCards.length">
                            <view class="d-flex flex-column align-items-center">
                                <image src="https://s3.uuu.ovh/imgs/2025/02/08/36ca6ba99601c912.png" style="width: 300rpx;margin-top: 100rpx;" mode="widthFix"/>
                                <view class="font-size-sm text-color-assist">您暂时还没有礼品卡哦~</view>
                            </view>
                        </template>
                    </swiper-item>
                    <swiper-item>
                        <template v-if="!myCards.length">
                            <view class="d-flex flex-column align-items-center">
                                <image src="https://s3.uuu.ovh/imgs/2025/02/08/36ca6ba99601c912.png" style="width: 300rpx;margin-top: 100rpx;" mode="widthFix"/>
                                <view class="font-size-sm text-color-assist">您暂时还没有礼品卡哦~</view>
                            </view>
                        </template>
                    </swiper-item>
                </swiper>
                <view class="footer">
                    <button type="primary" plain>获取记录</button>
                    <button type="primary">赠送记录</button>
                </view>
            </swiper-item>
            <!-- 我的礼品卡 end -->
        </swiper>
    </view>
</template>

<script>
    export default {
        data() {
            return {
                giftCards: {},
                currentTab: 0,
                giftCardType: 0,
                myCards: []
            }
        },
        async onShow() {
            this.giftCards = await this.$api('giftCards')
        },
        methods: {
            switchTab(index) {
                if(this.currentTab == index) return
                this.currentTab = index
            },
            switchGiftCardType(index) {
                if(this.giftCardType == index) return
                this.giftCardType = index
            },
            handleSwiperItemChange() {
                return true
            }
        }
    }
</script>

<style lang="scss" scoped>
    .container {
        display: flex;
        flex-direction: column;
    }
    
    .tabbar {
        width: 100%;
        height: 100rpx;
        border-top: 1rpx solid $border-color;
        background-color: $text-color-white;
        display: flex;
        align-items: stretch;
        font-size: $font-size-lg;
        
        .item {
            flex: 1;
            display: flex;
            align-items: center;
            justify-content: center;
            position: relative;
            
            &.active {
                color: $color-primary;
                &:after {
                    content: '';
                    position: absolute;
                    width: 40rpx;
                    height: 10rpx;
                    background-color: $color-primary;
                    border-radius: 50rem !important;
                    bottom: 0;
                    left: calc((100% - 40rpx) / 2);
                }
            }
        }
    }
    
    .swiper {
        flex: 1;
    }

    .swiper-item-1 {
        height: 100%;
        
        .themes-list {
            display: flex;
            flex-wrap: wrap;
            justify-content: space-between;
            
            .theme {
                width: 340rpx;
                margin-top: 30rpx;
                border-radius: 24rpx;
                background-color: $text-color-white;
                display: flex;
                flex-direction: column;
                box-shadow: $box-shadow;
                
                image {
                    border-radius: 24rpx 24rpx 0 0;
                    max-height: 300rpx;
                }
            }
            
            .activity-name {
                font-size: $font-size-base;
                padding: 20rpx 0;
                text-align: center;
            }
        }
        
        .footer {
            z-index: 10;
            background-color: $bg-color;
            position: fixed;
            bottom: 0;
            width: 100%;
            height: 80rpx;
            display: flex;
            justify-content: center;
            align-items: center;
            font-size: $font-size-sm;
            color: $color-primary;
            
            .divider {
                height: 0.6rem;
                width: 4rpx;
                background-color: $color-primary;
                margin: 0 20rpx;
            }
        }
    }
    
    .swiper-item-2 {
        height: 100%;
        display: flex;
        flex-direction: column;
        
        .header {
            height: 110rpx;
            display: flex;
            justify-content: space-between;
            align-items: stretch;
            padding: 30rpx;
            font-size: $font-size-sm;
            
            .gift-card-types {
                display: flex;
                align-items: stretch;
                
                .item {
                    display: flex;
                    justify-content: center;
                    align-items: center;
                    padding: 0 20rpx;
                    
                    &.active {
                        background-color: #FFFFFF;
                        box-shadow: $box-shadow;
                        border-radius: 50rem !important;
                        color: $color-primary;
                    }
                }
            }
        }
        
        .footer {
            z-index: 10;
            background-color: $text-color-white;
            position: fixed;
            bottom: 0;
            width: 100%;
            height: 100rpx;
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 10rpx 40rpx;
            box-shadow: 0 -10rpx 10rpx rgba($color: #eee, $alpha: 0.1);
            
            button {
                width: 310rpx;
                height: 100%;
                line-height: 80rpx;
                border-radius: 50rem !important;
                font-size: $font-size-lg;
            }
        }
    }
</style>

mine.vue 部分跳转代码

          ...
          ...
          ...
                <view class="w-100 d-flex align-items-center just-content-center">
                    <!-- 通过三目运算符判断 -->
                    <view class="user-grid" @tap="coupons">
                        <view class="value font-size-extra-lg font-weight-bold text-color-base">
                            {{ isLogin ? member.couponNum : '***' }}
                        </view>
                        <view class="font-size-sm text-color-assist">云鲤券</view>
                    </view>
                    <view class="user-grid" @tap="integrals">
                        <view class="value font-size-extra-lg font-weight-bold text-color-base">
                            {{ isLogin ? member.pointNum : '***' }}
                        </view>
                        <view class="font-size-sm text-color-assist">积分商城</view>
                    </view>
          ...
          ...
          ...
<script>
    import {
        mapState,
        mapGetters
    } from 'vuex'
    export default {
        data() {
            return {
                // isLogin: false,//false为未登录,true为登录
                newIcon: 'https://s3.uuu.ovh/imgs/2024/12/05/6b3856fe6d711a0a.png'
            }
        },
        computed: {
            ...mapState(['member']),
            ...mapGetters(['isLogin']),
            growthValue() { //计算成长属性
                if (!this.isLogin) return 0
                const {
                    currentValue,
                    needValue
                } = this.member
                return currentValue / (currentValue + needValue) * 100
            }
        },
        methods: {
            login() { //登录
                uni.navigateTo({
                    url: '/pages/login/login'
                })
            },
            ...
            ...
            ...
            services() {//更多服务
                uni.navigateTo({
                    url: '/pages/services/services'
                })
            },
            coupons() {//我的卡券
                if(!this.isLogin) {
                    this.login()
                    return
                }
                uni.navigateTo({
                    url: '/pages/coupons/coupons'
                })
            },
            balance() { //进入会员充值界面
                if (!this.isLogin) {
                    this.login()
                    return
                }
                uni.navigateTo({
                    url: '/pages/balance/balance'
                })
            },
            giftCards() { //礼品卡
                if (!this.isLogin) {
                    this.login()
                    return
                }
                uni.navigateTo({
                    url: '/pages/giftcard/giftcard'
                })
            }
        }
    }
</script>

相关文章

  • 小红圈礼品卡|轻松购买,赠予好友学习知识的入场券!

    礼品卡是小红圈 App 内的产品服务与购买功能,圈主可通过开启礼品卡,实现圈子的多层次拉新,拓展用户获取渠道。同时...

  • 进群宝产品操作手册

    快速新建裂变任务 操作流程图: 具体操作步骤: 一、新建任务 1、点击任务列表—新建任务,进入任务创建界面。 (任...

  • 年卡操作步骤

  • 礼品库插件使用手册

    简介: 界面功能: 1、兑换订单管理 2、礼品管理 3、提醒设置 机器人操作指令:

  • 礼品卡

    祝你幸福,和你所爱之人 珍重 附赠初中喜欢的诗经一句, 桃之夭夭,灼灼其华。之子于归, 宜其室家 http://m...

  • 中石油新手手册

    中石油新手手册 一、油卡操作流程图 二、油卡操作步骤 1、怎么获取油卡订单? 2、获取充值数量 一个用户一次最...

  • 《计算机组成与体系结构》——7操作系统支持

    操作系统最重要的功能是进程或任务的调度和存储管理!操作系统最重要的功能是进程或任务的调度和存储管理!操作系统最重要...

  • Python学习笔记(2)采集网页数据

    一、操作步骤 下面用京东网站作为案例,给大家演示如何使用直观标注的功能采集网页数据,操作步骤如下: 二、案例规则+...

  • 招行首刷礼领取方法

    步骤:1下载掌上生活app。2注册。3绑储蓄卡。4激活信用卡。5还款。(不消费也可以立即还款)。6还款六天后拿礼品...

  • 08消费卡管理流程

    消费卡管理流程 业务流程图: 操作步骤: [if !supportLists]Ø[endif]A.一批新卡买进来之...

网友评论

    本文标题:任务6-4操作步骤:礼品卡功能

    本文链接:https://www.haomeiwen.com/subject/hjczujtx.html