mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-uniapp.git
synced 2026-11-08 01:48:55 +08:00
feat(paid-member): 添加付费会员功能模块
- 新增付费会员API接口层,支持会员查询、下单、记录及报价 - 新增付费会员页面,展示权益、推荐商品及购买流程 - 新增付费会员购买记录页面,支持订单状态查看与继续支付 - 新增 PaidMemberPrice 组件用于商品列表和详情页展示会员价 - 个人中心页添加付费会员入口,支持配置化展示标题与背景 - 商品详情页集成会员价展示,支持秒杀和拼团场景下隐藏 - 商品列表组件集成会员价展示,支持批量请求与防竞态 - 支付页适配付费会员支付流程,支持H5轮询与结果回调 - 订单确认页优惠文案更新为"活动优惠(含会员优惠)" - pages.json 新增付费会员及购买记录页面路由配置 - README 更新升级计划,按时间倒序补充已完成功能明细
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
}}
|
||||
</div>
|
||||
</view>
|
||||
<PaidMemberPrice :quote="paidQuotes[item.id]" />
|
||||
<div class="promotion" @click="navigateToDetailPage(item)">
|
||||
<div v-for="(promotionItem,promotionIndex) in getPromotion(item)" :key="promotionIndex">
|
||||
<span class="promotion-tag" v-if="promotionItem.indexOf('COUPON') != -1">劵</span>
|
||||
@@ -80,6 +81,7 @@
|
||||
<u-icon name="shopping-cart" size="16" :color="mainColor"></u-icon>
|
||||
</div>
|
||||
</view>
|
||||
<PaidMemberPrice v-if="flag('price')" :quote="paidQuotes[item.id]" />
|
||||
<div class="store-seller-name" v-if="storeName" @click="navigateToStoreDetailPage(item)">
|
||||
<view class="store-name-row">
|
||||
<text class="self-tag" v-if="item.selfOperated && flag('selfTag')">自营</text>
|
||||
@@ -96,7 +98,11 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, watch } from 'vue'
|
||||
import { computed, watch, ref } from 'vue'
|
||||
import { onShow } from '@dcloudio/uni-app'
|
||||
import PaidMemberPrice from '@/components/paid-member-price/index.vue'
|
||||
import { getPaidMemberQuotes } from '@/api/paid-member'
|
||||
import { isLogin } from '@/utils/filters'
|
||||
import { useStore } from '@/store'
|
||||
import { useGoodsListCommon } from './common'
|
||||
import { goodsFormatPrice } from '@/utils/filters.js'
|
||||
@@ -123,6 +129,21 @@ const props = withDefaults(defineProps<{
|
||||
})
|
||||
|
||||
const emit = defineEmits(['addCart'])
|
||||
const paidQuotes = ref<Record<string, any>>({})
|
||||
let paidRequest = 0
|
||||
async function loadPaidQuotes() {
|
||||
const request = ++paidRequest, memberId = String(isLogin()?.id || '')
|
||||
paidQuotes.value = {}
|
||||
if (!memberId) return
|
||||
const ids = [...new Set((props.res || []).map(item => String(item.id || '')).filter(Boolean))]
|
||||
try {
|
||||
const results = await Promise.all(Array.from({length:Math.ceil(ids.length/100)},(_,i)=>getPaidMemberQuotes(ids.slice(i*100,i*100+100))))
|
||||
if (request !== paidRequest || String(isLogin()?.id || '') !== memberId) return
|
||||
paidQuotes.value = Object.assign({}, ...results.filter(res=>res.data?.success).map(res=>res.data.result || {}))
|
||||
} catch {}
|
||||
}
|
||||
watch(() => [(props.res || []).map(item=>item.id).join(','), store.state.userInfo?.id, store.state.hasLogin], loadPaidQuotes, {immediate:true})
|
||||
onShow(loadPaidQuotes)
|
||||
|
||||
// 存量字段(促销/销量/自营/价格):showFields 为 null 时维持现状渲染
|
||||
const flag = (key: string) => props.showFields == null || props.showFields[key] !== false
|
||||
|
||||
6
components/paid-member-price/index.vue
Normal file
6
components/paid-member-price/index.vue
Normal file
@@ -0,0 +1,6 @@
|
||||
<template><view v-if="quote" class="paid-price" @click.stop="open"><image v-if="quote.label" :src="quote.label" mode="aspectFit" /><text>会员价 ¥{{ Number(quote.price).toFixed(2) }}</text><text v-if="!quote.eligible" class="open">开通享 ›</text></view></template>
|
||||
<script setup>
|
||||
defineProps({quote:{type:Object,default:null}})
|
||||
function open(){uni.navigateTo({url:'/pages/mine/paidMember'})}
|
||||
</script>
|
||||
<style scoped>.paid-price{display:flex;align-items:center;flex-wrap:wrap;gap:6rpx;margin-top:8rpx;color:#a77c3e;font-size:22rpx;line-height:1.6}.paid-price image{width:28rpx;height:28rpx}.open{font-size:20rpx;opacity:.8}</style>
|
||||
Reference in New Issue
Block a user