Commit 6a9e49af authored by spc's avatar spc

Merge branch 'feihesanqi_20251014' of http://gitlab.dui88.com/fh/20250528_FHQ1...

Merge branch 'feihesanqi_20251014' of http://gitlab.dui88.com/fh/20250528_FHQ1 into feihesanqi_20251014# Please enter a commit message to explain why this merge is necessary,
parents 88dbcbe7 3730162c
......@@ -19,6 +19,23 @@
font-weight: bold;
margin-left: 16rpx;
color: #1d1e25;
// 不同等级的文字颜色
&.item-0 {
color: #503404; // LV1 深金色
}
&.item-1 {
color: #284A6C; // LV2 深蓝色
}
&.item-2 {
color: #322D6F; // LV3 深紫色
}
&.item-3 {
color: #503404; // LV4 深金色
}
&.item-4 {
color: #FFF0DF; // LV5 浅金色
}
}
}
......@@ -26,9 +43,9 @@
.credits_sale_container {
box-sizing: border-box;
width: 686rpx;
background-color: #EDE8D6;
border-radius: 30rpx;
margin-top: 30rpx;
// 背景色通过内联样式动态设置
// Tab切换区域样式 - 匹配截图中的不规则形状效果
.credits_sale_tabs {
......@@ -36,8 +53,8 @@
border-radius: 30rpx; // 与容器圆角保持一致
display: flex;
position: relative;
overflow: hidden;
background-color: #E5D5B0;
overflow: visible; // 改为visible,让三角形能显示出来
// 背景色通过内联样式动态设置
padding-bottom: 20px;
// 2场秒杀:平分区域
......@@ -78,32 +95,43 @@
&.active {
color: #1C1C1C;
font-weight: bold;
background-color: #EDE8D6;
background-color: transparent;
position: relative;
}
// &::after {
// content: '';
// position: absolute;
// right: -65rpx;
// top: 0;
// width: 116rpx;
// height: 100%;
// background-color: #EDE8D6;
// transform: skewX(30deg);
// border-radius: 0 30rpx 0 30rpx;
// z-index: -1;
// }
// &::before {
// content: '';
// position: absolute;
// right: -242rpx;
// top: 0;
// width: 30rpx;
// height: 30rpx;
// background-color: #EDE8D6;
// border-radius: 0 30rpx 0 30rpx;
// }
// 弧形三角形样式 - 使用base64 SVG背景图
.triangle-left {
position: absolute;
left: -100rpx;
top: 0;
pointer-events: none;
width: 200rpx;
height: 102%;
background-size: 100% 100%;
background-repeat: no-repeat;
background-position: center;
}
.triangle-right {
position: absolute;
right: -100rpx;
top: 0;
pointer-events: none;
width: 200rpx;
height: 102%;
background-size: 100% 100%;
background-repeat: no-repeat;
background-position: center;
}
// 背景色元素样式
.tab_bg_element {
position: absolute;
left: 50rpx;
right: 50rpx;
top: 0;
bottom: -2rpx;
// 背景色通过内联样式动态设置
}
// 多场秒杀内容区域样式
......@@ -112,6 +140,7 @@
flex-direction: column;
align-items: center;
text-align: center;
position: relative;
.tab_time_info {
margin-bottom: 18rpx;
......@@ -169,6 +198,7 @@
flex-direction: column;
align-items: center;
text-align: center;
position: relative;
.tab_time_info {
margin-bottom: 6rpx;
......@@ -235,8 +265,8 @@
padding-top: 20rpx;
margin-top: -40rpx;
border-radius: 0rpx 30rpx 30rpx 30rpx;
background-color: #EDE8D6;
position: relative;
// 背景色通过内联样式动态设置
}
// 场次商品列表容器
......@@ -336,6 +366,23 @@
justify-content: center;
transition: all 0.3s ease;
// 不同等级的按钮颜色 - 基于Integral模块的jifen颜色
&.item-0 {
background: linear-gradient(90deg, #5f3c27 0%, #d7aa72 100%);
}
&.item-1 {
background: linear-gradient(90deg, #385e85 0%, #6c9bc9 100%);
}
&.item-2 {
background: linear-gradient(90deg, #403294 0%, #756ae0 100%);
}
&.item-3 {
background: linear-gradient(90deg, #5f3c27 0%, #d4a468 100%);
}
&.item-4 {
background: linear-gradient(90deg, #f6c79c 0%, #d4a468 100%);
}
&.disabled {
background: #B9B9B9;
cursor: not-allowed;
......
......@@ -2,18 +2,25 @@
<view class="credits_sale_section" v-if="shouldShowSection">
<!-- 标题区域 -->
<view class="credits_sale_area">
<text class="credits_sale_title">积分限时购</text>
<text class="credits_sale_title" :class="`item-${itemIndex}`" :style="{ color: getColor('textColor')[itemIndex] }">积分限时购</text>
</view>
<!-- 积分限时购内容容器 -->
<view class="credits_sale_container">
<!-- 积分限时购内容容器 -->
<view class="credits_sale_container" :class="`item-${itemIndex}`" :style="{ backgroundColor: getColor('bgColor')[itemIndex] }">
<!-- 场次Tab切换区域 -->
<view class="credits_sale_tabs"
v-if="creditsSaleData.sessions && creditsSaleData.sessions.length > 1"
:class="getTabContainerClass">
:class="getTabContainerClass"
:style="{ backgroundColor: getColor('tabsColor')[itemIndex] }">
<view v-for="(session, index) in creditsSaleData.sessions || []" :key="index" class="tab_item"
:class="{ active: index === currentSessionIndex }" @click="currentSessionIndex = index">
:class="[`item-${itemIndex}`, { active: index === currentSessionIndex }]" @click="currentSessionIndex = index">
<!-- 背景色元素 - 只在active状态下显示 -->
<view v-if="index === currentSessionIndex" class="tab_bg_element" :style="{ left: index > 0 ? '50rpx' : '0', backgroundColor: getColor('bgColor')[itemIndex] }"></view>
<!-- 左侧弧形三角形 - 使用base64 SVG,第一个tab不显示 -->
<view v-if="index === currentSessionIndex && index > 0" class="triangle-left" :style="{ backgroundImage: getTriangleLeftSvg(itemIndex) }"></view>
<!-- 右侧弧形三角形 - 使用base64 SVG -->
<view v-if="index === currentSessionIndex" class="triangle-right" :style="{ backgroundImage: getTriangleRightSvg(itemIndex) }"></view>
<!-- 正在秒杀状态:倒计时在上,文案在下 -->
<view v-if="session.status === 'ongoing'" class="tab_content_ongoing">
<view class="tab_time_info">
......@@ -70,6 +77,8 @@
<!-- 当前选中场次的商品展示区域 -->
<view class="current_session_content"
:class="`item-${itemIndex}`"
:style="{ backgroundColor: getColor('bgColor')[itemIndex] }"
v-if="creditsSaleData.sessions && creditsSaleData.sessions[currentSessionIndex]">
<!-- 场次商品列表 - 根据商品数量动态调整布局 -->
......@@ -94,7 +103,8 @@
</view>
<!-- 立即抢购按钮 -->
<view class="credits_sale_button"
:class="{ disabled: getGoodButtonInfo(good, creditsSaleData.sessions[currentSessionIndex]).disabled }"
:class="[`item-${itemIndex}`, { disabled: getGoodButtonInfo(good, creditsSaleData.sessions[currentSessionIndex]).disabled }]"
:style="{ backgroundColor: getGoodButtonInfo(good, creditsSaleData.sessions[currentSessionIndex]).disabled ? '#B9B9B9' : getColor('buttonColor')[itemIndex] }"
@click="!getGoodButtonInfo(good, creditsSaleData.sessions[currentSessionIndex]).disabled && handleCreditsSaleClickThrottled(good)">
<text class="credits_sale_button_text">{{ getGoodButtonInfo(good, creditsSaleData.sessions[currentSessionIndex]).text }}</text>
</view>
......@@ -116,6 +126,10 @@ const props = defineProps({
isdebug: {
type: Boolean,
default: false
},
itemIndex: {
type: Number,
default: 0
}
});
......@@ -125,6 +139,52 @@ const emit = defineEmits(['credits-sale-click']);
// Store
const integralStore = useIntegralStore();
// 皮肤颜色配置 - 从Integral页面复用的颜色系统
const getColor = (type) => {
let colors = '';
switch (type) {
case 'bgColor':
colors = ['#EDE8D6', '#d6e8f7', '#eeeaf3', '#f2e9c7', '#49443f'];
break;
case 'textColor':
colors = ['#503404', '#284a6c', '#322d6f', '#503404', '#fff0df'];
break;
case 'buttonColor':
// 基于Integral模块中jifen的currentPoints颜色
colors = ['#5f3c27', '#385e85', '#403294', '#5f3c27', '#f6c79c'];
break;
case 'accentColor':
// 基于Integral模块中jifen的totalPoints颜色
colors = ['#d7aa72', '#6c9bc9', '#756ae0', '#d4a468', '#d4a468'];
break;
case 'tabsColor':
// Tab切换区域背景色
colors = ['#e5d5b0', '#a9cce8', '#d7c9ee', '#e6d7a5', '#2b221d'];
break;
}
return colors;
};
// 生成左侧三角形SVG的URL编码
const getTriangleLeftSvg = (itemIndex) => {
const color = getColor('bgColor')[itemIndex];
// 使用原始路径数据,只调整SVG尺寸
const svg = `<svg width="50" height="60" viewBox="0 0 43.51 52" xmlns="http://www.w3.org/2000/svg">
<path d="M43.51 0 C37.14 0 31.37 3.79061 28.836 9.64622 L14.684 42.3538 C12.15 48.2094 6.38 52 0 52 H43.51 V0Z" fill="${color}" />
</svg>`;
return `url("data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}")`;
};
// 生成右侧三角形SVG的URL编码
const getTriangleRightSvg = (itemIndex) => {
const color = getColor('bgColor')[itemIndex];
// 使用原始路径数据,只调整SVG尺寸
const svg = `<svg width="50" height="60" viewBox="0 0 43.51 52" xmlns="http://www.w3.org/2000/svg">
<path d="M0 0 C6.37 0 12.14 3.79061 14.674 9.64622 L28.826 42.3538 C31.36 48.2094 37.13 52 43.51 52 H0 V0Z" fill="${color}" />
</svg>`;
return `url("data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}")`;
};
// 积分限时购数据 - 秒杀场次
const creditsSaleData = ref({
sessions: []
......@@ -525,21 +585,21 @@ const generateTestSeckillData = () => {
const now = new Date();
const baseTime = now.getTime();
// 第一场:已结束(2小时前开始,1小时前结束)
const session1Start = baseTime - 2 * 60 * 60 * 1000; // 2小时前
const session1End = baseTime - 1 * 60 * 60 * 1000; // 1小时前
// 第一场:已结束(3小时前开始,2小时前结束)
const session1Start = baseTime - 3 * 60 * 60 * 1000; // 3小时前
const session1End = baseTime - 2 * 60 * 60 * 1000; // 2小时前
// 第二场:已结束(1小时前开始,30分钟前结束)
const session2Start = baseTime - 1 * 60 * 60 * 1000; // 1小时前
const session2End = baseTime - 30 * 60 * 1000; // 30分钟
// 第二场:已结束(2小时前开始,1小时前结束)
const session2Start = baseTime - 2 * 60 * 60 * 1000; // 2小时前
const session2End = baseTime - 1 * 60 * 60 * 1000; // 1小时
// 第三场:即将开始(20秒后开始,30秒后结束)
const session3Start = baseTime + 20 * 1000; // 20秒
const session3End = baseTime + 30 * 1000; // 30秒
// 第三场:即将开始(1小时后开始,2小时后结束)
const session3Start = baseTime + 1 * 60 * 60 * 1000; // 1小时
const session3End = baseTime + 2 * 60 * 60 * 1000; // 2小时
// 第四场:即将开始(40分钟后开始,50分钟后结束)
const session4Start = baseTime + 40 * 60 * 1000; // 40分钟
const session4End = baseTime + 50 * 60 * 1000; // 50分钟
// 第四场:即将开始(2小时后开始,3小时后结束)
const session4Start = baseTime + 2 * 60 * 60 * 1000; // 2小时
const session4End = baseTime + 3 * 60 * 60 * 1000; // 3小时
return {
"code": "000000",
......@@ -733,18 +793,18 @@ const generateTestSeckillData = () => {
const loadSeckillData = async () => {
try {
// 使用测试数据
// const testData = generateTestSeckillData();
// mapSeckillDataToCreditsSale(testData);
// // // 初始化倒计时
// initCountdowns();
const testData = generateTestSeckillData();
mapSeckillDataToCreditsSale(testData);
// // 初始化倒计时
initCountdowns();
// 如果需要真实数据,可以取消注释下面的代码
const seckillData = await integralStore.getSeckillData(props.isdebug);
if (seckillData) {
mapSeckillDataToCreditsSale(seckillData);
// 初始化倒计时
initCountdowns();
}
// const seckillData = await integralStore.getSeckillData(props.isdebug);
// if (seckillData) {
// mapSeckillDataToCreditsSale(seckillData);
// // 初始化倒计时
// initCountdowns();
// }
} catch (error) {
console.error('获取秒杀数据失败:', error);
}
......
......@@ -185,11 +185,14 @@ onMounted(async () => {
//获取邀请码和奖励
const res = await integralStore.getOriginInviteHome();
if(res.success && res.data?.unclaimedPrize) {
// const unionId = uni.getStorageSync('unionId');
const unclaimedPrize = res.data?.unclaimedPrize;
if(res.success && unclaimedPrize) {
globalStore.isShowInvitePrizePanel = true;
globalStore.inviteCount = res.data?.invitedCount;
globalStore.prizeName = res.data?.invitationImageUrl;//????
globalStore.prizeImage = res.data?.invitationImageUrl;
globalStore.prizeName = unclaimedPrize?.prizeName;
globalStore.prizeImage = res.data?.prizeImageUrl;
}
console.log('邀请活动首页数据:', res);
});
......
......@@ -34,7 +34,6 @@
justify-content: center;
box-shadow: 0 4rpx 20rpx rgba(211, 164, 88, 0.3);
transition: transform 0.2s ease;
z-index: 2;
&:active {
transform: translateX(-50%) scale(0.95);
......@@ -46,6 +45,16 @@
font-weight: bold;
}
}
.sharepage_login_button {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0.2;
background-color: #000;
}
}
}
......@@ -8,7 +8,14 @@
<view class="claim_button" @click="handleClaim">
<text class="claim_text">一键领取</text>
</view>
<button class="sharepage_login_button"
v-if="!isLogin"
open-type="getPhoneNumber"
@getphonenumber="onGetPhoneNumber"
:debug-mode="debugMode"
/>
</view>
<!-- 分享登录弹窗 -->
<!-- <sharepoplogin
......@@ -43,14 +50,14 @@ const showSharePopLogin = ref(false);
const showShareNPopNoLogin = ref(true);
const handlePageClick = () => {
console.log('handlePageClick');
if(!isLogin.value) {
needReinit.value = true;
jump({
type: JumpType.INNER,
url: "/pages/activity/register",
})
}
// console.log('handlePageClick');
// if(!isLogin.value) {
// needReinit.value = true;
// jump({
// type: JumpType.INNER,
// url: "/pages/activity/register",
// })
// }
};
// 获取store实例
......@@ -60,37 +67,97 @@ const integralStore = useIntegralStore();
const isLogin = computed(()=>{
//return false
console.log('isLogin--sharepage:', userStore.isLogin);
return userStore.isLogin;
})
const isnew = ref(false);
const inviteCode = ref('');
const unionId = ref('oQ9KswkD0qMVwPHQGslkHaJ0QxnE' || '');
onMounted(() => {
// 页面加载时显示分享未登录弹窗
// showShareNPopNoLogin.value = true;
const unionId = ref('');
const showPhone = ref(false);
// 获取邀请码参数
// 获取邀请码和unionId
const initInviteParams = () => {
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1];
const options = currentPage.options || {};
const inviteCode1 = options.inviteCode || '';
inviteCode.value = inviteCode1;
unionId.value = uni.getStorageSync('unionId');
console.log('unionIdsharepage:', unionId.value);
return { inviteCode: inviteCode1, unionId: unionId.value };
};
onMounted(() => {
// 页面加载时显示分享未登录弹窗
// showShareNPopNoLogin.value = true;
if(isLogin.value) {
// 获取邀请码参数
const { inviteCode: ivtCode, unionId: uid } = initInviteParams();
// 如果有邀请码,调用助力接口
if (inviteCode.value && isLogin.value) {
callAssistInvite(inviteCode1,unionId.value);
// 如果有邀请码,调用助力接口
if (ivtCode && isLogin.value) {
callAssistInvite(ivtCode, uid);
}
}
});
// Phone authorization
const onGetPhoneNumber = async (e) => {
console.log('onGetPhoneNumber', e.detail)
showLoading('授权中...')
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1];
const options = currentPage.options;
const incomingCode = options.inviteCode;
if (e.detail.errMsg === 'getPhoneNumber:ok') {
try {
// console.warn('onGetPhoneNumber', e.detail)
// 隐藏授权弹窗
userStore.phoneCallback(e.detail, null, null, async () => {
hideLoading()
// 重新获取用户信息(登录后)getphonenumber
await Promise.all([
userStore.loadUserInfo(),
userStore.loadMemberInfo(),
])
console.warn('授权后重新获取用户信息')
// 获取邀请码参数
const { inviteCode: ivtCode, unionId: uid } = initInviteParams();
// 如果有邀请码,调用助力接口
if (ivtCode && isLogin.value) {
callAssistInvite(ivtCode, uid);
}
}, {
wxLoginBusinessDTO: {
activityUserInvite915Code: incomingCode
}
})
} catch (error) {
hideLoading()
console.error('授权后处理失败:', error)
uni.showToast({title: '授权失败', icon: 'none'});
}
} else {
hideLoading()
uni.showToast({title: '授权失败', icon: 'none'});
}
};
// 调用助力接口
const callAssistInvite = async (ivtCode,unionId) => {
try {
// 获取用户unionId
const wxUnionId = userStore.unionId || '';
const res = await integralStore.assistInvite(ivtCode, unionId);
console.log('助力接口返回:', res);
......@@ -101,18 +168,20 @@ const callAssistInvite = async (ivtCode,unionId) => {
onShow(() => {
if(isLogin.value) {
if(isnew.value) {
globalStore.invateUseType = 'new';
//新用户注册登录后调用助力接口
gotoIntegral();
// 如果有邀请码,调用助力接口
if (inviteCode.value) {
callAssistInvite(ivtCode, unionId.value);
}
isnew.value = false;
}
// if(integralStore.assistInviteData.success && integralStore.assistInviteData.data.newUser) {
// globalStore.invateUseType = 'new';
// //新用户注册登录后调用助力接口
// gotoIntegral();
// // 如果有邀请码,调用助力接口
// if (inviteCode.value) {
// callAssistInvite(ivtCode, unionId.value);
// }
// isnew.value = false;
// }
}
});
......@@ -139,23 +208,18 @@ onShow(() => {
// 一键领取按钮点击事件
const handleClaim = () => {
if(!isLogin.value) {
needReinit.value = true;
jump({
type: JumpType.INNER,
url: "/pages/activity/register",
})
isnew.value = true;
}else{
// 设置邀请用户类型
if(isnew.value) {
globalStore.invateUseType = 'new';
} else {
globalStore.invateUseType = 'old';
}
showPhone.value = true;
return;
}
gotoIntegral();
// 设置邀请用户类型
if(integralStore.assistInviteData?.data?.newUser) {
globalStore.invateUseType = 'new';
} else {
globalStore.invateUseType = 'old';
}
gotoIntegral();
};
const gotoIntegral = () => {
......
......@@ -272,7 +272,7 @@
</view>
</view>
<!-- 积分限时购 -->
<SeckillSection :isdebug="isdebug" @credits-sale-click="handleCreditsSaleClick" />
<SeckillSection :isdebug="isdebug" :itemIndex="itemIndex" @credits-sale-click="handleCreditsSaleClick" />
<!-- 邀请得好礼组件 -->
<InviteGift v-if="true" class="invite_container" :itemIndex="itemIndex" @invite="handleInviteClick"
@record="handleRecordClick" />
......@@ -2909,7 +2909,7 @@ onShareAppMessage(() => {
return {
title: '积分分享',
path: '/pages/invate/sharepage' + '?inviteCode=' + integralStore.originInviteHome?.data?.invitationCode,
imageUrl: 'https://course.feihe.com/momclub-picture/integral/1023/invate_star_character1023.png'
imageUrl: integralStore.originInviteHome?.data?.invitationImageUrl || 'https://course.feihe.com/momclub-picture/integral/1023/invate_star_character1023.png'
};
});
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment