Browse Source

Merge branch 'milestone-20250722-众筹抽奖合并专用分支' of http://39.101.133.168:8807/hongxilin/activityLink into songjie/feature-20250710175416-众筹项目7月23提测

milestone-20250723-众筹
宋杰 3 weeks ago
parent
commit
969e709fae
  1. 1
      README.md
  2. 8
      package-lock.json
  3. 1
      package.json
  4. BIN
      src/assets/img/zhongchou/助力已达标.png
  5. 84
      src/views/choujiang/hxl-cj/cj.vue
  6. 8
      src/views/choujiang/index.vue
  7. 2
      src/views/choujiang/lottery/Lottery3D.vue
  8. 2
      src/views/choujiang/lottery/PrizePanel.vue
  9. 79
      src/views/zhongchou/index.vue

1
README.md

@ -10,3 +10,4 @@ npm install axios
npm install element-plus --save npm install element-plus --save
npm install pinia npm install pinia
npm install three npm install three
c 安装 lodash 组件,解决数据处理问题

8
package-lock.json

@ -13,6 +13,7 @@
"axios": "^1.10.0", "axios": "^1.10.0",
"dayjs": "^1.11.13", "dayjs": "^1.11.13",
"element-plus": "^2.10.3", "element-plus": "^2.10.3",
"lodash": "^4.17.21",
"pinia": "^3.0.3", "pinia": "^3.0.3",
"pinia-plugin-persistedstate": "^4.4.1", "pinia-plugin-persistedstate": "^4.4.1",
"three": "^0.178.0", "three": "^0.178.0",
@ -1987,8 +1988,9 @@
}, },
"node_modules/lodash": { "node_modules/lodash": {
"version": "4.17.21", "version": "4.17.21",
"resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
"resolved": "https://mirrors.huaweicloud.com/repository/npm/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"license": "MIT"
}, },
"node_modules/lodash-es": { "node_modules/lodash-es": {
"version": "4.17.21", "version": "4.17.21",
@ -4055,7 +4057,7 @@
}, },
"lodash": { "lodash": {
"version": "4.17.21", "version": "4.17.21",
"resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz",
"resolved": "https://mirrors.huaweicloud.com/repository/npm/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
}, },
"lodash-es": { "lodash-es": {

1
package.json

@ -16,6 +16,7 @@
"axios": "^1.10.0", "axios": "^1.10.0",
"dayjs": "^1.11.13", "dayjs": "^1.11.13",
"element-plus": "^2.10.3", "element-plus": "^2.10.3",
"lodash": "^4.17.21",
"pinia": "^3.0.3", "pinia": "^3.0.3",
"pinia-plugin-persistedstate": "^4.4.1", "pinia-plugin-persistedstate": "^4.4.1",
"three": "^0.178.0", "three": "^0.178.0",

BIN
src/assets/img/zhongchou/助力已达标.png

After

Width: 402  |  Height: 88  |  Size: 13 KiB

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

@ -120,7 +120,12 @@
<div class="btn">{{ cjText }}</div> <div class="btn">{{ cjText }}</div>
</div> </div>
<div v-else> <div v-else>
<div id="lottery" ref="lotteryRef" @click="lotteryBtn()" class="btn">
<div
id="lottery"
ref="lotteryRef"
@click="throttledLotteryBtn()"
class="btn"
>
{{ cjText }} {{ cjText }}
</div> </div>
</div> </div>
@ -142,6 +147,7 @@ import { TrackballControls } from "../../../utils/TrackballControls.js";
import TWEEN from "@tweenjs/tween.js"; import TWEEN from "@tweenjs/tween.js";
import worldcup from "../../../assets/worldcup.mp3"; import worldcup from "../../../assets/worldcup.mp3";
import dong from "../../../assets/dong.mp3"; import dong from "../../../assets/dong.mp3";
import _ from "lodash";
import { import {
getPrizeListApi, getPrizeListApi,
@ -507,6 +513,11 @@ const initAll = async () => {
}; };
const initCards = () => { const initCards = () => {
const screenWidth = window.innerWidth;
const isLaptop = screenWidth < 1600; //
const baseSpacingX = isLaptop ? 120 : 140;
const baseSpacingY = isLaptop ? 150 : 180;
let member = users.value.slice(), let member = users.value.slice(),
showCards = [], showCards = [],
length = member.length; length = member.length;
@ -514,9 +525,14 @@ const initCards = () => {
let isBold = false; let isBold = false;
let index = 0; let index = 0;
let totalMember = member.length; let totalMember = member.length;
// let position = {
// x: (140 * COLUMN_COUNT - 20) / 2,
// y: (180 * ROW_COUNT - 20) / 2,
// };
let position = { let position = {
x: (140 * COLUMN_COUNT - 20) / 2,
y: (180 * ROW_COUNT - 20) / 2,
x: (baseSpacingX * COLUMN_COUNT - 20) / 2,
y: (baseSpacingY * ROW_COUNT - 20) / 2,
}; };
camera = new THREE.PerspectiveCamera( camera = new THREE.PerspectiveCamera(
@ -542,9 +558,17 @@ const initCards = () => {
threeDCards.push(object); threeDCards.push(object);
// //
// initCards
const cardSpacingX = isLaptop ? 130 : 155;
const cardSpacingY = isLaptop ? 160 : 195;
var object = new THREE.Object3D(); var object = new THREE.Object3D();
object.position.x = j * 155 - position.x;
object.position.y = -(i * 195) + position.y;
// object.position.x = j * 155 - position.x;
// object.position.y = -(i * 195) + position.y;
// 使
object.position.x = j * cardSpacingX - position.x;
object.position.y = -(i * cardSpacingY) + position.y;
targets.table.push(object); targets.table.push(object);
index++; index++;
} }
@ -587,9 +611,10 @@ const initCards = () => {
// //
let joinLottery = false; let joinLottery = false;
// //
const enterLottery = () => {
const enterLottery = async () => {
joinLottery = true; joinLottery = true;
removeHighlight(); removeHighlight();
await nextTick();
// rotate = !rotate; // rotate = !rotate;
rotate = true; rotate = true;
switchScreen("lottery"); switchScreen("lottery");
@ -653,11 +678,14 @@ const createCard = (user, isBold, id) => {
return element; return element;
}; };
function removeHighlight() {
const removeHighlight = async () => {
document.querySelectorAll(".highlight").forEach((node) => { document.querySelectorAll(".highlight").forEach((node) => {
node.classList.remove("highlight");
console.log(node.id);
node.className = "";
node.classList.add("element");
node.style.backgroundColor = "rgb(255,170,22)";
}); });
}
};
function addHighlight() { function addHighlight() {
document.querySelectorAll(".lightitem").forEach((node) => { document.querySelectorAll(".lightitem").forEach((node) => {
@ -1078,7 +1106,7 @@ const lotteryBtn = () => {
// console.log("isLotting", isLotting); // console.log("isLotting", isLotting);
// console.log("currentPrize.value", currentPrize.value); // console.log("currentPrize.value", currentPrize.value);
if (isLotting) { if (isLotting) {
stopLottery();
throttledStopLottery();
return; return;
} }
@ -1132,9 +1160,10 @@ const lotteryBtn = () => {
const text = "正在抽取[" + currentPrize.value.prizeName + "],调整好姿势"; const text = "正在抽取[" + currentPrize.value.prizeName + "],调整好姿势";
// addQipao(text); // addQipao(text);
}; };
/**
* 抽奖
*/
const throttledLotteryBtn = _.throttle(lotteryBtn, 1000, {
trailing: false,
});
const lottery = () => { const lottery = () => {
rotateBall().then(() => { rotateBall().then(() => {
@ -1174,6 +1203,10 @@ const stopLottery = () => {
playDongAudio(); playDongAudio();
}; };
const throttledStopLottery = _.throttle(stopLottery, 1000, {
trailing: false,
});
const changePrize = async () => { const changePrize = async () => {
let type = currentPrize.value.type; let type = currentPrize.value.type;
@ -1216,13 +1249,15 @@ function changeSelectedCard(cardIndex, user) {
/** /**
* 切换名牌背景 * 切换名牌背景
*/ */
function changeBackground(cardIndex, color) {
const changeBackground = async (cardIndex) => {
let card = threeDCards[cardIndex].element; let card = threeDCards[cardIndex].element;
// card.style.backgroundColor = // card.style.backgroundColor =
// color || "rgba(255,170,22," + (Math.random() * 0.7 + 0.25) + ")"; // color || "rgba(255,170,22," + (Math.random() * 0.7 + 0.25) + ")";
card.style.backgroundColor = color || "rgba(255,170,22,1)";
card.style.border = "2px solid rgba(255, 255, 255, 1)";
}
card.style.backgroundColor = "rgb(255,170,22) !important";
card.style.border = "2px solid rgb(255, 255, 255)";
// await nextTick();
};
/** /**
* 随机切换背景和人员信息 * 随机切换背景和人员信息
@ -1246,7 +1281,7 @@ function shineCard() {
continue; continue;
} }
changeBackground(cardIndex);
// changeBackground(cardIndex);
changeCard(cardIndex, users.value[index]); changeCard(cardIndex, users.value[index]);
} }
}, 500); }, 500);
@ -1279,7 +1314,6 @@ function onWindowResize() {
onMounted(async () => { onMounted(async () => {
initAll(); initAll();
window.addEventListener("resize", onWindowResize, false); window.addEventListener("resize", onWindowResize, false);
}); });
</script> </script>
@ -1389,8 +1423,8 @@ a {
} }
.element { .element {
width: 15vh;
height: 19vh;
width: 7.5vw;
height: 18.5vh;
/* box-shadow: 0 0 12px rgba(0, 255, 255, 0.5); */ /* box-shadow: 0 0 12px rgba(0, 255, 255, 0.5); */
border: 1px solid rgba(127, 255, 255, 0.25); border: 1px solid rgba(127, 255, 255, 0.25);
text-align: center; text-align: center;
@ -1423,11 +1457,11 @@ button {
height: 70px; height: 70px;
color: #fff; color: #fff;
border: 0; border: 0;
font-size: 2.5vh;
font-size: 20px;
font-weight: bold; font-weight: bold;
cursor: pointer; cursor: pointer;
text-align: center; text-align: center;
padding-top: 5px;
padding-top: 12px;
} }
.highlight { .highlight {
@ -1521,7 +1555,7 @@ button {
justify-content: center; justify-content: center;
flex-wrap: nowrap; flex-wrap: nowrap;
/* color: rgba(127, 255, 255, 0.75); */ /* color: rgba(127, 255, 255, 0.75); */
width: 30vh;
width: 29vh;
height: 9.5vh; height: 9.5vh;
box-sizing: border-box; box-sizing: border-box;
transition: transform 1s ease-in; transition: transform 1s ease-in;
@ -2005,7 +2039,7 @@ button {
} }
.shine.prize-item { .shine.prize-item {
/* width: 24vh; */
/* width: 29.5vh; */
margin: 1.2vh 0; margin: 1.2vh 0;
} }

8
src/views/choujiang/index.vue

@ -333,9 +333,10 @@ async function handleLotteryClick() {
break; break;
case "rotating": case "rotating":
setTimeout(() => { setTimeout(() => {
isDisabled.value = false; isDisabled.value = false;
}, 2000);
}, 2700);
// toggleMusic(); // toggleMusic();
@ -344,13 +345,12 @@ async function handleLotteryClick() {
await lottery3DRef.value?.rotateBallStop?.(); await lottery3DRef.value?.rotateBallStop?.();
toggleMusic(); toggleMusic();
playMusic1(); playMusic1();
lotteryState.value = "result";
await lotteryEngine.executeLottery(); await lotteryEngine.executeLottery();
await nextTick(); await nextTick();
showLotteryQipao(); showLotteryQipao();
console.log("lotteryState 变更前:", lotteryState.value, "-> idle"); console.log("lotteryState 变更前:", lotteryState.value, "-> idle");
lotteryState.value = "result";
console.log("lotteryState 变更后:", lotteryState.value); console.log("lotteryState 变更后:", lotteryState.value);
@ -414,7 +414,7 @@ function handleNextPrize() {
overflow: hidden; overflow: hidden;
/* 添加背景图片 */ /* 添加背景图片 */
background: url("../../assets/bg@2x.png") ; background: url("../../assets/bg@2x.png") ;
background-size: 1920px 980px;
background-size: 100% 100%;
} }
/* 透明弹窗样式 */ /* 透明弹窗样式 */

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

@ -756,7 +756,7 @@ onMounted(async () => {
const length = member.length; const length = member.length;
const showTable = true; const showTable = true;
const position = { const position = {
x: (100 * config.COLUMN_COUNT - 20) / 2,
x: (115 * config.COLUMN_COUNT - 20) / 2,
y: (120 * config.ROW_COUNT - 20) / 2, y: (120 * config.ROW_COUNT - 20) / 2,
}; };
createCards(member, length, showTable, position, config); // 3. createCards(member, length, showTable, position, config); // 3.

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

@ -147,7 +147,7 @@
> >
<!-- <span>{{ user.id }}</span> - <span>{{ user.name }}</span> - --> <!-- <span>{{ user.id }}</span> - <span>{{ user.name }}</span> - -->
<span>{{ user.jwcode }}</span> <span>{{ user.jwcode }}</span>
<span>{{ user.prizeName }}</span>
<span>{{ user.gradeName }}</span>
</li> </li>
</ul> </ul>
<!-- 分页控件 --> <!-- 分页控件 -->

79
src/views/zhongchou/index.vue

@ -41,14 +41,21 @@
<!-- 美股剩余时间显示 --> <!-- 美股剩余时间显示 -->
<div class="stock-info" :class="{ 'time-almost-up': isTimeAlmostUp }"> <div class="stock-info" :class="{ 'time-almost-up': isTimeAlmostUp }">
<template v-if="!isCompleted">
<h3>{{ marketName }}实时数据</h3> <h3>{{ marketName }}实时数据</h3>
<h3>还剩{{ numberToChinese(usDisplayTime) }}分钟</h3> <h3>还剩{{ numberToChinese(usDisplayTime) }}分钟</h3>
</template>
<template v-else>
<h3>{{ marketName }}实时数据</h3>
<h3> 助力成功</h3>
</template>
</div> </div>
</div> </div>
</div> </div>
<!-- 美股助力按钮和底座 --> <!-- 美股助力按钮和底座 -->
<div class="boost-section"> <div class="boost-section">
<div class="boost-btn us-boost-btn" :class="{ 'boosted': usBoostStatus }"
<div class="boost-btn us-boost-btn"
:class="{ 'boosted': usBoostStatus && !isCompleted, 'completed': isCompleted }"
@click.stop="handleBoostClick('us')"></div> @click.stop="handleBoostClick('us')"></div>
<div class="base-image"> <div class="base-image">
<img src="@/assets/img/zhongchou/底座.png" alt="底座" /> <img src="@/assets/img/zhongchou/底座.png" alt="底座" />
@ -132,7 +139,7 @@
<script setup> <script setup>
import { addRecordAPI, getActivity1API } from '../../api/zhongchouApi' import { addRecordAPI, getActivity1API } from '../../api/zhongchouApi'
import { ref, computed, onMounted, nextTick, watch } from 'vue' import { ref, computed, onMounted, nextTick, watch } from 'vue'
const isCompleted = ref(false) // 1500
// //
const activityPeriod = ref('加载中...') const activityPeriod = ref('加载中...')
// IDID // IDID
@ -192,25 +199,33 @@ async function fetchActivity() {
const totalPeople = 1500 // 1500 const totalPeople = 1500 // 1500
const currentCount = item.marketCount || 0 // const currentCount = item.marketCount || 0 //
// (0-100)
const progressPercent = Math.min((currentCount / totalPeople) * 100, 100)
//
if (currentCount >= totalPeople) {
isCompleted.value = true //
usRemainingTime.value = 0 // 0
} else {
isCompleted.value = false
// - 151001
const initialTime = 15 // 15
const hundredsCount = Math.floor(currentCount / 100) // 100
const remainingTime = Math.max(0, initialTime - hundredsCount) // 1001
// (15100%)
const usedTime = (progressPercent / 100) * 15
const remainingTime = Math.max(0, 15 - usedTime)
usRemainingTime.value = remainingTime
}
usRemainingTime.value = Math.round(remainingTime)
console.log(`${marketName.value}助力人数: ${currentCount}/${totalPeople}, 进度: ${progressPercent.toFixed(1)}%, 剩余时间: ${remainingTime.toFixed(1)}分钟`)
// console.log(`${marketName.value}: ${currentCount}/${totalPeople}, : ${currentCount >= totalPeople ? '100' : progressPercent.toFixed(1)}%, : ${usRemainingTime.value}, : ${isCompleted.value}`)
// //
nextTick(() => { nextTick(() => {
updateProgressDisplay() updateProgressDisplay()
}) })
} }
} }
} else { } else {
console.error('获取活动失败:', response.message) console.error('获取活动失败:', response.message)
activityPeriod.value = '获取失败'
activityPeriod.value = response.message
} }
} catch (error) { } catch (error) {
console.error('请求错误:', error) console.error('请求错误:', error)
@ -259,7 +274,7 @@ const showRulesModal = ref(false)
// //
const showBoostSuccess = ref(false) const showBoostSuccess = ref(false)
// - marketTwoCount // - marketTwoCount
const marketName = ref('美股') // API
const marketName = ref() // API
const usRemainingTime = ref(15) // 15 const usRemainingTime = ref(15) // 15
// const hkRemainingTime = ref(6) // // const hkRemainingTime = ref(6) //
const usTotalTime = ref(15) // 15 const usTotalTime = ref(15) // 15
@ -359,11 +374,16 @@ onMounted(() => {
// } // }
const handleBoostClick = async (area) => { const handleBoostClick = async (area) => {
// 1500
if (isCompleted.value) {
return;
}
if (area === 'us' && !usBoostStatus.value) { if (area === 'us' && !usBoostStatus.value) {
try { try {
// IDID // IDID
if (!activityId.value || !usMarketId.value) { if (!activityId.value || !usMarketId.value) {
console.error('活动ID或市场ID未获取,请先获取活动数据') console.error('活动ID或市场ID未获取,请先获取活动数据')
await fetchActivity()
return return
} }
@ -382,15 +402,15 @@ const handleBoostClick = async (area) => {
setTimeout(() => { setTimeout(() => {
showBoostSuccess.value = false showBoostSuccess.value = false
}, 1000) }, 1000)
//
await fetchActivity()
console.log(`${marketName.value}已助力状态:`, usBoostStatus.value, '剩余时间:', usRemainingTime.value)
} else { } else {
console.error(`${marketName.value}助力失败:`, response.message) console.error(`${marketName.value}助力失败:`, response.message)
} }
} catch (error) { } catch (error) {
console.error(`${marketName.value}助力请求失败:`, error) console.error(`${marketName.value}助力请求失败:`, error)
} finally {
//
await fetchActivity()
console.log(`${marketName.value}已助力状态:`, usBoostStatus.value, '剩余时间:', usRemainingTime.value)
} }
} }
} }
@ -833,6 +853,23 @@ const hideRules = () => {
background-image: url('@/assets/img/zhongchou/美股已助力.png'); background-image: url('@/assets/img/zhongchou/美股已助力.png');
} }
/* 助力完成状态 - 当达到1500人时使用 */
.us-boost-btn.completed {
background-image: url('@/assets/img/zhongchou/助力已达标.png');
cursor: not-allowed;
/* 禁用鼠标指针 */
pointer-events: none;
/* 完全禁用鼠标事件 */
}
/* 修改悬浮效果,排除完成状态的按钮 */
.boost-btn:not(.completed):hover {
background-size: 110%;
}
/* 移除原有的通用悬浮效果 */
.boost-btn:hover {
/* 移除此样式或注释掉 */
}
/* 港股助力按钮 */ /* 港股助力按钮 */
/* .hk-boost-btn { /* .hk-boost-btn {
background-image: url('@/assets/img/zhongchou/助力港股.png'); background-image: url('@/assets/img/zhongchou/助力港股.png');
@ -1275,17 +1312,21 @@ const hideRules = () => {
.rules-list { .rules-list {
width: 100%; width: 100%;
line-height: 1.6; /* 增加行高 */
line-height: 1.6;
/* 增加行高 */
margin-top: 10%; margin-top: 10%;
margin-left: 10%; /* 减少左边距 */
padding-right: 5%; /* 添加右边距 */
margin-left: 10%;
/* 减少左边距 */
padding-right: 5%;
/* 添加右边距 */
} }
.rules-list p { .rules-list p {
margin: 10px 0; margin: 10px 0;
font-size: 16px; font-size: 16px;
color: #fff; color: #fff;
font-family: 'Microsoft YaHei', 'PingFang SC', sans-serif; /* 使用更清晰的中文字体 */
font-family: 'Microsoft YaHei', 'PingFang SC', sans-serif;
/* 使用更清晰的中文字体 */
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
line-height: 1.7; line-height: 1.7;
} }

Loading…
Cancel
Save