1281 lines
36 KiB
Vue
1281 lines
36 KiB
Vue
<template>
|
||
<view class="member-select-container">
|
||
<!-- 页面标题 -->
|
||
<view class="page-header">
|
||
<!-- <view class="header-title">会员等级选择</view> -->
|
||
<view class="header-subtitle">选择适合您的会员等级,享受更多权益</view>
|
||
</view>
|
||
|
||
<!-- 用户会员状态统一显示区域 -->
|
||
<view class="member-status-overview" v-if="showTabs">
|
||
<!-- 根据当前Tab显示对应的会员状态 - 已开通 -->
|
||
<view class="status-card" v-if="getCurrentTabMemberStatus().isVip">
|
||
<view class="status-card-header">
|
||
<text class="status-type">{{ getCurrentTabName() }}</text>
|
||
<text class="status-badge vip">已开通</text>
|
||
</view>
|
||
<view class="status-card-content">
|
||
<!-- 小程序上书会员显示上书本数 -->
|
||
<view class="status-detail" v-if="getCurrentTabType() === 'xcx'">
|
||
<text class="detail-label">已上书本数:</text>
|
||
<text class="detail-value">{{ getCurrentTabMemberStatus().count }}本</text>
|
||
</view>
|
||
<view class="status-detail" v-if="getCurrentTabMemberStatus().expirationDateStr">
|
||
<text class="detail-label">到期时间:</text>
|
||
<text class="detail-value">{{ getCurrentTabMemberStatus().expirationDateStr }}</text>
|
||
</view>
|
||
<view class="status-detail" v-if="getCurrentTabMemberStatus().daysRemaining > 0">
|
||
<text class="detail-label">剩余天数:</text>
|
||
<text
|
||
class="detail-value remaining-days">{{ getCurrentTabMemberStatus().daysRemaining }}天</text>
|
||
</view>
|
||
<view class="status-detail" v-else-if="getCurrentTabMemberStatus().daysRemaining === 0">
|
||
<text class="detail-label expired">会员已到期</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 根据当前Tab显示对应的会员状态 - 已过期 -->
|
||
<view class="status-card expired-card"
|
||
v-if="!getCurrentTabMemberStatus().isVip && getCurrentTabMemberStatus().isExpired">
|
||
<view class="status-card-header">
|
||
<text class="status-type">{{ getCurrentTabName() }}</text>
|
||
<text class="status-badge expired">已到期</text>
|
||
</view>
|
||
<view class="status-card-content">
|
||
<!-- 小程序上书会员显示上书本数 -->
|
||
<view class="status-detail" v-if="getCurrentTabType() === 'xcx'">
|
||
<text class="detail-label">已上书本数:</text>
|
||
<text class="detail-value">{{ getCurrentTabMemberStatus().count }}本</text>
|
||
</view>
|
||
<view class="status-detail" v-if="getCurrentTabMemberStatus().expirationDateStr">
|
||
<text class="detail-label">过期时间:</text>
|
||
<text class="detail-value">{{ getCurrentTabMemberStatus().expirationDateStr }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 未开通当前Tab对应会员时的提示 -->
|
||
<view class="no-member-tip"
|
||
v-if="!getCurrentTabMemberStatus().isVip && !getCurrentTabMemberStatus().isExpired">
|
||
<text class="tip-text">您还未开通{{ getCurrentTabName() }},选择下方套餐开始享受会员权益</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 未显示Tab时显示所有已开通的会员状态 -->
|
||
<view class="member-status-overview" v-if="!showTabs">
|
||
<!-- 小程序上书会员状态 -->
|
||
<view class="status-card" v-if="userMemberStatus.xcx.isVip">
|
||
<view class="status-card-header">
|
||
<text class="status-type">小程序上书会员</text>
|
||
<text class="status-badge vip">已开通</text>
|
||
</view>
|
||
<view class="status-card-content">
|
||
<view class="status-detail">
|
||
<text class="detail-label">已上书本数:</text>
|
||
<text class="detail-value">{{ userMemberStatus.xcx.count }}本</text>
|
||
</view>
|
||
<view class="status-detail" v-if="userMemberStatus.xcx.expirationDateStr">
|
||
<text class="detail-label">到期时间:</text>
|
||
<text class="detail-value">{{ userMemberStatus.xcx.expirationDateStr }}</text>
|
||
</view>
|
||
<view class="status-detail" v-if="userMemberStatus.xcx.daysRemaining > 0">
|
||
<text class="detail-label">剩余天数:</text>
|
||
<text class="detail-value remaining-days">{{ userMemberStatus.xcx.daysRemaining }}天</text>
|
||
</view>
|
||
<view class="status-detail" v-else-if="userMemberStatus.xcx.daysRemaining === 0">
|
||
<text class="detail-label expired">会员已到期</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 小程序上书会员过期状态 -->
|
||
<view class="status-card expired-card" v-if="!userMemberStatus.xcx.isVip && userMemberStatus.xcx.isExpired">
|
||
<view class="status-card-header">
|
||
<text class="status-type">小程序上书会员</text>
|
||
<text class="status-badge expired">已过期</text>
|
||
</view>
|
||
<view class="status-card-content">
|
||
<view class="status-detail">
|
||
<text class="detail-label">已上书本数:</text>
|
||
<text class="detail-value">{{ userMemberStatus.xcx.count }}本</text>
|
||
</view>
|
||
<view class="status-detail" v-if="userMemberStatus.xcx.expirationDateStr">
|
||
<text class="detail-label">过期时间:</text>
|
||
<text class="detail-value">{{ userMemberStatus.xcx.expirationDateStr }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 孔网翻新会员状态 -->
|
||
<view class="status-card" v-if="userMemberStatus.kwfw.isVip">
|
||
<view class="status-card-header">
|
||
<text class="status-type">孔网翻新会员</text>
|
||
<text class="status-badge vip">已开通</text>
|
||
</view>
|
||
<view class="status-card-content">
|
||
<view class="status-detail" v-if="userMemberStatus.kwfw.expirationDateStr">
|
||
<text class="detail-label">到期时间:</text>
|
||
<text class="detail-value">{{ userMemberStatus.kwfw.expirationDateStr }}</text>
|
||
</view>
|
||
<view class="status-detail" v-if="userMemberStatus.kwfw.daysRemaining > 0">
|
||
<text class="detail-label">剩余天数:</text>
|
||
<text class="detail-value remaining-days">{{ userMemberStatus.kwfw.daysRemaining }}天</text>
|
||
</view>
|
||
<view class="status-detail" v-else-if="userMemberStatus.kwfw.daysRemaining === 0">
|
||
<text class="detail-label expired">会员已到期</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 孔网翻新会员过期状态 -->
|
||
<view class="status-card expired-card"
|
||
v-if="!userMemberStatus.kwfw.isVip && userMemberStatus.kwfw.isExpired">
|
||
<view class="status-card-header">
|
||
<text class="status-type">孔网翻新会员</text>
|
||
<text class="status-badge expired">已过期</text>
|
||
</view>
|
||
<view class="status-card-content">
|
||
<view class="status-detail" v-if="userMemberStatus.kwfw.expirationDateStr">
|
||
<text class="detail-label">过期时间:</text>
|
||
<text class="detail-value">{{ userMemberStatus.kwfw.expirationDateStr }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 未开通任何会员时的提示 -->
|
||
<view class="no-member-tip"
|
||
v-if="!userMemberStatus.xcx.isVip && !userMemberStatus.kwfw.isVip && !userMemberStatus.xcx.isExpired && !userMemberStatus.kwfw.isExpired">
|
||
<text class="tip-text">您还未开通任何会员,选择下方套餐开始享受会员权益</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- Tab切换 - 只在展示所有会员时显示 -->
|
||
<view class="tab-container" v-if="showTabs">
|
||
<view class="tab-list">
|
||
<view v-for="(tab, index) in tabs" :key="index" class="tab-item"
|
||
:class="{ 'active': activeTabIndex === index }" @click="switchTab(index)">
|
||
{{ tab.name }}
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 会员卡片列表 -->
|
||
<view class="member-cards">
|
||
<view v-for="(item, index) in memberLevels" :key="index" class="member-card"
|
||
:class="{ 'selected': selectedIndex === index }" @click="selectMember(index)">
|
||
<!-- 会员卡片头部 -->
|
||
<view class="card-header" :style="{ backgroundColor: item.color || '#4A5CFF' }">
|
||
<view class="card-title">{{ item.name }}</view>
|
||
<view class="card-price">¥{{ item.price }}</view>
|
||
</view>
|
||
|
||
<!-- 会员卡片内容 -->
|
||
<view class="card-content">
|
||
<!-- 会员权益列表 -->
|
||
<view class="benefit-item" v-for="(benefit, bIndex) in item.benefits || defaultBenefits"
|
||
:key="bIndex">
|
||
<text class="benefit-icon">✓</text>
|
||
<text class="benefit-text">{{ benefit }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 选择标记 -->
|
||
<view class="select-mark" v-if="selectedIndex === index">
|
||
<text class="select-icon">✓</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 底部支付按钮 -->
|
||
<view class="bottom-bar">
|
||
<view class="selected-info" v-if="selectedIndex !== -1">
|
||
<text class="selected-name">{{ memberLevels[selectedIndex] && memberLevels[selectedIndex].name }}</text>
|
||
<text
|
||
class="selected-price">¥{{ memberLevels[selectedIndex] && memberLevels[selectedIndex].price }}</text>
|
||
</view>
|
||
<view class="pay-button" :class="{ 'disabled': selectedIndex === -1 }" @click="handlePay">
|
||
立即支付
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import {
|
||
callWxPay,
|
||
checkPayStatus,
|
||
getMemberLevelList,
|
||
createKwfwMemberOrder,
|
||
updateKwfwMemberOrder,
|
||
updateUserBooksCountLimit,
|
||
getUserRecbusiness,
|
||
checkKwfwMemberStatus
|
||
} from '@/components/MemberBookCheck.js';
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
memberLevels: [],
|
||
selectedIndex: -1,
|
||
isLoading: false,
|
||
defaultBenefits: [
|
||
'上传书籍数量增加',
|
||
'优先展示您的商品',
|
||
'专属客服服务',
|
||
'更多增值服务'
|
||
],
|
||
// 会员等级颜色配置
|
||
levelColors: [
|
||
'#4A5CFF', // 蓝色
|
||
'#FF7D3C', // 橙色
|
||
'#8A2BE2', // 紫色
|
||
'#FF4757', // 红色
|
||
'#2ED573' // 绿色
|
||
],
|
||
// Tab相关数据
|
||
showTabs: false, // 是否显示tab切换
|
||
activeTabIndex: 0, // 当前激活的tab索引
|
||
tabs: [{
|
||
name: '小程序上书会员',
|
||
type: 'xcx'
|
||
},
|
||
{
|
||
name: '孔网翻新会员',
|
||
type: 'kwfw'
|
||
}
|
||
],
|
||
// 存储所有会员数据
|
||
allMemberData: {
|
||
xcx: [], // 小程序上书会员数据
|
||
kwfw: [] // 孔网翻新会员数据
|
||
},
|
||
// 用户会员状态信息
|
||
userMemberStatus: {
|
||
xcx: {
|
||
isVip: false,
|
||
isExpired: false,
|
||
count: 0,
|
||
expirationDate: null,
|
||
expirationDateStr: '',
|
||
daysRemaining: 0
|
||
},
|
||
kwfw: {
|
||
isVip: false,
|
||
isExpired: false,
|
||
expirationDate: null,
|
||
expirationDateStr: '',
|
||
daysRemaining: 0
|
||
}
|
||
}
|
||
};
|
||
},
|
||
async onLoad(options) {
|
||
// 获取来源页面传递的参数
|
||
this.fromPage = options.from || '';
|
||
this.callback = options.callback || '';
|
||
this.memberType = options.type || ''; // 新增会员类型参数
|
||
|
||
// 加载会员等级数据和用户会员状态
|
||
await Promise.all([
|
||
this.loadMemberLevels(),
|
||
this.loadUserMemberStatus()
|
||
]);
|
||
},
|
||
|
||
async onShow() {
|
||
// 每次页面显示时刷新用户会员状态
|
||
await this.loadUserMemberStatus();
|
||
console.log('页面显示,会员状态已刷新:', this.userMemberStatus);
|
||
},
|
||
methods: {
|
||
// 加载会员等级数据
|
||
async loadMemberLevels() {
|
||
try {
|
||
uni.showLoading({
|
||
title: '加载中...'
|
||
});
|
||
|
||
console.log('加载会员等级数据,来源:', this.fromPage, '类型:', this.memberType);
|
||
|
||
// 根据不同的入口来源展示不同的会员卡片
|
||
if (this.fromPage === 'memberCheck' && this.memberType === 'xcx') {
|
||
// 从checkMemberBooksCount进入,只显示小程序上书会员
|
||
this.showTabs = false;
|
||
await this.loadXcxMemberLevels();
|
||
} else if (this.fromPage === 'kwfw' && this.memberType === 'kwfw') {
|
||
// 从checkKwfwMember进入,只显示翻新会员
|
||
this.showTabs = false;
|
||
this.setKwfwMemberLevels();
|
||
} else {
|
||
// 从toMemberSelect进入或其他情况,显示所有会员卡片
|
||
this.showTabs = true;
|
||
await this.loadAllMemberLevels();
|
||
// 默认显示第一个tab的内容
|
||
this.switchTab(0);
|
||
}
|
||
} catch (error) {
|
||
console.error('加载会员等级数据失败:', error);
|
||
uni.showToast({
|
||
title: '加载会员价格失败',
|
||
icon: 'none'
|
||
});
|
||
|
||
// 加载失败时使用默认数据
|
||
this.setDefaultMemberLevels();
|
||
} finally {
|
||
uni.hideLoading();
|
||
}
|
||
},
|
||
|
||
// 加载小程序上书会员等级数据
|
||
async loadXcxMemberLevels() {
|
||
try {
|
||
// 调用接口获取会员等级列表
|
||
const levelList = await getMemberLevelList();
|
||
console.log('获取到的会员等级列表:', levelList);
|
||
|
||
if (levelList && levelList.length > 0) {
|
||
// 清空原有的会员等级数据
|
||
this.memberLevels = [];
|
||
|
||
// 查找memberType为1的配置
|
||
const memberTypeConfig = levelList.find(item => item.memberType === 1);
|
||
const settledId = memberTypeConfig.id;
|
||
console.log('找到的memberType为1的配置:', memberTypeConfig);
|
||
|
||
if (memberTypeConfig && memberTypeConfig.constraintJson) {
|
||
let parsedConfig;
|
||
|
||
// 解析constraintJson数据
|
||
if (typeof memberTypeConfig.constraintJson === 'string') {
|
||
parsedConfig = JSON.parse(memberTypeConfig.constraintJson);
|
||
} else {
|
||
parsedConfig = memberTypeConfig.constraintJson;
|
||
}
|
||
|
||
console.log('解析后的配置:', parsedConfig);
|
||
|
||
// 确认数据中有miniapp字段
|
||
if (parsedConfig.miniapp) {
|
||
const miniapp = parsedConfig.miniapp;
|
||
console.log('miniapp数据:', miniapp);
|
||
|
||
// 创建月付会员卡
|
||
if (miniapp.month_fee) {
|
||
const monthFee = Number(miniapp.month_fee);
|
||
console.log("月费:", monthFee);
|
||
|
||
this.memberLevels.push({
|
||
id: settledId,
|
||
name: '月付会员 (点击开通)',
|
||
price: monthFee.toFixed(2),
|
||
originalPrice: monthFee * 100, // 转换为分
|
||
// price: '0.01',
|
||
// originalPrice: 1, // 以分为单位
|
||
color: this.levelColors[0],
|
||
unit: '月',
|
||
length: 1,
|
||
serviceName: 'xcx上书会员',
|
||
benefits: [
|
||
'每月上传书籍数量增加',
|
||
// '优先展示您的商品',
|
||
// '专属客服服务',
|
||
'月度VIP标识'
|
||
]
|
||
});
|
||
}
|
||
|
||
// 创建年付会员卡
|
||
if (miniapp.year_fee) {
|
||
const yearFee = Number(miniapp.year_fee);
|
||
console.log("年费:", yearFee);
|
||
|
||
this.memberLevels.push({
|
||
id: settledId,
|
||
name: '年度会员 (点击开通)',
|
||
price: yearFee.toFixed(2),
|
||
originalPrice: yearFee * 100, // 转换为分
|
||
color: this.levelColors[1],
|
||
unit: '月',
|
||
length: 12,
|
||
serviceName: 'xcx上书会员',
|
||
benefits: [
|
||
'无限制上传书籍数量',
|
||
// '优先展示您的商品',
|
||
// '24小时专属客服服务',
|
||
// '年度VIP专属标识',
|
||
'更多增值服务特权'
|
||
]
|
||
});
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 如果没有获取到会员等级数据,显示默认的小程序上书会员数据
|
||
if (this.memberLevels.length === 0) {
|
||
this.setDefaultXcxMemberLevels();
|
||
}
|
||
} catch (error) {
|
||
console.error('加载小程序上书会员数据失败:', error);
|
||
this.setDefaultXcxMemberLevels();
|
||
}
|
||
},
|
||
|
||
// 加载所有会员等级数据(小程序上书会员 + 翻新会员)
|
||
async loadAllMemberLevels() {
|
||
try {
|
||
// 清空之前的数据
|
||
this.allMemberData.xcx = [];
|
||
this.allMemberData.kwfw = [];
|
||
|
||
// 加载小程序上书会员数据
|
||
await this.loadXcxMemberLevels();
|
||
// 将当前的memberLevels保存到xcx数据中
|
||
this.allMemberData.xcx = [...this.memberLevels];
|
||
|
||
// 加载翻新会员数据
|
||
this.setKwfwMemberLevels();
|
||
// 将当前的memberLevels保存到kwfw数据中
|
||
this.allMemberData.kwfw = [...this.memberLevels];
|
||
|
||
} catch (error) {
|
||
console.error('加载所有会员数据失败:', error);
|
||
this.setDefaultAllMemberLevels();
|
||
}
|
||
},
|
||
|
||
// 设置默认小程序上书会员等级数据
|
||
setDefaultXcxMemberLevels() {
|
||
this.memberLevels = [{
|
||
id: 1,
|
||
name: '月付会员 (点击开通)',
|
||
price: '39.90',
|
||
originalPrice: 3990, // 以分为单位
|
||
color: this.levelColors[0],
|
||
unit: '月',
|
||
length: 1,
|
||
sort: 1,
|
||
serviceName: 'xcx上书会员',
|
||
benefits: [
|
||
'每月上传书籍数量增加',
|
||
'优先展示您的商品',
|
||
'专属客服服务',
|
||
'月度VIP标识'
|
||
]
|
||
},
|
||
{
|
||
id: 2,
|
||
name: '年度会员 (点击开通)',
|
||
price: '399.00',
|
||
originalPrice: 39900, // 以分为单位
|
||
color: this.levelColors[1],
|
||
unit: '月',
|
||
length: 12,
|
||
sort: 2,
|
||
serviceName: 'xcx上书会员',
|
||
benefits: [
|
||
'无限制上传书籍数量',
|
||
'优先展示您的商品',
|
||
'24小时专属客服服务',
|
||
'年度VIP专属标识',
|
||
'更多增值服务特权'
|
||
]
|
||
}
|
||
];
|
||
},
|
||
|
||
// 设置默认会员等级数据(兼容旧版本)
|
||
setDefaultMemberLevels() {
|
||
this.setDefaultXcxMemberLevels();
|
||
},
|
||
|
||
// 设置默认所有会员等级数据(小程序上书会员 + 翻新会员)
|
||
setDefaultAllMemberLevels() {
|
||
this.setDefaultXcxMemberLevels();
|
||
|
||
// 添加翻新会员
|
||
this.memberLevels.push({
|
||
id: 'kwfw',
|
||
name: '孔网翻新会员/月 (点击开通)',
|
||
price: '98.00',
|
||
originalPrice: 9800, // 以分为单位
|
||
color: this.levelColors[2], // 使用紫色
|
||
unit: '月',
|
||
length: 1,
|
||
sort: 1,
|
||
serviceName: 'xcx翻新会员',
|
||
benefits: [
|
||
'无限制使用孔网商品翻新功能',
|
||
'批量处理商品信息',
|
||
'优先获得新功能体验'
|
||
],
|
||
type: 'kwfw' // 标识为孔网翻新会员
|
||
});
|
||
},
|
||
|
||
// 设置孔网翻新会员等级数据
|
||
setKwfwMemberLevels() {
|
||
this.memberLevels = [{
|
||
id: 'kwfw',
|
||
name: '孔网翻新会员/月',
|
||
price: '98.00',
|
||
originalPrice: 9800, // 以分为单位
|
||
// price: '0.01',
|
||
// originalPrice: 1, // 以分为单位
|
||
color: this.levelColors[2], // 使用紫色
|
||
unit: '月',
|
||
length: 1,
|
||
sort: 1,
|
||
serviceName: 'xcx翻新会员',
|
||
benefits: [
|
||
'无限制使用孔网商品翻新功能',
|
||
'批量处理商品信息',
|
||
'优先获得新功能体验'
|
||
],
|
||
type: 'kwfw' // 标识为孔网翻新会员
|
||
}];
|
||
},
|
||
|
||
// 选择会员等级
|
||
selectMember(index) {
|
||
this.selectedIndex = index;
|
||
},
|
||
|
||
// 处理支付
|
||
async handlePay() {
|
||
if (this.selectedIndex === -1 || this.isLoading) {
|
||
return;
|
||
}
|
||
|
||
const selectedLevel = this.memberLevels[this.selectedIndex];
|
||
console.log('selectedLevel:', selectedLevel);
|
||
|
||
uni.showModal({
|
||
title: '确认支付',
|
||
content: `您选择了${selectedLevel.name},需支付¥${selectedLevel.price},确认继续吗?`,
|
||
success: async (res) => {
|
||
if (res.confirm) {
|
||
this.isLoading = true;
|
||
|
||
uni.showLoading({
|
||
title: '发起支付...'
|
||
});
|
||
|
||
try {
|
||
// 如果是孔网翻新会员,使用特殊的支付处理逻辑
|
||
if (selectedLevel.type === 'kwfw') {
|
||
await this.handleKwfwMemberPay(selectedLevel);
|
||
} else {
|
||
// 普通会员支付逻辑
|
||
await this.handleNormalMemberPay(selectedLevel);
|
||
}
|
||
} catch (error) {
|
||
console.error('支付过程出错:', error);
|
||
uni.showToast({
|
||
title: '支付过程出错,请重试',
|
||
icon: 'none'
|
||
});
|
||
} finally {
|
||
uni.hideLoading();
|
||
this.isLoading = false;
|
||
}
|
||
}
|
||
}
|
||
});
|
||
},
|
||
|
||
// 处理普通会员支付
|
||
async handleNormalMemberPay(selectedLevel) {
|
||
try {
|
||
const userId = uni.getStorageSync('userId')
|
||
// 第一步:支付前创建订单记录
|
||
const orderData = {
|
||
userId: userId,
|
||
memberType: 'normal',
|
||
amount: selectedLevel.price,
|
||
originalPrice: selectedLevel.originalPrice,
|
||
createTime: new Date().toISOString(),
|
||
unit: selectedLevel.unit,
|
||
length: selectedLevel.length,
|
||
serviceName: selectedLevel.serviceName,
|
||
};
|
||
|
||
console.log('支付前创建普通会员订单:', orderData);
|
||
const createResult = await createKwfwMemberOrder(orderData);
|
||
console.log('创建普通会员订单:', createResult);
|
||
|
||
if (!createResult.success) {
|
||
throw new Error('创建订单失败: ' + createResult.error);
|
||
}
|
||
|
||
// const orderId = createResult.orderId;
|
||
// console.log('普通会员订单创建成功,订单ID:', orderId);
|
||
|
||
// 第二步:发起支付
|
||
// 使用原始价格(分)进行支付
|
||
const originalPrice = selectedLevel.originalPrice;
|
||
|
||
// 获取会员等级ID
|
||
const settledId = selectedLevel.id;
|
||
// console.log('支付会员等级ID:', settledId);
|
||
console.log('订单id:', createResult.orderId.orderId);
|
||
const payResult = await callWxPay(originalPrice, settledId, 'normal', createResult.orderId
|
||
.orderId);
|
||
|
||
// console.log('支付结果:', payResult);
|
||
// console.log('订单更新结果:', updateResult);
|
||
|
||
// 调用更新用户书籍数量限制接口
|
||
// const userId = uni.getStorageSync('userId');
|
||
// const limitUpdateResult = await updateUserBooksCountLimit(payResult, orderId, userId, settledId);
|
||
// console.log('用户书籍数量限制更新结果:', limitUpdateResult);
|
||
|
||
// 孔网翻新会员的订单状态更新在 memberSelect.vue 中通过 updateKwfwMemberOrder 处理
|
||
// console.log('上书会员支付成功,订单状态将通过专用接口更新');
|
||
if (payResult.success) {
|
||
const updateResult = await updateKwfwMemberOrder(createResult.orderId.orderId, payResult, userId);
|
||
uni.showToast({
|
||
title: '支付成功',
|
||
icon: 'success'
|
||
});
|
||
|
||
// 支付成功后的处理
|
||
setTimeout(() => {
|
||
// 如果有回调函数,调用它
|
||
const app = getApp();
|
||
if (app.memberSelectCallback) {
|
||
app.memberSelectCallback(true);
|
||
}
|
||
|
||
// 返回上一页
|
||
// uni.navigateBack();
|
||
uni.navigateTo({
|
||
url: '/pages/user/index'
|
||
});
|
||
}, 1500);
|
||
} else {
|
||
uni.showToast({
|
||
title: '支付未完成',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
} catch (error) {
|
||
console.error('普通会员支付过程出错:', error);
|
||
uni.showToast({
|
||
title: '支付过程出错: ' + error.message,
|
||
icon: 'none',
|
||
duration: 3000
|
||
});
|
||
}
|
||
},
|
||
|
||
// 处理孔网翻新会员支付
|
||
async handleKwfwMemberPay(selectedLevel) {
|
||
// 导入孔网翻新会员订单相关函数
|
||
try {
|
||
const userId = uni.getStorageSync('userId')
|
||
// 第一步:支付前创建订单记录
|
||
const orderData = {
|
||
userId: userId,
|
||
memberType: 'kwfw',
|
||
amount: selectedLevel.price,
|
||
originalPrice: selectedLevel.originalPrice,
|
||
createTime: new Date().toISOString(),
|
||
unit: selectedLevel.unit,
|
||
length: selectedLevel.length,
|
||
serviceName: selectedLevel.serviceName,
|
||
sort: selectedLevel.sort,
|
||
};
|
||
|
||
console.log('支付前创建订单:', orderData);
|
||
const createResult = await createKwfwMemberOrder(orderData);
|
||
console.log('createResult:', createResult);
|
||
if (!createResult.success) {
|
||
throw new Error('创建订单失败: ' + createResult.error);
|
||
}
|
||
|
||
// orderId = createResult.orderId;
|
||
// console.log('订单创建成功,订单ID:', orderId);
|
||
|
||
// 第二步:发起支付
|
||
// 使用原始价格(分)进行支付
|
||
const originalPrice = selectedLevel.originalPrice;
|
||
|
||
// 孔网翻新会员使用特殊的ID标识
|
||
const settledId = 'kwfw_member';
|
||
console.log('支付孔网翻新会员ID:', settledId);
|
||
console.log('订单id:', createResult.orderId.orderId);
|
||
const payResult = await callWxPay(originalPrice, settledId, 'kwfw', createResult.orderId.orderId);
|
||
console.log('支付结果:', payResult);
|
||
|
||
|
||
|
||
// 孔网翻新会员的订单状态更新在 memberSelect.vue 中通过 updateKwfwMemberOrder 处理
|
||
if (payResult.success) {
|
||
await updateKwfwMemberOrder(createResult.orderId.orderId, payResult, userId);
|
||
|
||
uni.showToast({
|
||
title: '支付成功',
|
||
icon: 'success'
|
||
});
|
||
// 支付成功后的处理
|
||
setTimeout(() => {
|
||
// 如果有孔网翻新会员回调函数,调用它
|
||
const app = getApp();
|
||
if (app.kwfwMemberCallback) {
|
||
app.kwfwMemberCallback(true);
|
||
}
|
||
|
||
// 返回上一页
|
||
// uni.navigateBack();
|
||
uni.navigateTo({
|
||
url: '/pages/user/index'
|
||
});
|
||
}, 1500);
|
||
} else {
|
||
uni.showToast({
|
||
title: '支付未完成',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
} catch (error) {
|
||
console.error('孔网翻新会员支付过程出错:', error);
|
||
uni.showToast({
|
||
title: '支付过程出错: ' + error.message,
|
||
icon: 'none',
|
||
duration: 3000
|
||
});
|
||
}
|
||
},
|
||
|
||
// Tab切换方法
|
||
switchTab(index) {
|
||
this.activeTabIndex = index;
|
||
this.selectedIndex = -1; // 重置选择状态
|
||
|
||
const tabType = this.tabs[index].type;
|
||
if (tabType === 'xcx') {
|
||
// 显示小程序上书会员
|
||
this.memberLevels = [...this.allMemberData.xcx];
|
||
} else if (tabType === 'kwfw') {
|
||
// 显示孔网翻新会员
|
||
this.memberLevels = [...this.allMemberData.kwfw];
|
||
}
|
||
},
|
||
|
||
// 时间戳转换为北京时间字符串
|
||
formatTimestamp(timestamp) {
|
||
if (!timestamp) return '';
|
||
|
||
const date = new Date(timestamp);
|
||
const year = date.getFullYear();
|
||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||
const day = String(date.getDate()).padStart(2, '0');
|
||
const hours = String(date.getHours()).padStart(2, '0');
|
||
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||
const seconds = String(date.getSeconds()).padStart(2, '0');
|
||
|
||
return `${year}年${month}月${day}日 ${hours}:${minutes}:${seconds}`;
|
||
},
|
||
|
||
// 计算距离到期还有多少天
|
||
calculateDaysRemaining(timestamp) {
|
||
if (!timestamp) return 0;
|
||
|
||
const now = new Date().getTime();
|
||
const expiration = new Date(timestamp).getTime();
|
||
const diffTime = expiration - now;
|
||
|
||
if (diffTime <= 0) return 0;
|
||
|
||
return Math.ceil(diffTime / (1000 * 60 * 60 * 24));
|
||
},
|
||
|
||
// 获取用户小程序上书会员状态
|
||
async getUserXcxMemberStatus() {
|
||
try {
|
||
const userId = uni.getStorageSync('userId');
|
||
if (!userId) {
|
||
console.log('用户未登录');
|
||
return;
|
||
}
|
||
|
||
const response = await getUserRecbusiness(userId);
|
||
console.log('小程序上书会员状态响应:', response);
|
||
|
||
if (response && response.data) {
|
||
if (response.data.code === 200 && response.data.data) {
|
||
// 成功获取用户会员状态
|
||
const data = response.data.data;
|
||
|
||
// 判断是否过期:有expirationDate但isVip为false
|
||
const isExpired = !data.isVip && data.expirationDate;
|
||
|
||
this.userMemberStatus.xcx = {
|
||
isVip: data.isVip,
|
||
isExpired: isExpired,
|
||
count: data.count || 0,
|
||
expirationDate: data.expirationDate,
|
||
expirationDateStr: data.expirationDate ? this.formatTimestamp(data
|
||
.expirationDate) : '',
|
||
daysRemaining: data.expirationDate ? this.calculateDaysRemaining(data
|
||
.expirationDate) : 0
|
||
};
|
||
console.log('小程序上书会员状态更新成功:', this.userMemberStatus.xcx);
|
||
} else {
|
||
// 其他错误情况,设置为未开通状态
|
||
console.log('小程序上书会员:获取状态失败,设置为未开通状态', response);
|
||
this.userMemberStatus.xcx = {
|
||
isVip: false,
|
||
isExpired: false,
|
||
count: 0,
|
||
expirationDate: null,
|
||
expirationDateStr: '',
|
||
daysRemaining: 0
|
||
};
|
||
}
|
||
} else {
|
||
// 响应为空,设置为未开通状态
|
||
console.log('小程序上书会员:响应为空,设置为未开通状态');
|
||
this.userMemberStatus.xcx = {
|
||
isVip: false,
|
||
isExpired: false,
|
||
count: 0,
|
||
expirationDate: null,
|
||
expirationDateStr: '',
|
||
daysRemaining: 0
|
||
};
|
||
}
|
||
} catch (error) {
|
||
console.error('获取小程序上书会员状态失败:', error);
|
||
// 发生异常时也设置为未开通状态
|
||
this.userMemberStatus.xcx = {
|
||
isVip: false,
|
||
isExpired: false,
|
||
count: 0,
|
||
expirationDate: null,
|
||
expirationDateStr: '',
|
||
daysRemaining: 0
|
||
};
|
||
}
|
||
},
|
||
|
||
// 获取用户孔网翻新会员状态
|
||
async getUserKwfwMemberStatus() {
|
||
try {
|
||
const userId = uni.getStorageSync('userId');
|
||
if (!userId) {
|
||
console.log('用户未登录');
|
||
return;
|
||
}
|
||
|
||
const response = await checkKwfwMemberStatus(userId);
|
||
console.log('孔网翻新会员状态响应:', response);
|
||
|
||
if (response) {
|
||
if (response.data.code === 200 && response.data.data) {
|
||
// 用户存在,处理会员状态
|
||
const data = response.data.data;
|
||
|
||
// 判断是否过期:有expirationDate但isVip为false
|
||
const isExpired = !data.isVip && data.expirationDate;
|
||
|
||
this.userMemberStatus.kwfw = {
|
||
isVip: data.isVip || false,
|
||
isExpired: isExpired,
|
||
expirationDate: data.expirationDate,
|
||
expirationDateStr: data.expirationDate ? this.formatTimestamp(data
|
||
.expirationDate) : '',
|
||
daysRemaining: data.expirationDate ? this.calculateDaysRemaining(data
|
||
.expirationDate) : 0
|
||
};
|
||
} else if (response.data.code === 40001) {
|
||
// 用户未找到,设置为未开通状态
|
||
console.log('孔网翻新会员:用户未找到,设置为未开通状态');
|
||
this.userMemberStatus.kwfw = {
|
||
isVip: false,
|
||
isExpired: false,
|
||
expirationDate: null,
|
||
expirationDateStr: '',
|
||
daysRemaining: 0
|
||
};
|
||
} else {
|
||
// 其他错误情况,也设置为未开通状态
|
||
console.log('孔网翻新会员:其他错误,设置为未开通状态', response);
|
||
this.userMemberStatus.kwfw = {
|
||
isVip: false,
|
||
isExpired: false,
|
||
expirationDate: null,
|
||
expirationDateStr: '',
|
||
daysRemaining: 0
|
||
};
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('获取孔网翻新会员状态失败:', error);
|
||
// 发生异常时也设置为未开通状态
|
||
this.userMemberStatus.kwfw = {
|
||
isVip: false,
|
||
isExpired: false,
|
||
expirationDate: null,
|
||
expirationDateStr: '',
|
||
daysRemaining: 0
|
||
};
|
||
}
|
||
},
|
||
|
||
// 获取所有用户会员状态
|
||
async loadUserMemberStatus() {
|
||
await Promise.all([
|
||
this.getUserXcxMemberStatus(),
|
||
this.getUserKwfwMemberStatus()
|
||
]);
|
||
},
|
||
|
||
// 根据会员卡片类型获取对应的用户会员状态
|
||
|
||
// 获取当前Tab的会员状态
|
||
getCurrentTabMemberStatus() {
|
||
const currentTabType = this.getCurrentTabType();
|
||
if (currentTabType === 'xcx' && this.userMemberStatus.xcx) {
|
||
return this.userMemberStatus.xcx;
|
||
} else if (currentTabType === 'kwfw' && this.userMemberStatus.kwfw) {
|
||
return this.userMemberStatus.kwfw;
|
||
}
|
||
return {
|
||
isVip: false,
|
||
isExpired: false,
|
||
count: 0,
|
||
expirationDate: null,
|
||
expirationDateStr: '',
|
||
daysRemaining: 0
|
||
};
|
||
},
|
||
|
||
// 获取当前Tab的类型
|
||
getCurrentTabType() {
|
||
if (this.showTabs && this.tabs && this.tabs[this.activeTabIndex] && this.tabs[this.activeTabIndex].type) {
|
||
return this.tabs[this.activeTabIndex].type;
|
||
}
|
||
return '';
|
||
},
|
||
|
||
// 获取当前Tab的名称
|
||
getCurrentTabName() {
|
||
if (this.showTabs && this.tabs && this.tabs[this.activeTabIndex] && this.tabs[this.activeTabIndex].name) {
|
||
return this.tabs[this.activeTabIndex].name;
|
||
}
|
||
return '会员';
|
||
}
|
||
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.member-select-container {
|
||
min-height: 100vh;
|
||
background-color: #f8f9fc;
|
||
padding: 30rpx;
|
||
box-sizing: border-box;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.page-header {
|
||
margin-bottom: 40rpx;
|
||
text-align: center;
|
||
}
|
||
|
||
.header-title {
|
||
font-size: 40rpx;
|
||
font-weight: bold;
|
||
color: #333;
|
||
margin-bottom: 10rpx;
|
||
}
|
||
|
||
.header-subtitle {
|
||
font-size: 28rpx;
|
||
color: #666;
|
||
}
|
||
|
||
/* 会员状态统一显示区域样式 */
|
||
.member-status-overview {
|
||
margin-bottom: 30rpx;
|
||
}
|
||
|
||
.status-card {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
border-radius: 16rpx;
|
||
padding: 30rpx;
|
||
margin-bottom: 20rpx;
|
||
box-shadow: 0 8rpx 24rpx rgba(102, 126, 234, 0.15);
|
||
}
|
||
|
||
|
||
|
||
.status-card-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.status-type {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #fff;
|
||
}
|
||
|
||
.status-badge.vip {
|
||
background-color: #FFD700;
|
||
color: #333;
|
||
padding: 8rpx 16rpx;
|
||
border-radius: 20rpx;
|
||
font-size: 24rpx;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.status-badge.expired {
|
||
background-color: rgba(255, 255, 255, 0.2);
|
||
color: #FF6B6B;
|
||
padding: 8rpx 16rpx;
|
||
border-radius: 20rpx;
|
||
font-size: 24rpx;
|
||
font-weight: bold;
|
||
border: 1rpx solid #FF6B6B;
|
||
}
|
||
|
||
.status-card-content {
|
||
background-color: rgba(255, 255, 255, 0.1);
|
||
border-radius: 12rpx;
|
||
padding: 20rpx;
|
||
}
|
||
|
||
.status-detail {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 12rpx;
|
||
}
|
||
|
||
.status-detail:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.detail-label {
|
||
font-size: 26rpx;
|
||
color: rgba(255, 255, 255, 0.8);
|
||
}
|
||
|
||
.detail-label.expired {
|
||
color: #FF6B6B;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.detail-value {
|
||
font-size: 26rpx;
|
||
color: #fff;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.detail-value.remaining-days {
|
||
color: #FFD700;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.no-member-tip {
|
||
background-color: #fff;
|
||
border-radius: 16rpx;
|
||
padding: 40rpx 30rpx;
|
||
text-align: center;
|
||
border: 2rpx dashed #ddd;
|
||
}
|
||
|
||
.tip-text {
|
||
font-size: 28rpx;
|
||
color: #999;
|
||
line-height: 1.5;
|
||
}
|
||
|
||
.tab-container {
|
||
margin-bottom: 30rpx;
|
||
}
|
||
|
||
.tab-list {
|
||
display: flex;
|
||
background-color: #f5f5f5;
|
||
border-radius: 12rpx;
|
||
padding: 6rpx;
|
||
}
|
||
|
||
.tab-item {
|
||
flex: 1;
|
||
text-align: center;
|
||
padding: 20rpx 0;
|
||
font-size: 28rpx;
|
||
color: #666;
|
||
border-radius: 8rpx;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.tab-item.active {
|
||
background-color: #fff;
|
||
color: #4A5CFF;
|
||
font-weight: bold;
|
||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
.member-cards {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 30rpx;
|
||
margin-bottom: 40rpx;
|
||
flex: 1;
|
||
}
|
||
|
||
.member-card {
|
||
background-color: #fff;
|
||
border-radius: 16rpx;
|
||
overflow: hidden;
|
||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
|
||
position: relative;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.member-card.selected {
|
||
transform: scale(1.02);
|
||
box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
.card-header {
|
||
padding: 30rpx;
|
||
color: #fff;
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.card-header::after {
|
||
content: '';
|
||
position: absolute;
|
||
right: -40rpx;
|
||
top: -40rpx;
|
||
width: 120rpx;
|
||
height: 120rpx;
|
||
border-radius: 50%;
|
||
background-color: rgba(255, 255, 255, 0.1);
|
||
}
|
||
|
||
.card-title {
|
||
font-size: 36rpx;
|
||
font-weight: bold;
|
||
margin-bottom: 10rpx;
|
||
}
|
||
|
||
.card-price {
|
||
font-size: 48rpx;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.card-content {
|
||
padding: 30rpx;
|
||
}
|
||
|
||
|
||
|
||
.benefit-item {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.benefit-item:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.benefit-icon {
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
background-color: #f0f5ff;
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: #4A5CFF;
|
||
margin-right: 20rpx;
|
||
font-size: 24rpx;
|
||
}
|
||
|
||
.benefit-text {
|
||
font-size: 28rpx;
|
||
color: #666;
|
||
}
|
||
|
||
.select-mark {
|
||
position: absolute;
|
||
top: 20rpx;
|
||
right: 20rpx;
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
border-radius: 50%;
|
||
background-color: #fff;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.select-icon {
|
||
color: #4A5CFF;
|
||
font-size: 24rpx;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.bottom-bar {
|
||
position: sticky;
|
||
bottom: 0;
|
||
left: 0;
|
||
right: 0;
|
||
background-color: #fff;
|
||
padding: 30rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
box-shadow: 0 -4rpx 10rpx rgba(0, 0, 0, 0.05);
|
||
border-radius: 16rpx;
|
||
margin-top: 20rpx;
|
||
}
|
||
|
||
.selected-info {
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.selected-name {
|
||
font-size: 28rpx;
|
||
color: #666;
|
||
}
|
||
|
||
.selected-price {
|
||
font-size: 40rpx;
|
||
font-weight: bold;
|
||
color: #FF4757;
|
||
}
|
||
|
||
.pay-button {
|
||
background: linear-gradient(to right, #4A5CFF, #6979FF);
|
||
color: #fff;
|
||
padding: 20rpx 60rpx;
|
||
border-radius: 50rpx;
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
box-shadow: 0 10rpx 20rpx rgba(74, 92, 255, 0.3);
|
||
}
|
||
|
||
.pay-button.disabled {
|
||
background: linear-gradient(to right, #ccc, #ddd);
|
||
box-shadow: none;
|
||
opacity: 0.8;
|
||
}
|
||
</style> |