25 Commits

Author SHA1 Message Date
no99 eac2b28dcc Merge branch 'milestone-20250722-抽奖' into milestone-20250722-众筹抽奖合并专用分支 4 weeks ago
no99 a3730c2f44 解决了当第一个奖品已经抽完,但是没有揭示的时候,可以直接揭示第二个奖品的问题 4 weeks ago
zhangjiahao d858ebcef0 Merge branch 'milestone-20250723-众筹' into milestone-20250722-众筹抽奖合并专用分支 4 weeks ago
zhangjiahao ed5c701407 助力成功动画2s改为1s 4 weeks ago
no99 0b45b72670 修改图片链接的变量名称 4 weeks ago
no99 0ff34d3ed7 Merge branch 'milestone-20250722-抽奖' into milestone-20250722-众筹抽奖合并专用分支 4 weeks ago
zhangjiahao 2f65a7baa2 更改状态 4 weeks ago
zhangjiahao cfc8afdef4 添加助力成功动画 4 weeks ago
Ethereal f6f878775f Merge branch 'wangyi/feature-20250710191445-抽奖' into milestone-20250722-抽奖 4 weeks ago
Ethereal fd1fe50618 优化卡牌字体大小,解决最后一个商品不能抽取的bug 4 weeks ago
宋杰 5292ead3bb Merge branch 'milestone-20250722-众筹抽奖合并专用分支' of http://39.101.133.168:8807/hongxilin/activityLink into milestone-20250722-众筹抽奖合并专用分支 4 weeks ago
宋杰 a37445dc47 剩余分钟数小于3时字体变成红色。 4 weeks ago
no99 e8891edb65 Merge branch 'milestone-20250722-抽奖' into milestone-20250722-众筹抽奖合并专用分支 4 weeks ago
no99 d6e099201d Merge branch 'hongxilin/feature-20250710175148-抽奖' into milestone-20250722-抽奖 4 weeks ago
no99 e2170b97e2 中奖进度条初始化不对的问题 4 weeks ago
no99 3b125e172e 修改获取中奖名单api 4 weeks ago
pangluotong d4259b9bcc Merge branch 'milestone-20250722-抽奖' into pangluotong/feature-20250712103401-抽奖 4 weeks ago
pangluotong 89313277af 修改了获奖名单bug,更改文字提醒样式 4 weeks ago
Ethereal 5e671550cf 继续优化奖品列表,查询全部 4 weeks ago
Ethereal 7c5c4d7ce6 Merge branch 'wangyi/feature-20250710191445-抽奖' into milestone-20250722-抽奖 4 weeks ago
Ethereal e3fa0f8a32 优化获奖名单 4 weeks ago
Ethereal 1638bd8c0a wy完成合并 4 weeks ago
Ethereal 2478651625 优化无商品时,还能继续抽奖的逻辑 4 weeks ago
pangluotong 077d7b97ac 弹窗改为文字提示,改变奖品列表长度 4 weeks ago
Ethereal f6bffc9c01 优化奖品列表高亮 4 weeks ago
  1. 2
      src/api/API.js
  2. BIN
      src/assets/img/zhongchou/助力成功.png
  3. 119
      src/views/choujiang/hxl-cj/cj.vue
  4. 57
      src/views/choujiang/index.vue
  5. 2
      src/views/choujiang/lottery/CardItem.vue
  6. 2
      src/views/choujiang/lottery/Lottery3D.vue
  7. 100
      src/views/choujiang/lottery/PrizePanel.vue
  8. 96
      src/views/zhongchou/index.vue

2
src/api/API.js

@ -24,7 +24,7 @@ export const getUserListApi = function (params) {
// 查询中奖名单
export const getGetPrizeUserListApi = function (params) {
return request({
url: `${APIurl}/admin/win/list`,
url: `${APIurl}/api/winUser/list`,
method: "POST",
data: params,
});

BIN
src/assets/img/zhongchou/助力成功.png

After

Width: 624  |  Height: 754  |  Size: 92 KiB

119
src/views/choujiang/hxl-cj/cj.vue

@ -11,12 +11,20 @@
<div class="leftBar">
<el-scrollbar id="prizeBar">
<ul class="prize-list">
<li v-for="item in prizes" :key="item.type" :id="`prize-item-${item.type}`" :class="['prize-item']"
@click="lookPrize(item)">
<div v-if="item.isLook" style="display: flex; width: 100%; height: 100%">
<li
v-for="item in prizes"
:key="item.type"
:id="`prize-item-${item.type}`"
:class="['prize-item']"
@click="lookPrize(item)"
>
<div
v-if="item.isLook"
style="display: flex; width: 100%; height: 100%"
>
<span></span><span></span><span></span><span></span>
<div class="prize-img">
<img :src="item.img" :alt="item.title" />
<img :src="item.imageUrl" :alt="item.title" />
</div>
<div class="prize-text">
<div class="prize-title">
@ -27,17 +35,27 @@
</div>
<div class="prize-count">
<div class="progress">
<div :id="`prize-bar-${item.type}`"
class="progress-bar progress-bar-danger progress-bar-striped active" style="width: 100%"></div>
<div
:id="`prize-bar-${item.type}`"
class="progress-bar progress-bar-danger progress-bar-striped active"
style="width: 100%"
></div>
</div>
<div :id="`prize-count-${item.type}`" class="prize-count-left">
<div
:id="`prize-count-${item.type}`"
class="prize-count-left"
>
{{ item.leftCount }}/{{ item.count }}
</div>
</div>
</div>
</div>
<div v-else style="display: flex; width: 100%; height: 100%">
<img src="../../../assets/img/待揭秘.png" alt="待揭秘" class="readyLook" />
<img
src="../../../assets/img/待揭秘.png"
alt="待揭秘"
class="readyLook"
/>
</div>
</li>
</ul>
@ -50,7 +68,12 @@
</div>
<div v-else>
<div class="dgetPrizeName">
<img src="../../../assets/img/展开.png" alt="展开" class="close" @click="closeGetPrize()" />
<img
src="../../../assets/img/展开.png"
alt="展开"
class="close"
@click="closeGetPrize()"
/>
<div class="tableHead">
<div class="tableHead1">HomilyID</div>
<div class="tableHead2">奖项</div>
@ -245,7 +268,7 @@ const closeGetPrize = () => {
};
//
const lookPrize = (item) => {
const lookPrize = async (item) => {
//
if (!joinLottery) {
addQipao("请先进入抽奖。");
@ -265,6 +288,7 @@ const lookPrize = (item) => {
item.isLook = true;
} else if (
!isLotting && //
currentPrize.value.isLook &&
currentPrize.value.leftCount == 0 && //
prizes.value[currentPrizeIndex - 1] == item //
) {
@ -293,6 +317,8 @@ const lookPrize = (item) => {
//
item.isLook = true;
}
await nextTick();
setPrizeData(currentPrizeIndex);
};
function setPrizeData(currentPrizeIndex, isInit) {
@ -323,7 +349,8 @@ function setPrizeData(currentPrizeIndex, isInit) {
}
}
// console.log("currentPrize", currentPrize);
console.log("count", count);
console.log("totalCount", totalCount);
let percent = (count / totalCount).toFixed(2);
if (elements.bar) {
@ -351,7 +378,7 @@ const initAll = async () => {
prizes.value = prizeList.data;
//
users.value = userList.data;
prizes.value.forEach((item, index) => {
prizes.value.forEach((item, index) => {
item.type = index;
item.count = item.amount;
item.leftCount = item.remainNum; //
@ -1648,7 +1675,6 @@ a {
}
@keyframes bounce1 {
0%,
100% {
transform: rotate(180deg) translateY(0);
@ -1660,7 +1686,6 @@ a {
}
@keyframes bounce2 {
0%,
100% {
transform: translateY(0);
@ -1696,11 +1721,13 @@ a {
width: 90%;
height: 3px;
border-radius: 150%;
background: linear-gradient(to right,
transparent 0%,
#d5291f 45%,
#d5291f 55%,
transparent 100%);
background: linear-gradient(
to right,
transparent 0%,
#d5291f 45%,
#d5291f 55%,
transparent 100%
);
position: absolute;
bottom: -10px;
}
@ -1838,30 +1865,36 @@ a {
}
.progress-bar-striped {
background-image: -webkit-linear-gradient(45deg,
rgba(255, 255, 255, 0.15) 25%,
transparent 25%,
transparent 50%,
rgba(255, 255, 255, 0.15) 50%,
rgba(255, 255, 255, 0.15) 75%,
transparent 75%,
transparent);
background-image: -o-linear-gradient(45deg,
rgba(255, 255, 255, 0.15) 25%,
transparent 25%,
transparent 50%,
rgba(255, 255, 255, 0.15) 50%,
rgba(255, 255, 255, 0.15) 75%,
transparent 75%,
transparent);
background-image: linear-gradient(45deg,
rgba(255, 255, 255, 0.15) 25%,
transparent 25%,
transparent 50%,
rgba(255, 255, 255, 0.15) 50%,
rgba(255, 255, 255, 0.15) 75%,
transparent 75%,
transparent);
background-image: -webkit-linear-gradient(
45deg,
rgba(255, 255, 255, 0.15) 25%,
transparent 25%,
transparent 50%,
rgba(255, 255, 255, 0.15) 50%,
rgba(255, 255, 255, 0.15) 75%,
transparent 75%,
transparent
);
background-image: -o-linear-gradient(
45deg,
rgba(255, 255, 255, 0.15) 25%,
transparent 25%,
transparent 50%,
rgba(255, 255, 255, 0.15) 50%,
rgba(255, 255, 255, 0.15) 75%,
transparent 75%,
transparent
);
background-image: linear-gradient(
45deg,
rgba(255, 255, 255, 0.15) 25%,
transparent 25%,
transparent 50%,
rgba(255, 255, 255, 0.15) 50%,
rgba(255, 255, 255, 0.15) 75%,
transparent 75%,
transparent
);
-webkit-background-size: 8px 8px;
background-size: 8px 8px;
}

57
src/views/choujiang/index.vue

@ -25,6 +25,12 @@
</div>
</div>
<div v-if="showPrizeExhaustedModal2" class="prize-exhausted-modal">
<div class="modal-content">
<p class="modal-text">该礼品已抽取完毕</p>
</div>
</div>
<!-- <UserList
:lucky-users="
dataManager.state.basicData.luckyUsers[
@ -56,6 +62,7 @@ const qipaoText = ref("");
const showQipao = ref(false);
const showPrizeExhaustedModal = ref(false);
const showPrizeExhaustedModal1 = ref(false);
const showPrizeExhaustedModal2 = ref(false);
// const lotteryState = ref('idle'); // idle, ready, rotating, result
@ -102,12 +109,14 @@ const lotteryEngine = useLotteryEngine(dataManager, {
onMounted(async () => {
isDisabled.value = true;
await dataManager.getBasicData();
await dataManager.getUsers();
setTimeout(() => {
isDisabled.value = false;
}, 4000);
}, 3800);
await dataManager.getBasicData();
await dataManager.getUsers();
// dataManager window 使
window.dataManager = dataManager;
@ -182,6 +191,20 @@ async function handleLotteryClick() {
break;
}
if (lastRevealed.value === 0 && dataManager.state.basicData.prizes[lastRevealed.value].remainNum === 0) {
// 0
// const currentPrize = dataManager.state.basicData.prizes[lastRevealed.value];
// if (currentPrize && currentPrize.remainNum === 0) {
showPrizeExhaustedModal2.value = true;
setTimeout(() => {
showPrizeExhaustedModal2.value = false;
}, 1000);
isDisabled.value = false;
break;
// }
}
console.log("lotteryState 变更前:", lotteryState.value, "-> rotating");
lotteryState.value = "rotating";
console.log("lotteryState 变更后:", lotteryState.value);
@ -327,30 +350,22 @@ function handleNextPrize() {
}
.modal-text {
position: fixed !important;
top: 300px;
left: 50% !important;
transform: translate(-50%, -50%) !important;
color: #ff0000;
font-size: 18px;
font-size: 50px;
font-weight: bold;
text-align: center;
margin: 0;
white-space: nowrap;
}
@keyframes fadeInOut {
0% {
opacity: 0;
transform: translateY(-20px);
}
20% {
opacity: 1;
transform: translateY(0);
}
80% {
opacity: 1;
transform: translateY(0);
}
100% {
opacity: 0;
transform: translateY(-20px);
}
0% { opacity: 0; }
20% { opacity: 1; }
80% { opacity: 1; }
100% { opacity: 0; }
}
</style>

2
src/views/choujiang/lottery/CardItem.vue

@ -173,7 +173,7 @@ onBeforeUnmount(() => {
/* ... */
}
.details {
font-size: 26px;
font-size: 24px;
color: white;
text-align: center;
display: flex;

2
src/views/choujiang/lottery/Lottery3D.vue

@ -571,7 +571,7 @@ function changeCard(cardIndex, user) {
const username = user.username || user[1] || "";
const company = user.company || user[2] || "PSST";
card.innerHTML = `<div style="font-size: 30px; font-weight: bold; color: #ffffff; text-align: center; display: flex; justify-content: center; align-items: center; width: 100%; height: 100%;">${jwcode}</div>`;
card.innerHTML = `<div style="font-size: 20px; font-weight: bold; color: #ffffff; text-align: center; display: flex; justify-content: center; align-items: center; width: 100%; height: 100%;">${jwcode}</div>`;
//
card.classList.add("prize");

100
src/views/choujiang/lottery/PrizePanel.vue

@ -1,6 +1,9 @@
<template>
<div v-if="showOne">
<div class="prize-panel-root">
<div v-if="showNotification" class="auto-hide-notification">
{{ notificationMessage }}
</div>
<div class="prize-panel-list" v-if="prizes && prizes.length">
<div
class="prize-panel-item"
@ -48,18 +51,11 @@
/>
</div>
</div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class="prize-panel-footer">
<div class="arrow-up" @click="openWinnerList"></div>
<button
ref="winnerBtnRef"
class="winner-btn"
@click="toggleWinnerList"
>
<button ref="winnerBtnRef" class="winner-btn" @click="openWinnerList">
获奖名单
</button>
</div>
@ -171,6 +167,17 @@ import { ref, computed, nextTick, watch, onMounted } from "vue";
import { useLotteryStore } from "../../../store/lottery";
import { useDataManager } from "../lottery/dataManager";
const showNotification = ref(false);
const notificationMessage = ref('');
//
const showAutoHideNotification = (message, duration = 1500) => {
notificationMessage.value = message;
showNotification.value = true;
setTimeout(() => {
showNotification.value = false;
}, duration);
};
const props = defineProps({
prizes: Array,
});
@ -237,8 +244,10 @@ function canRevealPrize(idx) {
//
function handleReveal(idx) {
//
if (idx !== nextRevealIdx.value) {
alert("请按顺序揭秘奖品!");
if (idx !== nextRevealIdx.value && !isRevealed(idx)) {
// alert("!");
showAutoHideNotification("请按顺序揭秘奖品!");
return;
}
if (idx === nextRevealIdx.value && canRevealPrize(idx)) {
@ -278,7 +287,8 @@ import { getGetPrizeUserListApi } from "../../../api/API";
const updateWinners = async () => {
try {
const response = await getGetPrizeUserListApi({
pageSize: 1000,
pageNum: 1,
});
console.log("updatePrizeList response", response);
fakeWinners.value = response.data.list;
@ -291,7 +301,10 @@ async function openWinnerList() {
// showWinnerList.value = true;
if (!showWinnerList.value) {
if (revealedCount.value === 0) {
alert("请先揭晓奖品,并抽奖!");
// alert(",");
showAutoHideNotification("请先揭晓奖品,并抽奖!");
}
// await updatePrizeList();
}
@ -319,6 +332,7 @@ async function toggleWinnerList() {
await updateWinners();
showWinnerList.value = !showWinnerList.value;
console.log(
"toggleWinnerList - showWinnerList:",
showWinnerList.value,
@ -329,7 +343,8 @@ async function toggleWinnerList() {
);
if (!showWinnerList.value) {
if (revealedCount.value === 0) {
alert("请先揭晓奖品,并抽奖!");
// alert(",");
showAutoHideNotification("请先揭晓奖品,并抽奖!");
}
}
@ -357,26 +372,37 @@ function getProgressPercent(prize) {
return Math.round((left / total) * 100);
}
// onMounted(() => {
// updateWinners();
// });
onMounted(() => {
updateWinners();
});
</script>
<style scoped>
.auto-hide-notification {
position: fixed;
top: 300px;
left: 50%;
transform: translateX(-50%);
color: #e61414;
padding: 8px 16px;
border-radius: 4px;
font-size: 50px;
z-index: 1000;}
.prize-panel-list {
position: relative;
background: none;
z-index: 10;
min-width: 300px;
max-width: 342px;
max-width: 362px;
text-align: left;
display: flex;
flex-direction: column;
gap: 18px;
height: 700px;
max-height: 700px;
overflow-x: hidden !important;
overflow-y: auto;
/* overflow-y: auto; */
padding-right: 10px;
padding-left: 10px;
scrollbar-width: thin;
scrollbar-color: #ffd283 rgba(255, 210, 131, 0.3); /* Firefox */
}
@ -386,6 +412,8 @@ function getProgressPercent(prize) {
z-index: 10;
min-width: 320px;
max-width: 342px;
padding-right: 10px;
padding-left: 10px;
text-align: left;
display: flex;
}
@ -464,17 +492,10 @@ function getProgressPercent(prize) {
color: #d84315;
font-weight: 500;
}
/* .prize-row-bottom {
background: linear-gradient(90deg, #ff9800 0%, #ff5722 100%);
background: #8a3500;
border-radius: 16px;
color: #fff;
font-size: 20px;
font-weight: bold;
padding: 2px 0 2px 0;
justify-content: center;
min-width: 80px;
} */
.prize-row-bottom {
/* margin-bottom: 8px; */
/* border: 1px solid #ea2b0a; */
}
.custom-arrow-icon {
font-size: 24px; /* 图标大小 */
color: #d84315; /* 图标颜色,使用项目主题橙色 */
@ -505,14 +526,14 @@ function getProgressPercent(prize) {
background: none;
z-index: 10;
min-width: 320px;
max-width: 342px;
max-width: 362px;
display: flex;
flex-direction: column;
}
.prize-panel-footer {
position: relative;
width: 100%;
/* width: 100%; */
display: flex;
flex-direction: column;
align-items: center;
@ -554,6 +575,7 @@ function getProgressPercent(prize) {
font-weight: bold;
cursor: pointer;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
outline: none;
}
.winner-modal-mask {
position: fixed;
@ -628,8 +650,8 @@ function getProgressPercent(prize) {
}
.progress-bar-bg {
position: relative;
width: 220px;
height: 28px;
width: 228px;
height: 30px;
background: #e9620e;
border-radius: 16px;
overflow: hidden;
@ -642,6 +664,7 @@ function getProgressPercent(prize) {
position: absolute;
left: 0;
top: 0;
/* width: 100%; */
height: 100%;
/* background: linear-gradient(90deg, #ff9800 0%, #8a3500 100%); */
background: #8a3500;
@ -682,9 +705,14 @@ function getProgressPercent(prize) {
.prize-panel-item.revealed-highlight {
/* border: 3px solid #ff9800; */
box-shadow: 0 0 16px 4px #ff9800aa;
transform: scale(1.05);
transform: scale(1.03);
z-index: 2;
transition: all 0.3s;
/* 确保放大的元素不被遮挡 */
position: relative;
/* margin: 8px 0; */
/* 为放大的元素留出空间 */
transform-origin: center center;
}
.prize-panel-item.disabled {

96
src/views/zhongchou/index.vue

@ -40,7 +40,7 @@
</div>
<!-- 美股剩余时间显示 -->
<div class="stock-info">
<div class="stock-info" :class="{ 'time-almost-up': isTimeAlmostUp }">
<h3>距美股实时数据</h3>
<h3>还剩{{ numberToChinese(usDisplayTime) }}分钟</h3>
</div>
@ -66,6 +66,13 @@
</div>
</div>
<!-- 助力成功提示 -->
<transition name="fade" appear>
<div class="boost-success-container" v-if="showBoostSuccess">
<img src="@/assets/img/zhongchou/助力成功.png" alt="助力成功" />
</div>
</transition>
<!-- 右侧港股区域 -->
<!-- <div class="stock-area right-area" @click="handleAreaClick('hk')"
:class="{ active: activeArea === 'hk', 'side': activeArea === 'us' }">
@ -251,7 +258,8 @@ const activeArea = ref(null)
const usBoostStatus = ref(false)
// const hkBoostStatus = ref(false)
const showRulesModal = ref(false)
//
const showBoostSuccess = ref(false)
// - marketTwoCount
const usRemainingTime = ref(15) // 15
// const hkRemainingTime = ref(6) //
@ -272,6 +280,11 @@ const usDisplayTime = computed(() => {
return Math.max(0, usRemainingTime.value)
})
// 3
const isTimeAlmostUp = computed(() => {
return usRemainingTime.value <= 3
})
// const hkDisplayTime = computed(() => {
// return Math.max(0, hkRemainingTime.value)
// })
@ -362,6 +375,14 @@ const handleBoostClick = async (area) => {
if (response.code === 200) {
console.log('美股助力成功:', response.message)
//
showBoostSuccess.value = true
//1s
setTimeout(() => {
showBoostSuccess.value = false
}, 1000)
//
await fetchActivity()
console.log('美股已助力状态:', usBoostStatus.value, '剩余时间:', usRemainingTime.value)
@ -372,7 +393,7 @@ const handleBoostClick = async (area) => {
console.error('美股助力请求失败:', error)
}
}
// ... existing code ...
}
const showRulesFunc = () => {
@ -679,6 +700,11 @@ const hideRules = () => {
flex-direction: column;
}
/* 剩余时间小于等于3分钟时的样式 */
.time-almost-up h3 {
color: #ff0000;
}
/* 股票信息标题样式 */
.stock-info h3 {
margin: 5px 0;
@ -1275,4 +1301,68 @@ const hideRules = () => {
.close-btn:hover {
transform: scale(1.05);
}
/* 助力成功提示样式 */
.boost-success-container {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 1000;
/* 确保显示在最上层 */
pointer-events: none;
/* 允许点击穿透 */
}
.boost-success-container img {
max-width: 300px;
height: auto;
filter: drop-shadow(0 0 10px rgba(255, 255, 255, 0.5));
}
/* 增强的淡入淡出动画 */
.fade-enter-active {
animation: bounce-in 0.6s ease-out;
}
.fade-leave-active {
animation: bounce-out 0.5s ease-in;
}
@keyframes bounce-in {
0% {
opacity: 0;
transform: translate(-50%, -50%) scale(0.5);
}
50% {
opacity: 1;
transform: translate(-50%, -50%) scale(1.05);
}
70% {
transform: translate(-50%, -50%) scale(0.95);
}
100% {
transform: translate(-50%, -50%) scale(1);
}
}
@keyframes bounce-out {
0% {
opacity: 1;
transform: translate(-50%, -50%) scale(1);
}
20% {
opacity: 1;
transform: translate(-50%, -50%) scale(1.05);
}
100% {
opacity: 0;
transform: translate(-50%, -50%) scale(0.5);
}
}
</style>
Loading…
Cancel
Save