From cc71d20aa6512060f19a8514054ac0d7443425e8 Mon Sep 17 00:00:00 2001 From: "pikachu1995@126.com" Date: Thu, 5 Nov 2026 22:37:12 +0800 Subject: [PATCH] =?UTF-8?q?feat(paid-member):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E4=BB=98=E8=B4=B9=E4=BC=9A=E5=91=98=E5=8A=9F=E8=83=BD=E6=A8=A1?= =?UTF-8?q?=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增付费会员API接口层,支持会员查询、下单、记录及报价 - 新增付费会员页面,展示权益、推荐商品及购买流程 - 新增付费会员购买记录页面,支持订单状态查看与继续支付 - 新增 PaidMemberPrice 组件用于商品列表和详情页展示会员价 - 个人中心页添加付费会员入口,支持配置化展示标题与背景 - 商品详情页集成会员价展示,支持秒杀和拼团场景下隐藏 - 商品列表组件集成会员价展示,支持批量请求与防竞态 - 支付页适配付费会员支付流程,支持H5轮询与结果回调 - 订单确认页优惠文案更新为"活动优惠(含会员优惠)" - pages.json 新增付费会员及购买记录页面路由配置 - README 更新升级计划,按时间倒序补充已完成功能明细 --- README.md | 46 +- api/paid-member.js | 7 + components/m-goods-list/list.vue | 23 +- components/paid-member-price/index.vue | 6 + pages.json | 70 +- pages/cart/payment/payOrder.vue | 41 +- pages/mine/paidMember.vue | 79 + pages/mine/paidMemberRecords.vue | 36 + pages/order/fillorder.vue | 2 +- pages/product/goods.vue | 1580 +++++++++-------- .../product/promotion/-promotion-details.vue | 272 +-- pages/tabbar/user/my.vue | 55 +- 12 files changed, 1244 insertions(+), 973 deletions(-) create mode 100644 api/paid-member.js create mode 100644 components/paid-member-price/index.vue create mode 100644 pages/mine/paidMember.vue create mode 100644 pages/mine/paidMemberRecords.vue diff --git a/README.md b/README.md index 152796d..9beac8a 100644 --- a/README.md +++ b/README.md @@ -160,18 +160,44 @@ lilishop-uniapp ## 8. 升级计划 -> 更新日期:2026-11-04,依据各端近期提交及当前代码实现同步。 +> 更新日期:2026-11-05,依据各端提交记录及当前代码实现同步。 ### ✅ 已完成特性 -| 功能模块 | 功能模块 | -| :--- | :--- | -| ✅ 商品定时上下架 | ✅ 商品分组 / 会员分组 | -| ✅ 商品虚拟销量 | ✅ 专用发票(发票上传) | -| ✅ 置顶评论 | ✅ 客户等级体系 | -| ✅ 购物卡 | ✅ 腾讯云-云直播 | -| ✅ 卡密商品 | ✅ 二级分销 | -| ✅ 定时任务管理(数据库配置驱动) | ✅ 预约服务商品 | -| ✅ 主题色管理 | ✅ 立减优惠券 | + +按可核实的实现或完善时间倒序记录;日期表示代码完成或功能更新时间,不代表生产上线时间。 + +| 时间 | 功能模块 | 完成内容 | +| :--- | :--- | :--- | +| 2026-11-05 | ✅ 付费会员 | 单一付费会员、开通与续费、有效期、关联权益、商家与商品折扣、平台补贴及付费记录。 | +| 2026-11-04 | ✅ 客户等级体系 / 客户权益 | 等级配置、权益介绍、经验值任务与明细、权益发放及重试,提供默认等级与权益数据。 | +| 2026-11-04 | ✅ 小程序订单管理 | 增加小程序订单查询入口及微信订单自动上报开关。 | +| 2026-11-04 | ✅ 立减优惠券 | 新增立减券,完善优惠券校验、领取与订单优惠计算。 | +| 2026-11-04 | ✅ 商品定时上下架 | 完善定时上下架计划管理、独立列表及执行校验。 | +| 2026-11-04 | ✅ 微信小程序原生能力 | 接入微信地址导入、头像选择和昵称填写。 | +| 2026-11-02 | ✅ 消息模板 | 支持多渠道模板矩阵维护,统一站内信、短信、微信公众号及小程序订阅消息的场景配置和异步发送。 | +| 2026-10-30 | ✅ PC 页面装修 | 重构楼层组件,支持自适应高度、可视化热区绘制及配置交互优化。 | +| 2026-10-29 | ✅ 定时任务管理 | 重构为数据库配置驱动,支持运营后台维护任务。 | +| 2026-10-29 | ✅ 敏感词管理 | 支持按业务场景配置过滤开关,并优化词库加载。 | +| 2026-10-29 | ✅ PC 店铺搜索 | 新增店铺列表,支持商品与店铺双模式搜索。 | +| 2026-10-22 | ✅ 分类设置 | 支持四种分类页模板选择、商品列表展示字段开关及模板图片预览。 | +| 2026-10-20 | ✅ 移动端页面装修 | 完善可视化编辑器,新增首页组合组件及优惠券、店铺、文章等楼层。 | +| 2026-10-09 | ✅ 主题色管理 | 完善主题设置,支持自定义模式。 | +| 2026-10-02 | ✅ 预约服务商品 | 完善预约商品、预约交易及订单详情功能。 | +| 2026-08-05 | ✅ 二级分销 | 由一级分销扩展为二级分销,增加节点配置及分销员中心。 | +| 2026-08-03 | ✅ 卡密商品 | 完善电子卡券履约、订单状态及卡池管理。 | +| 2026-07-23 | ✅ 素材库管理 | 增加文件分类、目录管理及目录归属校验。 | +| 2026-07-20 | ✅ 经营统计报表 | 新增店铺业绩、商品同比环比、销售订单明细及商品销售汇总报表。 | +| 2026-07-13 | ✅ 腾讯云直播 | 接入并完善直播、聊天与直播商品相关功能。 | +| 2026-06-30 | ✅ 移动端技术升级 | 升级 Vue 3 与 uView Plus,适配组件和页面。 | +| 2026-06-29 | ✅ 电子面单发货 | 完善快递鸟电子面单,支持自动携带运单号发货。 | +| 2026-06-05 | ✅ 后端与管理端框架升级 | 5 月 25 日至 6 月 5 日完成 Spring Boot 4、管理端 Vue 3 与 Element Plus 升级。 | +| 2026-05-22 | ✅ 购物卡 | 新增礼品卡接口,以及选择、绑定、激活和列表管理。 | +| 2026-05-20 | ✅ 微信提现 | 完善转账状态查询、确认回调和重试处理,后续补充提现规则说明配置。 | +| 2026-04-16 | ✅ 置顶评论 | 支持评论置顶及商品评价管理。 | +| 2026-04-13 | ✅ 专用发票(发票上传) | 完善发票信息字段、发票详情及管理展示。 | +| 2026-04-01 | ✅ 商品虚拟销量 | 支持按商品规格设置虚拟销量,提供单个及批量设置入口。 | +| 2026-03-30 | ✅ 商品分组 | 新增商品分组管理及商品关联功能。 | +| 2026-03-24 | ✅ 会员分组 | 新增会员分组管理。 | ### 🔜 近期规划中 - 🔜 微信小店对接 diff --git a/api/paid-member.js b/api/paid-member.js new file mode 100644 index 0000000..6e8f9e0 --- /dev/null +++ b/api/paid-member.js @@ -0,0 +1,7 @@ +import { http, Method } from '@/utils/request.js' +export const getPaidMember = () => http.request({ url: '/member/paid/current', method: Method.GET, needToken: true }) +export const createPaidMemberOrder = data => http.request({ url: '/member/paid/orders', method: Method.POST, data, needToken: true, header: { 'Content-Type': 'application/json' } }) +export const getPaidMemberOrders = params => http.request({ url: '/member/paid/orders', method: Method.GET, params, needToken: true }) +export const getPaidMemberOrder = sn => http.request({ url: `/member/paid/orders/${encodeURIComponent(sn)}`, method: Method.GET, needToken: true }) +export const cancelPaidMemberOrder = sn => http.request({ url: `/member/paid/orders/${encodeURIComponent(sn)}/cancel`, method: Method.POST, needToken: true }) +export const getPaidMemberQuotes = skuIds => http.request({ url: '/member/paid/quotes', method: Method.GET, params: { skuIds: skuIds.join(',') }, needToken: true }) diff --git a/components/m-goods-list/list.vue b/components/m-goods-list/list.vue index b315d0c..befa623 100644 --- a/components/m-goods-list/list.vue +++ b/components/m-goods-list/list.vue @@ -20,6 +20,7 @@ }} +
劵 @@ -80,6 +81,7 @@
+
自营 @@ -96,7 +98,11 @@ + diff --git a/pages.json b/pages.json index 0aa04b6..c7f3197 100644 --- a/pages.json +++ b/pages.json @@ -13,16 +13,16 @@ } }, "pages": [ - + { "path": "pages/tabbar/home/index", "style": { "navigationBarTitleText": "首页", "navigationStyle": "custom", // 隐藏系统导航栏 "navigationBarTextStyle": "black", - "enablePullDownRefresh":true + "enablePullDownRefresh":true } - }, + }, { "path":"pages/tabbar/screen/fullScreen", "style": { @@ -63,13 +63,13 @@ } } }, - + { "path": "pages/navigation/search/searchPage", "style": { "navigationBarTitleText": "搜索", "navigationStyle": "custom", - + "app-plus": { //app页面不显示滚动条 "scrollIndicator": "none", @@ -89,11 +89,11 @@ "navigationStyle": "custom" } }, - + { "path": "pages/tabbar/home/web-view", "style": { - + } }, { @@ -174,8 +174,10 @@ "root": "pages/mine", "pages": [ {"path":"memberBenefits","style":{"navigationBarTitleText":"会员权益","enablePullDownRefresh":true,"navigationBarBackgroundColor":"#f5f6f9","navigationBarTextStyle":"black"}}, + {"path":"paidMember","style":{"navigationBarTitleText":"付费会员","enablePullDownRefresh":true,"navigationBarBackgroundColor":"#f5f6f9","navigationBarTextStyle":"black"}}, + {"path":"paidMemberRecords","style":{"navigationBarTitleText":"会员购买记录","enablePullDownRefresh":true,"navigationBarBackgroundColor":"#f5f6f9","navigationBarTextStyle":"black"}}, {"path":"experience","style":{"navigationBarTitleText":"我的经验","enablePullDownRefresh":true,"navigationBarBackgroundColor":"#f5f6f9","navigationBarTextStyle":"black"}}, - + { "path": "signIn", "style": { @@ -381,7 +383,7 @@ "navigationStyle": "custom" } }, - + { "path": "deposit/info", "style": { @@ -434,8 +436,8 @@ "navigationBarTitleText": "面容登录" } }, - - + + { "path": "set/securityCenter/editPassword", "style": { @@ -445,13 +447,13 @@ } } }, - + { "path": "set/securityCenter/bindMobile", "style": { "navigationBarTitleText": "绑定手机号", "app-plus": { - + } } }, @@ -463,7 +465,7 @@ "enablePullDownRefresh": true, "app-plus": { } - + } }, { @@ -473,7 +475,7 @@ "enablePullDownRefresh": true, "app-plus": { } - + } }, { @@ -621,9 +623,9 @@ // 禁止页面滚动 "scrollIndicator": "none", "safearea": { - "bottom": { - "offset": "none" - } + "bottom": { + "offset": "none" + } } } } @@ -679,14 +681,14 @@ "animationType": "slide-in-bottom", "scrollIndicator": "none", "safearea": { - "bottom": { - "offset": "none" - } + "bottom": { + "offset": "none" + } } } } }, - + { "path": "entry/seller/index", "style": { @@ -742,7 +744,7 @@ } } }, - + // #ifndef MP-WEIXIN { "path": "live/room", @@ -804,7 +806,7 @@ "path": "point/pointList", "style": { "navigationBarTitleText": "积分商城" - + } } @@ -820,7 +822,7 @@ "navigationBarTitleText": "我的优惠券", "app-plus": { "bounce": "coupon/none" - + } } }, @@ -836,13 +838,13 @@ "navigationBarTitleText": "优惠券" } }, - + { "path": "coupon/couponCenter", "style": { "navigationBarTitleText": "领券中心", "enablePullDownRefresh": true - + } }, { @@ -899,7 +901,7 @@ } } } - + ] }, @@ -930,7 +932,7 @@ "enablePullDownRefresh": true, "app-plus": { "bounce": "none" - + } } }, @@ -971,7 +973,7 @@ "navigationBarTitleText": "评价详情" } }, - + { "path": "evaluate/releaseEvaluate", "style": { @@ -984,7 +986,7 @@ "navigationBarTitleText": "我的评价" } }, - + { "path": "afterSales/applyProgress", "style": { @@ -1069,7 +1071,7 @@ "selectedIconPath": "static/tabbar/category-s.png", "text": "分类" }, - + { "pagePath": "pages/tabbar/cart/cartList", "iconPath": "static/tabbar/cart.png", @@ -1084,11 +1086,11 @@ } ] }, - // #todo 为什么要注释condition下代码? + // #todo 为什么要注释condition下代码? // IOS plus.runtime.arguments 添加 condition节点后, 框架会修改 runtime.arguments // 会影响什么功能? // -在h5中唤醒app会一直返回默认值 {"name":"","path":"","query":"","id":0} - "condition": { //模式配置,仅开发期间生效 + "condition": { //模式配置,仅开发期间生效 // "current": 0, //当前激活的模式(list 的索引项) // "list": [{ // "name": "", //模式名称 diff --git a/pages/cart/payment/payOrder.vue b/pages/cart/payment/payOrder.vue index 410e30c..d56c3ca 100644 --- a/pages/cart/payment/payOrder.vue +++ b/pages/cart/payment/payOrder.vue @@ -68,7 +68,7 @@ + diff --git a/pages/mine/paidMemberRecords.vue b/pages/mine/paidMemberRecords.vue new file mode 100644 index 0000000..afc6d41 --- /dev/null +++ b/pages/mine/paidMemberRecords.vue @@ -0,0 +1,36 @@ + + + diff --git a/pages/order/fillorder.vue b/pages/order/fillorder.vue index 7ed2831..a7d98b1 100644 --- a/pages/order/fillorder.vue +++ b/pages/order/fillorder.vue @@ -346,7 +346,7 @@
- 活动优惠 + 活动优惠(含会员优惠) -¥{{unitPrice(orderMessage.priceDetailDTO.discountPrice) diff --git a/pages/product/goods.vue b/pages/product/goods.vue index d38eca3..926aca0 100644 --- a/pages/product/goods.vue +++ b/pages/product/goods.vue @@ -1,782 +1,798 @@ - - - - - + + + + + diff --git a/pages/product/product/promotion/-promotion-details.vue b/pages/product/product/promotion/-promotion-details.vue index 4ec870d..2ed0d34 100644 --- a/pages/product/product/promotion/-promotion-details.vue +++ b/pages/product/product/promotion/-promotion-details.vue @@ -1,136 +1,136 @@ - - - - - + + + + + diff --git a/pages/tabbar/user/my.vue b/pages/tabbar/user/my.vue index c0f1a2e..4617a2c 100644 --- a/pages/tabbar/user/my.vue +++ b/pages/tabbar/user/my.vue @@ -69,6 +69,13 @@ + @@ -132,6 +139,7 @@ import { onNavigationBarButtonTap, } from '@dcloudio/uni-app' import tool from '@/pages/tabbar/user/utils/tool.vue' +import { getPaidMember } from '@/api/paid-member' import { getCouponsNum, getFootprintNum } from '@/api/members.js' import { getUserWallet } from '@/api/members' import configs from '@/config/config' @@ -154,6 +162,22 @@ const aiderLightColor = computed(() => store.getters.aiderLightColor) const userImage = configs.defaultUserPhoto const userInfo = ref({}) +const paidMemberInfo = ref(null) +let paidMemberRequestId = 0 +const showPaidMemberEntry = computed(() => !!paidMemberInfo.value?.config + && !!(paidMemberInfo.value.config.enabled || paidMemberInfo.value.active || paidMemberInfo.value.status === 'EXPIRED')) +const paidEntryTitle = computed(() => paidMemberInfo.value?.active + ? paidMemberInfo.value.config?.openedText || '我的付费会员' + : paidMemberInfo.value?.config?.unopenedText || '开通付费会员,享专属权益') +const paidEntryColor = computed(() => (paidMemberInfo.value?.active + ? paidMemberInfo.value.config?.openedFontColor + : paidMemberInfo.value?.config?.unopenedFontColor) || '#f4dfb9') +const paidEntryBackground = computed(() => paidMemberInfo.value?.active + ? paidMemberInfo.value.config?.openedBackground + : paidMemberInfo.value?.config?.unopenedBackground) +const paidEntrySubtitle = computed(() => paidMemberInfo.value?.active + ? '有效期至 ' + paidMemberInfo.value.endTime + : paidMemberInfo.value?.status === 'EXPIRED' ? '会员已到期,续费继续享权益' : '开通享商品优惠与专属权益') const couponNum = ref('') const footNum = ref('') const walletNum = ref('') @@ -189,6 +213,26 @@ function resetMemberGrade() { gradeIconFailed.value = false } +/** 个人中心显示时读取会员配置及资格;退出或切换账号后丢弃旧请求结果。 */ +async function loadPaidMemberInfo() { + const requestId = ++paidMemberRequestId + const memberId = String(userInfo.value.id || '') + paidMemberInfo.value = null + if (!memberId) return + try { + const res = await getPaidMember() + if (requestId !== paidMemberRequestId + || String(userInfo.value.id || '') !== memberId + || String((isLogin() || {}).id || '') !== memberId) return + if (!res.data?.success) throw new Error(res.data?.message || '会员服务返回异常') + paidMemberInfo.value = res.data.result || null + } catch (error: any) { + if (requestId === paidMemberRequestId) { + console.warn('[付费会员] 入口加载失败', error?.message || '请求失败') + } + } +} + function onGradeBackgroundError() { gradeBackgroundFailed.value = true gradeBackgroundLoaded.value = false @@ -218,6 +262,8 @@ watch(() => [store.state.userInfo?.id, store.state.hasLogin], () => { if (String(account.id || '') !== String(userInfo.value.id || '')) { userInfo.value = account resetMemberGrade() + paidMemberRequestId++ + paidMemberInfo.value = null walletNum.value = 0 couponNum.value = 0 footNum.value = 0 @@ -256,9 +302,11 @@ async function refreshUserPage() { userInfo.value = isLogin() || {} try { if (isLogin('auth')) { - await Promise.allSettled([loadMemberGrade(), getUserOrderNum()]) + await Promise.allSettled([loadMemberGrade(), loadPaidMemberInfo(), getUserOrderNum()]) } else { resetMemberGrade() + paidMemberRequestId++ + paidMemberInfo.value = null walletNum.value = 0 couponNum.value = 0 footNum.value = 0 @@ -313,6 +361,11 @@ async function getUserOrderNum() {