Commit dabb76e6 authored by 王炽's avatar 王炽

Merge branch 'feihesanqi_20251014' of...

Merge branch 'feihesanqi_20251014' of http://gitlab2.dui88.com/fh/20250528_FHQ1 into feihesanqi_20251014
parents 4812b0cc 64904fb4
...@@ -12,6 +12,24 @@ const { ...@@ -12,6 +12,24 @@ const {
export const fetchGoodsDetail = (data) => api.get('/c/goods/detail', data); export const fetchGoodsDetail = (data) => api.get('/c/goods/detail', data);
/**
* 获取秒杀商品详情
* @param {Object} data - 请求参数
* @param {string} data.id - 商品ID (必须)
* @param {string} [data.phone] - 充值号码 (可选)
* @param {string} [data.buyNum=1] - 下单数量 (可选,默认1)
* @param {string} [data.storeId] - 门店ID (可选)
* @param {string} [data.amount] - 充值面额 (可选)
* @param {string} [data.channel] - 渠道 (可选)
* @param {string} [data.addressId] - 地址ID (可选)
* @param {string} data.appGoodsId - 应用商品ID (必须)
* @param {string} data.sessionKey - 会话密钥 (必须)
* @returns {Promise} API响应
* @description 获取秒杀商品详情信息
*/
export const fetchSeckillDetail = (data) => api.get('/c/seckill/detail', data);
/** /**
...@@ -51,6 +69,23 @@ export const fetchGoodsPrice = (data) => api.post('/c/goods/price', data); ...@@ -51,6 +69,23 @@ export const fetchGoodsPrice = (data) => api.post('/c/goods/price', data);
export const fetchTradeCredits = (data) => api.post('/c/trade/credits', data); export const fetchTradeCredits = (data) => api.post('/c/trade/credits', data);
/**
* 秒杀下单
* @param {Object} data - 请求参数
* @param {string} data.id - 商品ID (必须)
* @param {string} [data.phone] - 充值号码 (可选)
* @param {string} [data.buyNum=1] - 下单数量 (可选,默认1)
* @param {string} [data.storeId] - 门店ID (可选)
* @param {string} [data.amount] - 充值面额 (可选)
* @param {string} [data.channel] - 渠道 (可选)
* @param {string} [data.addressId] - 地址ID (可选)
* @param {string} data.appGoodsId - 应用商品ID (必须)
* @param {string} data.sessionKey - 会话密钥 (必须)
* @returns {Promise} API响应
* @description 秒杀下单,不需要调用价格计算接口
*/
export const fetchSeckillTakeOrder = (data) => api.post('/c/seckill/takeOrder', data);
...@@ -243,6 +243,58 @@ const getGoodsListClass = () => { ...@@ -243,6 +243,58 @@ const getGoodsListClass = () => {
return ''; return '';
}; };
// 智能定位场次索引
const getTargetSessionIndex = (sessions) => {
if (!sessions || sessions.length === 0) return 0;
// 1. 有正在秒杀的就定位到正在秒杀的场次
const ongoingSessions = sessions.filter(session => session.status === 'ongoing');
if (ongoingSessions.length > 0) {
// 如果有多个正在秒杀的场次,选择开始时间最早的
const earliestOngoingSession = ongoingSessions.reduce((earliest, current) => {
const getStartTimeFromTags = (session) => {
const timeTag = session.timeTags.find(tag => tag.includes('开始') && /^\d{2}:\d{2}开始$/.test(tag));
if (timeTag) {
const timeStr = timeTag.replace('开始', '');
const [hours, minutes] = timeStr.split(':').map(Number);
return hours * 60 + minutes;
}
return 0;
};
return getStartTimeFromTags(current) < getStartTimeFromTags(earliest) ? current : earliest;
});
return sessions.findIndex(session => session.id === earliestOngoingSession.id);
}
// 2. 只有已结束和未开始时定位到即将开始的场次
const upcomingSessions = sessions.filter(session => session.status === 'upcoming');
if (upcomingSessions.length > 0) {
// 选择开始时间最早的即将开始的场次
const earliestUpcomingSession = upcomingSessions.reduce((earliest, current) => {
const getStartTimeFromTags = (session) => {
const timeTag = session.timeTags.find(tag => tag.includes('开始') && /^\d{2}:\d{2}开始$/.test(tag));
if (timeTag) {
const timeStr = timeTag.replace('开始', '');
const [hours, minutes] = timeStr.split(':').map(Number);
return hours * 60 + minutes;
}
return 0;
};
return getStartTimeFromTags(current) < getStartTimeFromTags(earliest) ? current : earliest;
});
return sessions.findIndex(session => session.id === earliestUpcomingSession.id);
}
// 3. 全部结束定位到最后一个场次
const allEnded = sessions.every(session => session.status === 'ended');
if (allEnded) {
return sessions.length - 1;
}
// 4. 所有场次未开始时定位到第一个场次
return 0;
};
// 开始倒计时 // 开始倒计时
const startCountdown = (sessionId, initialSeconds) => { const startCountdown = (sessionId, initialSeconds) => {
if (countdownTimers.value[sessionId]) { if (countdownTimers.value[sessionId]) {
...@@ -254,7 +306,8 @@ const startCountdown = (sessionId, initialSeconds) => { ...@@ -254,7 +306,8 @@ const startCountdown = (sessionId, initialSeconds) => {
seconds--; seconds--;
if (seconds <= 0) { if (seconds <= 0) {
clearInterval(countdownTimers.value[sessionId]); clearInterval(countdownTimers.value[sessionId]);
// 倒计时结束,可以触发相应逻辑 // 倒计时结束,自动切换到下一场
handleCountdownEnd(sessionId);
} }
// 更新对应场次的倒计时数据 // 更新对应场次的倒计时数据
const session = creditsSaleData.value.sessions.find(s => s.id === sessionId); const session = creditsSaleData.value.sessions.find(s => s.id === sessionId);
...@@ -264,11 +317,66 @@ const startCountdown = (sessionId, initialSeconds) => { ...@@ -264,11 +317,66 @@ const startCountdown = (sessionId, initialSeconds) => {
}, 1000); }, 1000);
}; };
// 处理倒计时结束
const handleCountdownEnd = (endedSessionId) => {
const sessions = creditsSaleData.value.sessions;
const currentIndex = sessions.findIndex(s => s.id === endedSessionId);
const endedSession = sessions[currentIndex];
// 如果当前场次是"即将开始"状态,转换为"正在秒杀"
if (endedSession && endedSession.status === 'upcoming') {
// 更新场次状态为正在秒杀
endedSession.status = 'ongoing';
// 重新计算结束时间倒计时
const now = new Date();
const endTime = new Date(endedSession.endTime);
const remainingMs = endTime.getTime() - now.getTime();
if (remainingMs > 0) {
const hours = Math.floor(remainingMs / (1000 * 60 * 60));
const minutes = Math.floor((remainingMs % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((remainingMs % (1000 * 60)) / 1000);
const totalSeconds = hours * 3600 + minutes * 60 + seconds;
// 更新倒计时显示
endedSession.countdown = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
// 重新启动倒计时
if (totalSeconds > 0) {
startCountdown(endedSessionId, totalSeconds);
}
console.log('场次开始,状态转换为正在秒杀:', endedSession);
}
} else if (endedSession && endedSession.status === 'ongoing') {
// 正在秒杀场次结束,标记为已结束
endedSession.status = 'ended';
// 如果当前场次不是最后一场,切换到下一场
if (currentIndex < sessions.length - 1) {
const nextSession = sessions[currentIndex + 1];
// 检查下一场是否已经开始或即将开始
if (nextSession.status === 'ongoing' || nextSession.status === 'upcoming') {
currentSessionIndex.value = currentIndex + 1;
console.log('自动切换到下一场:', nextSession);
}
}
}
};
// 初始化倒计时 // 初始化倒计时
const initCountdowns = () => { const initCountdowns = () => {
if (creditsSaleData.value.sessions && Array.isArray(creditsSaleData.value.sessions)) { if (creditsSaleData.value.sessions && Array.isArray(creditsSaleData.value.sessions)) {
// 检查是否全部结束
const allEnded = creditsSaleData.value.sessions.every(session => session.status === 'ended');
if (allEnded) {
return; // 全部结束,不需要倒计时
}
// 其他情况都需要倒计时
creditsSaleData.value.sessions.forEach(session => { creditsSaleData.value.sessions.forEach(session => {
if (session.status === 'ongoing') { if (session.status === 'ongoing' || session.status === 'upcoming') {
// 将倒计时字符串转换为秒数 // 将倒计时字符串转换为秒数
const timeParts = session.countdown.split(':'); const timeParts = session.countdown.split(':');
const hours = parseInt(timeParts[0]) || 0; const hours = parseInt(timeParts[0]) || 0;
...@@ -293,6 +401,9 @@ const mapSeckillDataToCreditsSale = (seckillData) => { ...@@ -293,6 +401,9 @@ const mapSeckillDataToCreditsSale = (seckillData) => {
return; return;
} }
// 保存活动ID
creditsSaleData.value.activityId = seckillData.data.id;
console.log('开始处理接口数据,configs长度:', seckillData.data.configs.length); console.log('开始处理接口数据,configs长度:', seckillData.data.configs.length);
const sessions = seckillData.data.configs.map((config, index) => { const sessions = seckillData.data.configs.map((config, index) => {
...@@ -364,7 +475,10 @@ const mapSeckillDataToCreditsSale = (seckillData) => { ...@@ -364,7 +475,10 @@ const mapSeckillDataToCreditsSale = (seckillData) => {
status, status,
countdown, countdown,
timeTags, timeTags,
goods goods,
sessionKey: config.sessionKey,
startTime: config.start,
endTime: config.end
}; };
}); });
...@@ -386,33 +500,9 @@ const mapSeckillDataToCreditsSale = (seckillData) => { ...@@ -386,33 +500,9 @@ const mapSeckillDataToCreditsSale = (seckillData) => {
creditsSaleData.value.sessions = sessions; creditsSaleData.value.sessions = sessions;
// 自动定位到正在秒杀的场次 // 智能定位场次逻辑
const ongoingSessions = sessions.filter(session => session.status === 'ongoing'); const targetIndex = getTargetSessionIndex(sessions);
if (ongoingSessions.length > 0) { currentSessionIndex.value = targetIndex;
// 如果有多个正在秒杀的场次,选择开始时间最早的
const earliestOngoingSession = ongoingSessions.reduce((earliest, current) => {
const getStartTimeFromTags = (session) => {
const timeTag = session.timeTags.find(tag => tag.includes('开始') && /^\d{2}:\d{2}开始$/.test(tag));
if (timeTag) {
const timeStr = timeTag.replace('开始', '');
const [hours, minutes] = timeStr.split(':').map(Number);
return hours * 60 + minutes;
}
return 0;
};
return getStartTimeFromTags(current) < getStartTimeFromTags(earliest) ? current : earliest;
});
// 找到最早场次的索引
const targetIndex = sessions.findIndex(session => session.id === earliestOngoingSession.id);
if (targetIndex !== -1) {
currentSessionIndex.value = targetIndex;
}
} else {
// 没有正在秒杀的场次,定位到第一个
currentSessionIndex.value = 0;
}
console.log('映射后的秒杀数据:', creditsSaleData.value); console.log('映射后的秒杀数据:', creditsSaleData.value);
console.log('当前选中场次索引:', currentSessionIndex.value); console.log('当前选中场次索引:', currentSessionIndex.value);
...@@ -421,7 +511,10 @@ const mapSeckillDataToCreditsSale = (seckillData) => { ...@@ -421,7 +511,10 @@ const mapSeckillDataToCreditsSale = (seckillData) => {
// 处理积分抢购点击事件 // 处理积分抢购点击事件
const handleCreditsSaleClick = (good) => { const handleCreditsSaleClick = (good) => {
console.log('点击抢购商品:', good); console.log('点击抢购商品:', good);
emit('credits-sale-click', good); // 获取当前活动ID和场次Key
const activityId = creditsSaleData.value.activityId;
const sessionKey = creditsSaleData.value.sessions[currentSessionIndex.value]?.sessionKey;
emit('credits-sale-click', { good, activityId, sessionKey });
}; };
// 创建防连点的点击处理函数 // 创建防连点的点击处理函数
......
This diff is collapsed.
...@@ -540,8 +540,9 @@ const isdebug = ref(false); ...@@ -540,8 +540,9 @@ const isdebug = ref(false);
// 处理积分抢购点击事件 // 处理积分抢购点击事件
const handleCreditsSaleClick = (good) => { const handleCreditsSaleClick = (params) => {
console.log('点击抢购商品:', good); const { good, activityId, sessionKey } = params;
console.log('点击抢购商品:', good, '活动ID:', activityId, '场次Key:', sessionKey);
// 检查库存 // 检查库存
if (good.stock <= 0) { if (good.stock <= 0) {
...@@ -567,10 +568,11 @@ const handleCreditsSaleClick = (good) => { ...@@ -567,10 +568,11 @@ const handleCreditsSaleClick = (good) => {
icon: 'none' icon: 'none'
}); });
// TODO: 添加跳转到商品详情页或购买页面的逻辑 // 构建跳转URL,添加activityId和sessionKey参数
const url = `/v3/goodDetail/goodDetail?gid=${good.id}&activityId=${activityId}&sessionKey=${sessionKey}`;
jump({ jump({
type: JumpType.INNER, type: JumpType.INNER,
url: `/v3/goodDetail/goodDetail?gid=${good.id}` url: url
}); });
}; };
......
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