Browse Source

7.17推送,王毅更改抽奖卡牌,庞罗统更改奖品列表

songtongtong/feature-20250717104937-众筹
Ethereal 1 month ago
parent
commit
35cec973a1
  1. 614
      package-lock.json
  2. 2
      package.json
  3. 588
      src/assets/PrizePanel1.vue
  4. 6
      src/views/choujiang/index.vue
  5. 87
      src/views/choujiang/lottery/CardItem.vue
  6. 428
      src/views/choujiang/lottery/Lottery3D.vue
  7. 252
      src/views/choujiang/lottery/PrizePanel.vue
  8. 78
      src/views/choujiang/lottery/dataManager.js

614
package-lock.json
File diff suppressed because it is too large
View File

2
package.json

@ -9,10 +9,12 @@
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"@tweenjs/tween.js": "^18.6.4",
"@vitejs/plugin-vue": "^4.6.2", "@vitejs/plugin-vue": "^4.6.2",
"axios": "^1.10.0", "axios": "^1.10.0",
"element-plus": "^2.10.3", "element-plus": "^2.10.3",
"pinia": "^3.0.3", "pinia": "^3.0.3",
"three": "^0.150.1",
"vite": "^4.5.3", "vite": "^4.5.3",
"vue": "^3.5.17", "vue": "^3.5.17",
"vue-router": "^4.5.1" "vue-router": "^4.5.1"

588
src/assets/PrizePanel1.vue

@ -0,0 +1,588 @@
<template>
<div class="prize-panel-root">
<div class="prize-panel-list" v-if="prizes && prizes.length" :style="containerStyle">
<div
class="prize-panel-item"
v-for="(prize, idx) in prizes"
:key="prize.type || idx"
:class="{
'revealed-highlight': idx === lastRevealedIdx,
'winner-mode-highlight': showWinnerList && idx === lastRevealedIdx
}"
@click="showWinnerList ? null : handleReveal(idx)"
:style="{ cursor: showWinnerList ? 'default' : 'pointer' }"
:ref="el => setPrizeRef(el, idx)"
v-show="!shouldHideOtherPrizes || idx === lastRevealedIdx"
>
<div v-if="isRevealed(idx)" class="prize-card">
<div class="prize-img-wrap">
<img class="prize-img" :src="prize.img" :alt="prize.title" />
</div>
<div class="prize-info">
<div class="prize-row prize-row-top">
<span class="prize-level">{{ prize.title }}</span>
<span class="prize-name">{{ prize.text }}</span>
</div>
<div class="prize-row prize-row-bottom">
<div class="progress-bar-bg">
<div
class="progress-bar-fill"
:style="{ width:getProgressPercent(prize) + '%' }"
></div>
<span class="progress-bar-text">
{{ prize.count-getLeftCount(prize) }}/{{ prize.count }}
</span>
</div>
</div>
</div>
</div>
<div v-else class="prize-card prize-card-mask">
<img src="../../../assets/daijiemi.png" alt="待揭秘" class="prize-mask-img" />
</div>
</div>
<!-- 隐藏占位div -->
<div v-show="!shouldHideOtherPrizes"></div>
<div v-show="!shouldHideOtherPrizes"></div>
<div v-show="!shouldHideOtherPrizes"></div>
<div v-show="!shouldHideOtherPrizes"></div>
<!-- 动态定位的获奖名单按钮 -->
<div
class="prize-panel-footer"
:class="{ 'winner-mode': shouldHideOtherPrizes }"
:style="winnerBtnStyle"
>
<div class="arrow-up" @click="openWinnerList"></div>
<button ref="winnerBtnRef" class="winner-btn" @click="toggleWinnerList">
{{ showWinnerList ? '关闭名单' : '获奖名单' }}
</button>
<div
v-if="showWinnerList"
class="winner-modal-mask"
@click="closeWinnerList"
>
<div
class="winner-modal"
:style="{ position: 'absolute', left: modalLeft + 'px', top: modalTop + 'px' }"
@click.stop
>
<div class="winner-modal-header">
<div class="winner-modal-title">Homily ID</div>
<div class="winner-modal-close" @click="closeWinnerList">×</div>
</div>
<ul class="winner-list">
<li v-for="(user, idx) in fakeWinners" :key="idx">
<!-- <span>{{ user.id }}</span> - <span>{{ user.name }}</span> - -->
<span>{{ user.id }}</span>
<span>{{ user.prize }}</span>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed, nextTick, watch } from "vue";
const props = defineProps({
prizes: Array,
});
//
const revealedCount = ref(0);
//
const lastRevealedIdx = ref(-1);
//
const prizeRefs = ref([]);
//
const winnerBtnStyle = ref({
position: 'absolute',
left: '0',
bottom: '0',
width: '100%'
});
//
const containerStyle = computed(() => {
if (shouldHideOtherPrizes.value) {
return {
justifyContent: 'flex-start',
alignItems: 'flex-start',
paddingTop: '20px'
};
}
return {};
});
//
function setPrizeRef(el, idx) {
if (el) {
prizeRefs.value[idx] = el;
}
}
//
const isRevealed = idx => idx >= (props.prizes?.length || 0) - revealedCount.value;
// index
const nextRevealIdx = computed(() => (props.prizes?.length || 0) - revealedCount.value - 1);
//
function handleReveal(idx) {
if (idx === nextRevealIdx.value) {
revealedCount.value++;
lastRevealedIdx.value = idx; //
}
}
//
function getLeftCount(prize) {
// type dataManager.state.basicData.luckyUsers
// luckyUsers 访
// window.dataManager
let luckyUsers =
(window.dataManager && window.dataManager.state.basicData.luckyUsers) || {};
let got = luckyUsers[prize.type]?.length || 0;
return prize.count - got;
}
//
const showWinnerList = ref(false);
const fakeWinners = ref([
{ id: "90044065", name: "张三", prize: "六等奖" },
{ id: "90044066", name: "李四", prize: "六等奖" },
{ id: "90044067", name: "王五", prize: "六等奖" },
{ id: "90044068", name: "赵六", prize: "六等奖" },
{ id: "90044069", name: "小明", prize: "六等奖" },
]);
//
const shouldHideOtherPrizes = computed(() => {
return showWinnerList.value && lastRevealedIdx.value >= 0;
});
//
function positionWinnerBtn() {
if (lastRevealedIdx.value >= 0 && prizeRefs.value[lastRevealedIdx.value]) {
const highlightedPrize = prizeRefs.value[lastRevealedIdx.value];
//
if (shouldHideOtherPrizes.value) {
const rect = highlightedPrize.getBoundingClientRect();
const containerRect = highlightedPrize.parentElement.getBoundingClientRect();
//
const relativeTop = rect.bottom - containerRect.top + 18; // 18px
winnerBtnStyle.value = {
position: 'absolute',
left: '0',
top: relativeTop + 'px',
width: '100%',
zIndex: '20'
};
} else {
//
winnerBtnStyle.value = {
position: 'absolute',
left: '0',
bottom: '0',
width: '100%'
};
}
} else {
//
winnerBtnStyle.value = {
position: 'absolute',
left: '0',
bottom: '0',
width: '100%'
};
}
}
function openWinnerList() {
showWinnerList.value = true;
//
if (lastRevealedIdx.value >= 0) {
nextTick(() => {
positionWinnerBtn();
});
} else {
//
winnerBtnStyle.value = {
position: 'absolute',
left: '0',
bottom: '0',
width: '100%'
};
}
}
function closeWinnerList() {
showWinnerList.value = false;
//
nextTick(() => {
winnerBtnStyle.value = {
position: 'absolute',
left: '0',
bottom: '0',
width: '100%'
};
});
}
const winnerBtnRef = ref(null);
const modalLeft = ref(0);
const modalTop = ref(0);
function toggleWinnerList() {
showWinnerList.value = !showWinnerList.value;
if (showWinnerList.value) {
nextTick(() => {
const btn = winnerBtnRef.value;
if (btn) {
const rect = btn.getBoundingClientRect();
modalLeft.value = rect.left-22;
modalTop.value = rect.bottom + 20; // 4px
}
});
}
}
//
watch(lastRevealedIdx, () => {
nextTick(() => {
//
if (lastRevealedIdx.value >= 0 && showWinnerList.value) {
positionWinnerBtn();
} else if (lastRevealedIdx.value >= 0) {
//
winnerBtnStyle.value = {
position: 'absolute',
left: '0',
bottom: '0',
width: '100%'
};
}
});
});
function getProgressPercent(prize) {
const total = prize.count || 1;
const left = getLeftCount(prize);
const got = total - left;
return Math.round((got / total) * 100);
}
</script>
<style scoped>
.prize-panel-list {
position: absolute;
top: 20px;
left: 20px;
background: none;
z-index: 10;
min-width: 320px;
text-align: left;
display: flex;
flex-direction: column;
gap: 18px;
/* 新增:支持flexbox排序 */
align-items: flex-start;
/* 新增:支持滚动和定位 */
max-height: calc(100vh - 40px);
/* overflow-y: auto; */
/* 新增:当显示获奖名单时的特殊样式 */
transition: all 0.3s ease;
}
.prize-panel-item {
background: #ffd283;
border-radius: 6px 6px 6px 6px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
display: flex;
align-items: center;
min-width: 300px;
transition: opacity 0.3s ease, transform 0.3s ease;
}
.prize-card {
display: flex;
align-items: center;
width: 100%;
padding: 10px 18px;
}
.prize-img-wrap {
width: 64px;
height: 64px;
border-radius: 50%;
background: #fff;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
margin-right: 18px;
border: 2px solid #fff3e0;
}
.prize-img {
width: 60px;
height: 60px;
object-fit: contain;
}
.prize-info {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
}
.prize-row {
display: flex;
align-items: center;
background: #ffffff;
border-radius: 93px 93px 93px 93px;
}
.prize-row-top {
margin-bottom: 8px;
}
.prize-level {
background: linear-gradient(90deg, #ff9800 0%, #ff5722 100%);
color: #fff;
border-radius: 15.71px 15.71px 15.71px 15.71px;
padding: 2px 18px;
font-size: 18px;
font-weight: bold;
margin-right: 12px;
}
.prize-name {
font-size: 18px;
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-count {
font-size: 20px;
font-weight: bold;
}
.prize-divider {
margin: 0 4px;
font-size: 20px;
}
.prize-total {
font-size: 20px;
font-weight: bold;
}
/* 新增:获奖名单按钮容器样式调整 */
.prize-panel-footer {
position: absolute;
left: 0;
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
z-index: 20;
transition: all 0.3s ease;
/* 移除 bottom 定位,改为动态定位 */
}
/* 新增:获奖名单模式下的按钮样式 */
.prize-panel-footer.winner-mode {
position: relative;
margin-top: 18px;
}
.arrow-up {
width: 36px;
height: 24px;
background: url("@/assets/arrow-up.svg") no-repeat center/contain;
margin-bottom: 4px;
cursor: pointer;
}
.winner-btn {
background: rgba(255, 210, 131, 0.8);
color: #fff;
border: #fff;
border-radius: 8px;
padding: 15px 79px;
font-size: 20px;
font-weight: bold;
cursor: pointer;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
transition: all 0.3s ease;
}
.winner-btn:hover {
background: rgba(255, 210, 131, 1);
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
.winner-modal-mask {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: rgba(0,0,0,0.01);
z-index: 1000;
display: flex;
align-items: flex-start;
justify-content: center;
}
.winner-modal {
background:rgba(255, 210, 131, 0.8);
border-radius: 12px;
/* margin-top: 2vh; */
padding-top: 12px;
min-width: 280px;
max-width: 90vw;
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.12);
position: relative;
}
.winner-modal-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 18px;
padding: 0 12px;
}
.winner-modal-title {
font-size: 22px;
font-weight: bold;
text-align: center;
flex: 1;
}
.winner-modal-close {
font-size: 24px;
color: #d84315;
cursor: pointer;
width: 30px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
background: rgba(255, 255, 255, 0.8);
transition: all 0.2s ease;
}
.winner-modal-close:hover {
background: rgba(255, 255, 255, 1);
transform: scale(1.1);
}
.winner-list {
max-height: 260px;
/* background: rgba(255, 210, 131, 0.8);/ */
overflow-y: auto;
padding: 0;
margin: 0;
list-style: none;
}
.winner-list li {
padding: 8px 0;
/* border-bottom: 1px solid #f2f2f2; */
font-size: 17px;
color: #d84315;
display: flex;
gap: 12px;
align-items: center;
justify-content: center;
text-align: center;
}
.progress-bar-bg {
position: relative;
width: 220px;
height: 28px;
background: #E9620E;
border-radius: 16px;
overflow: hidden;
display: flex;
align-items: center;
margin: 0 auto;
border: #E13726;
}
.progress-bar-fill {
position: absolute;
left: 0;
top: 0;
height: 100%;
/* background: linear-gradient(90deg, #ff9800 0%, #8a3500 100%); */
background: #8a3500;
border-radius: 16px;
transition: width 0.4s;
z-index: 1;
}
.progress-bar-text {
position: relative;
width: 100%;
text-align: center;
color: #ffffff;
font-size: 18px;
font-weight: bold;
z-index: 2;
letter-spacing: 1px;
}
.prize-card-mask {
position: relative;
width: 342px;
height: 88px;
display: flex;
/* align-items: center;
justify-content: center; */
padding: 0;
overflow: hidden;
}
.prize-mask-img {
object-fit: cover;
position: absolute;
width: 100%;
height: 98%;
object-fit: cover;
left: 0;
top: 0;
border-radius: 8px 8px 8px 8px;
}
.prize-panel-item.revealed-highlight {
border: 3px solid #ff9800;
box-shadow: 0 0 16px 4px #ff9800aa;
transform: scale(1.05);
z-index: 2;
transition: all 0.3s;
/* 确保高亮奖品在顶部 */
position: relative;
}
/* 新增:只有在获奖名单模式下才上移 */
.prize-panel-item.revealed-highlight.winner-mode-highlight {
order: -1;
margin-bottom: 18px;
/* 确保在左侧顶部显示 */
align-self: flex-start;
width: 100%;
}
/* 新增:获奖名单模式下的高亮样式 */
.prize-panel-item.winner-mode-highlight {
transform: scale(1.05);
box-shadow: 0 0 24px 8px #ff9800dd;
border: 4px solid #ff9800;
animation: winnerPulse 2s ease-in-out infinite;
/* 确保在左侧顶部显示 */
margin-top: 0;
margin-bottom: 18px;
}
@keyframes winnerPulse {
0%, 100% {
box-shadow: 0 0 24px 8px #ff9800dd;
}
50% {
box-shadow: 0 0 32px 12px #ff9800ff;
}
}
</style>

6
src/views/choujiang/index.vue

@ -20,7 +20,7 @@
" "
:left-users="dataManager.state.basicData.leftUsers" :left-users="dataManager.state.basicData.leftUsers"
/> --> /> -->
<Qipao :text="qipaoText" :show="showQipao" />
<!-- <Qipao :text="qipaoText" :show="showQipao" /> -->
</div> </div>
</template> </template>
@ -124,6 +124,10 @@ async function handleLotteryClick() {
case "result": case "result":
// result // result
await lottery3DRef.value?.switchScreen?.("lottery"); await lottery3DRef.value?.switchScreen?.("lottery");
//
lottery3DRef.value?.changeCard1?.();
lotteryState.value = "ready"; lotteryState.value = "ready";
break; break;

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

@ -1,26 +1,28 @@
<template> <template>
<div <div
:id="`card-${id}`" :id="`card-${id}`"
:class="['element', { lightitem: isBold, highlight: highlight, prize: prize }]"
:class="[
'element',
{ lightitem: isBold, highlight: highlight, prize: prize },
]"
:style="cardStyle" :style="cardStyle"
> >
<!-- <div class="company">{{ company }}</div> --> <!-- <div class="company">{{ company }}</div> -->
<!-- <div class="name">{{ user[1] }}</div> --> <!-- <div class="name">{{ user[1] }}</div> -->
<div class="details">{{ (user[0] || '') + '\n' + (user[2] || '') }}</div>
<div class="details">{{ (user[0] || "") + "\n" + (user[2] || "") }}</div>
</div> </div>
</template> </template>
<script setup> <script setup>
import { computed } from 'vue';
import { computed } from "vue";
import { useLotteryStore } from '../../../store/lottery' //
import { useLotteryStore } from "../../../store/lottery"; //
const lotteryStore = useLotteryStore(); //
const lotteryState = computed({
const lotteryStore = useLotteryStore(); //
const lotteryState = computed({
get: () => lotteryStore.lotteryState, get: () => lotteryStore.lotteryState,
set: (val) => lotteryStore.setLotteryState(val)
})
set: (val) => lotteryStore.setLotteryState(val),
});
const props = defineProps({ const props = defineProps({
id: [String, Number], id: [String, Number],
@ -32,43 +34,45 @@ const props = defineProps({
prize: Boolean, prize: Boolean,
}); });
const cardStyle = computed(() => { const cardStyle = computed(() => {
if (props.isBold && props.showTable) { if (props.isBold && props.showTable) {
if (lotteryState.value === 'idle') {
if (lotteryState.value === "idle") {
return {
// backgroundColor: "rgba(226, 60, 38, 1)",
background: 'linear-gradient(135deg, rgba(243,153,38,0.7) 0%, rgba(207,56,35,1) 100%)',
width: "130px",
height: "170px",
};
}
}
// return {
// // background: 'linear-gradient(135deg,rgba(255, 170, 22, 100) 0%, rgba(255, 170, 22, 100) 100%)',
// backgroundColor:'rgba(254, 177, 48, 100)',
// width: '130px',
// height: '170px',
// border: '1px solid rgb(255,255,255)',
// };
if (lotteryState.value === "result") {
return { return {
backgroundColor:'rgba(226, 60, 38, 1)',
// background: 'linear-gradient(135deg, rgba(243,153,38,0.7) 0%, rgba(207,56,35,1) 100%)',
width: '130px',
height: '170px',
// width: '68px',
// height: '88px',
background: 'linear-gradient(135deg,rgba(255, 170, 22, 100) 0%, rgba(255, 170, 22, 100) 100%)',
// backgroundColor: "rgba(254, 177, 48, 100)",
width: "130px",
height: "170px",
border: "1px solid rgb(255,255,255)",
};
} else {
return {
backgroundColor: "rgba(254, 177, 48, 100)",
width: "130px",
height: "170px",
border: "1px solid rgb(255,255,255)",
}; };
} }
// return {
// backgroundColor: 'rgb(226, 64, 35)',
// // backgroundColor: 'rgb(226, 164, 35)',
// width: '125px',
// height: '170px',
// };
}
return {
// background: 'linear-gradient(135deg,rgba(255, 170, 22, 100) 0%, rgba(255, 170, 22, 100) 100%)',
// backgroundColor:'rgba(255, 170, 22, 100)',
backgroundColor:'rgba(254, 177, 48, 100)',
width: '130px',
height: '170px',
// width: '68px',
// height: '88px',
border: '1px solid rgb(255,255,255)',
};
}); });
</script> </script>
<style scoped> <style scoped>
.element { .element {
transition: background-Color 2s;
transition: background 2s;
/* 你的基础样式 */ /* 你的基础样式 */
} }
.lightitem { .lightitem {
@ -79,9 +83,14 @@ const cardStyle = computed(() => {
} }
.prize { .prize {
/* 中奖样式 */ /* 中奖样式 */
background-color: #fc0202;
}
.company {
/* ... */
}
.name {
/* ... */
} }
.company { /* ... */ }
.name { /* ... */ }
.details { .details {
font-size: 30px; font-size: 30px;
text-align: center; text-align: center;

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

@ -1,6 +1,19 @@
<template> <template>
<div class="lottery-3d-container"> <div class="lottery-3d-container">
<div ref="threeContainer" class="three-container"></div> <div ref="threeContainer" class="three-container"></div>
<!-- 分页指示器 -->
<div v-if="totalPages > 1" class="page-indicator">
{{ currentPage + 1 }} / {{ totalPages }}
</div>
<!-- 滚动提示 -->
<!-- <div v-if="totalPages > 1 && currentPage === 0" class="scroll-hint">
向下滚动查看更多
</div>
<div v-if="totalPages > 1 && currentPage === totalPages - 1" class="scroll-hint">
向上滚动查看上一页
</div> -->
</div> </div>
</template> </template>
@ -20,6 +33,15 @@ const threeContainer = ref(null);
let renderer, scene, camera, animationId; let renderer, scene, camera, animationId;
// let controls; // controls // let controls; // controls
//
let globalCardIndexes = [];
//
const currentPage = ref(0);
const totalPages = ref(0);
const cardsPerPage = 10; //
let isPageTransitioning = false; //
// 3D // 3D
const threeDCards = []; const threeDCards = [];
const targets = { const targets = {
@ -157,54 +179,79 @@ function selectCard(selectedCardIndex, currentLuckys, duration = 600) {
}); });
return new Promise((resolve) => { return new Promise((resolve) => {
const width = 140; const width = 140;
let tag = -(currentLuckys.length - 1) / 2;
const locates = [];
// , 5
if (currentLuckys.length > 5) {
const yPosition = [-87, 87];
const l = selectedCardIndex.length;
const mid = Math.ceil(l / 2);
tag = -(mid - 1) / 2;
for (let i = 0; i < mid; i++) {
locates.push({
x: tag * width,
y: yPosition[0],
});
tag++;
}
tag = -(l - mid - 1) / 2;
for (let i = mid; i < l; i++) {
locates.push({
x: tag * width,
y: yPosition[1],
});
tag++;
}
} else {
for (let i = selectedCardIndex.length; i > 0; i--) {
locates.push({
x: tag * width,
y: 0,
});
tag++;
//
totalPages.value = Math.ceil(currentLuckys.length / cardsPerPage);
currentPage.value = 0;
//
const pageLocates = [];
for (let page = 0; page < totalPages.value; page++) {
const startIndex = page * cardsPerPage;
const endIndex = Math.min((page + 1) * cardsPerPage, currentLuckys.length);
const pageCount = endIndex - startIndex;
const pageLocate = [];
//
if (pageCount > 5) {
// 510
const yPosition = [-87, 87];
const mid = Math.ceil(pageCount / 2);
let tag = -(mid - 1) / 2;
for (let i = 0; i < mid; i++) {
pageLocate.push({
x: tag * width,
y: yPosition[0],
});
tag++;
}
tag = -(pageCount - mid - 1) / 2;
for (let i = mid; i < pageCount; i++) {
pageLocate.push({
x: tag * width,
y: yPosition[1],
});
tag++;
}
} else {
// 510
let tag = -(pageCount - 1) / 2;
for (let i = 0; i < pageCount; i++) {
pageLocate.push({
x: tag * width,
y: 0,
});
tag++;
}
} }
pageLocates.push(pageLocate);
} }
console.log("locates calculated:", locates);
console.log("pageLocates calculated:", pageLocates);
//
selectedCardIndex.forEach((cardIndex, index) => { selectedCardIndex.forEach((cardIndex, index) => {
// console.log("animating card:", cardIndex, "to position:", locates[index]);
changeCard(cardIndex, currentLuckys[index]); changeCard(cardIndex, currentLuckys[index]);
const object = threeDCards[cardIndex]; const object = threeDCards[cardIndex];
//
const cardPage = Math.floor(index / cardsPerPage);
const isVisible = cardPage === 0;
//
const pageIndex = index % cardsPerPage;
const pageLocate = pageLocates[cardPage][pageIndex];
new TWEEN.Tween(object.position) new TWEEN.Tween(object.position)
.to( .to(
{ {
x: locates[index].x,
y: locates[index].y,
x: isVisible ? pageLocate.x : pageLocate.x,
y: isVisible ? pageLocate.y : pageLocate.y + 1000, //
z: 2200, z: 2200,
}, },
Math.random() * duration + duration Math.random() * duration + duration
@ -227,22 +274,176 @@ function selectCard(selectedCardIndex, currentLuckys, duration = 600) {
object.element.classList.add("prize"); object.element.classList.add("prize");
}); });
// switchPage使
window.pageLocates = pageLocates;
new TWEEN.Tween({}) new TWEEN.Tween({})
.to({}, duration * 2) .to({}, duration * 2)
.onUpdate(() => render()) .onUpdate(() => render())
.start() .start()
.onComplete(() => { .onComplete(() => {
console.log("selectCard animation completed"); console.log("selectCard animation completed");
//
if (totalPages.value > 1) {
addWheelListener();
}
resolve(); resolve();
}); });
}); });
} }
//
function switchPage(direction) {
if (isPageTransitioning || totalPages.value <= 1) return;
const newPage = direction === 'next' ? currentPage.value + 1 : currentPage.value - 1;
if (newPage < 0 || newPage >= totalPages.value) return;
isPageTransitioning = true;
const duration = 800;
// 使
const pageLocates = window.pageLocates;
if (!pageLocates) {
console.error('页面位置信息未找到');
isPageTransitioning = false;
return;
}
//
globalCardIndexes.forEach((cardIndex, index) => {
const object = threeDCards[cardIndex];
const cardPage = Math.floor(index / cardsPerPage);
const isVisible = cardPage === newPage;
//
const pageIndex = index % cardsPerPage;
const pageLocate = pageLocates[cardPage][pageIndex];
new TWEEN.Tween(object.position)
.to(
{
x: pageLocate.x,
y: isVisible ? pageLocate.y : pageLocate.y + 1000,
z: 2200,
},
duration
)
.easing(TWEEN.Easing.Cubic.InOut)
.start();
});
new TWEEN.Tween({})
.to({}, duration)
.onUpdate(() => render())
.onComplete(() => {
currentPage.value = newPage;
isPageTransitioning = false;
console.log(`切换到第 ${currentPage.value + 1} 页,共 ${totalPages.value}`);
})
.start();
}
// function switchPage(direction) {
// if (isPageTransitioning || totalPages.value <= 1) return;
// const newPage = direction === 'next' ? currentPage.value + 1 : currentPage.value - 1;
// if (newPage < 0 || newPage >= totalPages.value) return;
// isPageTransitioning = true;
// const duration = 800;
// // 使
// const pageLocates = window.pageLocates;
// if (!pageLocates) {
// console.error('');
// isPageTransitioning = false;
// return;
// }
// //
// globalCardIndexes.forEach((cardIndex, index) => {
// const object = threeDCards[cardIndex];
// const cardPage = Math.floor(index / cardsPerPage);
// const isVisible = cardPage === newPage;
// //
// const pageIndex = index % cardsPerPage;
// const pageLocate = pageLocates[cardPage][pageIndex];
// //
// new TWEEN.Tween(object.position)
// .to(
// {
// x: pageLocate.x,
// y: isVisible ? pageLocate.y : (direction === 'next' ? pageLocate.y - 1000 : pageLocate.y + 1000), //
// z: 2200,
// },
// duration
// )
// .easing(TWEEN.Easing.Cubic.InOut)
// .start();
// });
// new TWEEN.Tween({})
// .to({}, duration)
// .onUpdate(() => render())
// .onComplete(() => {
// currentPage.value = newPage;
// isPageTransitioning = false;
// console.log(` ${currentPage.value + 1} ${totalPages.value} `);
// })
// .start();
// }
//
function handleWheel(event) {
if (isPageTransitioning || totalPages.value <= 1) return;
event.preventDefault();
if (event.deltaY > 0) {
//
switchPage('next');
} else if (event.deltaY < 0) {
//
switchPage('prev');
}
}
//
function addWheelListener() {
if (threeContainer.value) {
threeContainer.value.addEventListener('wheel', handleWheel, { passive: false });
}
}
//
function removeWheelListener() {
if (threeContainer.value) {
threeContainer.value.removeEventListener('wheel', handleWheel);
}
}
function resetCard(selectedCardIndex, duration = 500) { function resetCard(selectedCardIndex, duration = 500) {
if (!selectedCardIndex || selectedCardIndex.length === 0) { if (!selectedCardIndex || selectedCardIndex.length === 0) {
return Promise.resolve(); return Promise.resolve();
} }
//
removeWheelListener();
//
currentPage.value = 0;
totalPages.value = 0;
isPageTransitioning = false;
//
if (window.pageLocates) {
delete window.pageLocates;
}
selectedCardIndex.forEach((index) => { selectedCardIndex.forEach((index) => {
const object = threeDCards[index]; const object = threeDCards[index];
const target = targets.sphere[index]; const target = targets.sphere[index];
@ -288,12 +489,53 @@ function resetCard(selectedCardIndex, duration = 500) {
} }
function changeCard(cardIndex, user) { function changeCard(cardIndex, user) {
//
if (!globalCardIndexes.includes(cardIndex)) {
globalCardIndexes.push(cardIndex);
}
const card = threeDCards[cardIndex].element; const card = threeDCards[cardIndex].element;
card.innerHTML = `<div class="company">${
user.company || ""
}</div><div class="name">${user[1]}</div><div class="details">${
user[0] || ""
}<br/>${user[2] || "PSST"}</div>`;
// card.innerHTML = `<div class="company">${
// user.company || ""
// }</div><div class="name">${user[1]}</div><div class="details">${
// user[0] || ""
// }<br/>${user[2] || "PSST"}</div>`;
card.style.setProperty('background-color', '#ffffff', 'important');
// card.style.backgroundColor = '#ffffff';
// card.style.backgroundColor = '';
}
function changeCard1() {
console.log('执行取消高光,当前卡片索引:', globalCardIndexes);
//
removeWheelListener();
//
currentPage.value = 0;
totalPages.value = 0;
isPageTransitioning = false;
//
if (window.pageLocates) {
delete window.pageLocates;
}
globalCardIndexes.forEach(cardIndex => {
const card = threeDCards[cardIndex].element;
console.log('取消卡片', cardIndex, '的高光');
card.style.setProperty('background-color', 'rgba(254, 177, 48, 1)', 'important');
// prizeCSSbackgroundColor
card.classList.remove('prize');
});
//
globalCardIndexes = [];
} }
function shine(cardIndex, color) { function shine(cardIndex, color) {
@ -312,9 +554,9 @@ function addHighlight(indexes = null) {
} else { } else {
// .lightitem // .lightitem
highlightedIndexes.value = threeDCards highlightedIndexes.value = threeDCards
.map((obj, idx) =>
obj.element.classList.contains("lightitem") ? idx : null
)
// .map((obj, idx) =>
// obj.element.classList.contains("lightitem") ? idx : null
// )
.filter((idx) => idx !== null); .filter((idx) => idx !== null);
} }
} }
@ -429,6 +671,66 @@ onMounted(() => {
[17, "周二十"], [17, "周二十"],
[18, "吴二一"], [18, "吴二一"],
[19, "郑二二"], [19, "郑二二"],
[0, "张三"],
[1, "李四"],
[2, "王五"],
[3, "赵六"],
[4, "孙七"],
[5, "周八"],
[6, "吴九"],
[7, "郑十"],
[8, "钱十一"],
[9, "孙十二"],
[10, "李十三"],
[11, "周十四"],
[12, "吴十五"],
[13, "郑十六"],
[14, "钱十七"],
[15, "孙十八"],
[16, "李十九"],
[17, "周二十"],
[18, "吴二一"],
[19, "郑二二"],
[0, "张三"],
[1, "李四"],
[2, "王五"],
[3, "赵六"],
[4, "孙七"],
[5, "周八"],
[6, "吴九"],
[7, "郑十"],
[8, "钱十一"],
[9, "孙十二"],
[10, "李十三"],
[11, "周十四"],
[12, "吴十五"],
[13, "郑十六"],
[14, "钱十七"],
[15, "孙十八"],
[16, "李十九"],
[17, "周二十"],
[18, "吴二一"],
[19, "郑二二"],
[0, "张三"],
[1, "李四"],
[2, "王五"],
[3, "赵六"],
[4, "孙七"],
[5, "周八"],
[6, "吴九"],
[7, "郑十"],
[8, "钱十一"],
[9, "孙十二"],
[10, "李十三"],
[11, "周十四"],
[12, "吴十五"],
[13, "郑十六"],
[14, "钱十七"],
[15, "孙十八"],
[16, "李十九"],
[17, "周二十"],
[18, "吴二一"],
[19, "郑二二"],
]; ];
const length = member.length; const length = member.length;
const showTable = true; const showTable = true;
@ -453,6 +755,7 @@ onMounted(() => {
onBeforeUnmount(() => { onBeforeUnmount(() => {
window.removeEventListener("resize", onWindowResize); window.removeEventListener("resize", onWindowResize);
removeWheelListener(); //
if (animationId) cancelAnimationFrame(animationId); if (animationId) cancelAnimationFrame(animationId);
if (highlightTimeout) { if (highlightTimeout) {
clearTimeout(highlightTimeout); clearTimeout(highlightTimeout);
@ -486,6 +789,7 @@ defineExpose({
rotateBallStop, rotateBallStop,
selectCard, selectCard,
getTotalCards, getTotalCards,
changeCard1,
}); });
</script> </script>
@ -500,4 +804,40 @@ defineExpose({
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
/* 分页指示器样式 */
.page-indicator {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
z-index: 1000;
background: rgba(0, 0, 0, 0.7);
color: white;
padding: 8px 16px;
border-radius: 20px;
font-size: 14px;
pointer-events: none;
}
/* 滚动提示样式 */
.scroll-hint {
position: absolute;
bottom: 60px;
left: 50%;
transform: translateX(-50%);
z-index: 1000;
background: rgba(0, 0, 0, 0.7);
color: white;
padding: 8px 16px;
border-radius: 20px;
font-size: 12px;
pointer-events: none;
animation: fadeInOut 2s ease-in-out infinite;
}
@keyframes fadeInOut {
0%, 100% { opacity: 0.6; }
50% { opacity: 1; }
}
</style> </style>

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

@ -1,67 +1,155 @@
<template> <template>
<div class="prize-panel-root">
<div class="prize-panel-list" v-if="prizes && prizes.length">
<div
class="prize-panel-item"
v-for="(prize, idx) in prizes"
:key="prize.type || idx"
:class="{ 'revealed-highlight': idx === lastRevealedIdx }"
@click="handleReveal(idx)"
style="cursor: pointer;"
>
<div v-if="isRevealed(idx)" class="prize-card">
<div class="prize-img-wrap">
<img class="prize-img" :src="prize.img" :alt="prize.title" />
</div>
<div class="prize-info">
<div class="prize-row prize-row-top">
<span class="prize-level">{{ prize.title }}</span>
<span class="prize-name">{{ prize.text }}</span>
<div v-if="showOne">
<div class="prize-panel-root">
<div class="prize-panel-list" v-if="prizes && prizes.length">
<div
class="prize-panel-item"
v-for="(prize, idx) in prizes"
:key="prize.type || idx"
:class="{ 'revealed-highlight': idx === lastRevealedIdx }"
@click="handleReveal(idx)"
style="cursor: pointer"
>
<div v-if="isRevealed(idx)" class="prize-card">
<div class="prize-img-wrap">
<img class="prize-img" :src="prize.img" :alt="prize.title" />
</div> </div>
<div class="prize-row prize-row-bottom">
<div class="progress-bar-bg">
<div
class="progress-bar-fill"
:style="{ width:getProgressPercent(prize) + '%' }"
></div>
<span class="progress-bar-text">
{{ prize.count-getLeftCount(prize) }}/{{ prize.count }}
</span>
<div class="prize-info">
<div class="prize-row prize-row-top">
<span class="prize-level">{{ prize.title }}</span>
<span class="prize-name">{{ prize.text }}</span>
</div>
<div class="prize-row prize-row-bottom">
<div class="progress-bar-bg">
<div
class="progress-bar-fill"
:style="{ width: getProgressPercent(prize) + '%' }"
></div>
<span class="progress-bar-text">
{{ prize.count - getLeftCount(prize) }}/{{ prize.count }}
</span>
</div>
</div> </div>
</div> </div>
</div> </div>
<div v-else class="prize-card prize-card-mask">
<img
src="../../../assets/daijiemi.png"
alt="待揭秘"
class="prize-mask-img"
/>
</div>
</div> </div>
<div v-else class="prize-card prize-card-mask">
<img src="../../../assets/daijiemi.png" alt="待揭秘" class="prize-mask-img" />
<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>
<div
v-if="showWinnerList"
class="winner-modal-mask"
@click="closeWinnerList"
>
<div
class="winner-modal"
:style="{
position: 'absolute',
left: modalLeft + 'px',
top: modalTop + 'px',
}"
@click.stop
>
<div class="winner-modal-title">Homily ID</div>
<ul class="winner-list">
<li v-for="(user, idx) in fakeWinners" :key="idx">
<!-- <span>{{ user.id }}</span> - <span>{{ user.name }}</span> - -->
<span>{{ user.id }}</span>
<span>{{ user.prize }}</span>
</li>
</ul>
</div>
</div>
</div> </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>
</div>
</div>
<div v-else>
<div class="prize-panel-root">
<div class="prize-panel-list" v-if="prizes && prizes.length && lastRevealedIdx >= 0">
<div <div
v-if="showWinnerList"
class="winner-modal-mask"
@click="closeWinnerList"
class="prize-panel-item"
:key="prizes[lastRevealedIdx].type || lastRevealedIdx"
:class="{ 'revealed-highlight': true }"
style="cursor: pointer"
> >
<div class="prize-card">
<div class="prize-img-wrap">
<img class="prize-img" :src="prizes[lastRevealedIdx].img" :alt="prizes[lastRevealedIdx].title" />
</div>
<div class="prize-info">
<div class="prize-row prize-row-top">
<span class="prize-level">{{ prizes[lastRevealedIdx].title }}</span>
<span class="prize-name">{{ prizes[lastRevealedIdx].text }}</span>
</div>
<div class="prize-row prize-row-bottom">
<div class="progress-bar-bg">
<div
class="progress-bar-fill"
:style="{ width: getProgressPercent(prizes[lastRevealedIdx]) + '%' }"
></div>
<span class="progress-bar-text">
{{ prizes[lastRevealedIdx].count - getLeftCount(prizes[lastRevealedIdx]) }}/{{ prizes[lastRevealedIdx].count }}
</span>
</div>
</div>
</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>
<div <div
class="winner-modal"
:style="{ position: 'absolute', left: modalLeft + 'px', top: modalTop + 'px' }"
@click.stop
v-if="showWinnerList"
class="winner-modal-mask"
@click="closeWinnerList"
> >
<div class="winner-modal-title">
Homily ID
<div
class="winner-modal"
:style="{
position: 'absolute',
left: modalLeft + 'px',
top: modalTop + 'px',
}"
@click.stop
>
<div class="winner-modal-title">Homily ID</div>
<ul class="winner-list">
<li v-for="(user, idx) in fakeWinners" :key="idx">
<!-- <span>{{ user.id }}</span> - <span>{{ user.name }}</span> - -->
<span>{{ user.id }}</span>
<span>{{ user.prize }}</span>
</li>
</ul>
</div> </div>
<ul class="winner-list">
<li v-for="(user, idx) in fakeWinners" :key="idx">
<!-- <span>{{ user.id }}</span> - <span>{{ user.name }}</span> - -->
<span>{{ user.id }}</span>
<span>{{ user.prize }}</span>
</li>
</ul>
</div> </div>
</div> </div>
</div> </div>
@ -78,10 +166,17 @@ const props = defineProps({
const revealedCount = ref(0); const revealedCount = ref(0);
// //
const lastRevealedIdx = ref(-1); const lastRevealedIdx = ref(-1);
const showOne = ref(true);
// //
const isRevealed = idx => idx >= (props.prizes?.length || 0) - revealedCount.value;
const isRevealed = (idx) =>
idx >= (props.prizes?.length || 0) - revealedCount.value;
// index // index
const nextRevealIdx = computed(() => (props.prizes?.length || 0) - revealedCount.value - 1);
const nextRevealIdx = computed(
() => (props.prizes?.length || 0) - revealedCount.value - 1
);
// //
function handleReveal(idx) { function handleReveal(idx) {
if (idx === nextRevealIdx.value) { if (idx === nextRevealIdx.value) {
@ -111,9 +206,26 @@ const fakeWinners = ref([
]); ]);
function openWinnerList() { function openWinnerList() {
showWinnerList.value = true; showWinnerList.value = true;
// showOnefalse
if (lastRevealedIdx.value >= 0) {
showOne.value = false;
}
//
nextTick(() => {
const btn = winnerBtnRef.value;
if (btn) {
const rect = btn.getBoundingClientRect();
modalLeft.value = rect.left - 23;
modalTop.value = rect.bottom + 18; // 4px
}
});
} }
function closeWinnerList() { function closeWinnerList() {
showWinnerList.value = false; showWinnerList.value = false;
// showOnefalsetrue
if (!showOne.value) {
showOne.value = true;
}
} }
const winnerBtnRef = ref(null); const winnerBtnRef = ref(null);
@ -122,15 +234,29 @@ const modalTop = ref(0);
function toggleWinnerList() { function toggleWinnerList() {
showWinnerList.value = !showWinnerList.value; showWinnerList.value = !showWinnerList.value;
console.log('toggleWinnerList - showWinnerList:', showWinnerList.value, 'showOne:', showOne.value, 'lastRevealedIdx:', lastRevealedIdx.value);
if (showWinnerList.value) { if (showWinnerList.value) {
// showOnefalse
if (lastRevealedIdx.value >= 0) {
showOne.value = false;
console.log('设置 showOne 为 false');
}
//
nextTick(() => { nextTick(() => {
const btn = winnerBtnRef.value; const btn = winnerBtnRef.value;
if (btn) { if (btn) {
const rect = btn.getBoundingClientRect(); const rect = btn.getBoundingClientRect();
modalLeft.value = rect.left;
modalTop.value = rect.bottom + 4; // 4px
modalLeft.value = rect.left - 23;
modalTop.value = rect.bottom + 18; // 4px
} }
}); });
} else {
// showOnefalsetrue
if (!showOne.value) {
showOne.value = true;
console.log('设置 showOne 为 true');
}
} }
} }
@ -167,8 +293,7 @@ function getProgressPercent(prize) {
display: flex; display: flex;
align-items: center; align-items: center;
width: 100%; width: 100%;
padding: 10px 18px;
padding: 10px 18px;
} }
.prize-img-wrap { .prize-img-wrap {
width: 64px; width: 64px;
@ -261,7 +386,7 @@ function getProgressPercent(prize) {
background: rgba(255, 210, 131, 0.8); background: rgba(255, 210, 131, 0.8);
color: #fff; color: #fff;
border: #fff; border: #fff;
border-radius: 8px;
border-radius: 8px;
padding: 15px 79px; padding: 15px 79px;
font-size: 20px; font-size: 20px;
font-weight: bold; font-weight: bold;
@ -274,14 +399,14 @@ function getProgressPercent(prize) {
left: 0; left: 0;
width: 100vw; width: 100vw;
height: 100vh; height: 100vh;
background: rgba(0,0,0,0.01);
background: rgba(0, 0, 0, 0.01);
z-index: 1000; z-index: 1000;
display: flex; display: flex;
align-items: flex-start; align-items: flex-start;
justify-content: center; justify-content: center;
} }
.winner-modal { .winner-modal {
background:rgba(255, 210, 131, 0.8);
background: rgba(255, 210, 131, 0.8);
border-radius: 12px; border-radius: 12px;
padding-top: 12px; padding-top: 12px;
min-width: 280px; min-width: 280px;
@ -326,13 +451,13 @@ function getProgressPercent(prize) {
position: relative; position: relative;
width: 220px; width: 220px;
height: 28px; height: 28px;
background: #E9620E;
background: #e9620e;
border-radius: 16px; border-radius: 16px;
overflow: hidden; overflow: hidden;
display: flex; display: flex;
align-items: center; align-items: center;
margin: 0 auto; margin: 0 auto;
border: #E13726;
border: #e13726;
} }
.progress-bar-fill { .progress-bar-fill {
position: absolute; position: absolute;
@ -373,8 +498,7 @@ function getProgressPercent(prize) {
object-fit: cover; object-fit: cover;
left: 0; left: 0;
top: 0; top: 0;
border-radius: 8px 8px 8px 8px;
border-radius: 8px 8px 8px 8px;
} }
.prize-panel-item.revealed-highlight { .prize-panel-item.revealed-highlight {
border: 3px solid #ff9800; border: 3px solid #ff9800;

78
src/views/choujiang/lottery/dataManager.js

@ -28,7 +28,7 @@ export function useDataManager() {
{ type: 1, title: '一等奖', text: 'Kindle', count: 20, img: '/src/assets/lottery/kindle.jpg' }, { type: 1, title: '一等奖', text: 'Kindle', count: 20, img: '/src/assets/lottery/kindle.jpg' },
{ type: 2, title: '二等奖', text: 'MacBook Pro', count: 10, img: '/src/assets/lottery/mbp.jpg' } { type: 2, title: '二等奖', text: 'MacBook Pro', count: 10, img: '/src/assets/lottery/mbp.jpg' }
]; ];
const fakeEachCount = [10, 10, 10];
const fakeEachCount = [15, 17, 36];
const fakeCompany = '前端假公司'; const fakeCompany = '前端假公司';
const fakeLuckyData = {}; const fakeLuckyData = {};
fakePrizes.forEach(prize => { fakePrizes.forEach(prize => {
@ -54,6 +54,44 @@ export function useDataManager() {
[16, "李十九"], [16, "李十九"],
[17, "周二十"], [17, "周二十"],
[18, "吴二一"], [18, "吴二一"],
[19, "郑二二"], [0, "张三"],
[1, "李四"],
[2, "王五"],
[3, "赵六"],
[4, "孙七"],
[5, "周八"],
[6, "吴九"],
[7, "郑十"],
[8, "钱十一"],
[9, "孙十二"],
[10, "李十三"],
[11, "周十四"],
[12, "吴十五"],
[13, "郑十六"],
[14, "钱十七"],
[15, "孙十八"],
[16, "李十九"],
[17, "周二十"],
[18, "吴二一"],
[19, "郑二二"], [0, "张三"],
[1, "李四"],
[2, "王五"],
[3, "赵六"],
[4, "孙七"],
[5, "周八"],
[6, "吴九"],
[7, "郑十"],
[8, "钱十一"],
[9, "孙十二"],
[10, "李十三"],
[11, "周十四"],
[12, "吴十五"],
[13, "郑十六"],
[14, "钱十七"],
[15, "孙十八"],
[16, "李十九"],
[17, "周二十"],
[18, "吴二一"],
[19, "郑二二"], [19, "郑二二"],
]; ];
state.config.prizes = fakePrizes; state.config.prizes = fakePrizes;
@ -96,6 +134,44 @@ export function useDataManager() {
[16, "李十九"], [16, "李十九"],
[17, "周二十"], [17, "周二十"],
[18, "吴二一"], [18, "吴二一"],
[19, "郑二二"], [0, "张三"],
[1, "李四"],
[2, "王五"],
[3, "赵六"],
[4, "孙七"],
[5, "周八"],
[6, "吴九"],
[7, "郑十"],
[8, "钱十一"],
[9, "孙十二"],
[10, "李十三"],
[11, "周十四"],
[12, "吴十五"],
[13, "郑十六"],
[14, "钱十七"],
[15, "孙十八"],
[16, "李十九"],
[17, "周二十"],
[18, "吴二一"],
[19, "郑二二"], [0, "张三"],
[1, "李四"],
[2, "王五"],
[3, "赵六"],
[4, "孙七"],
[5, "周八"],
[6, "吴九"],
[7, "郑十"],
[8, "钱十一"],
[9, "孙十二"],
[10, "李十三"],
[11, "周十四"],
[12, "吴十五"],
[13, "郑十六"],
[14, "钱十七"],
[15, "孙十八"],
[16, "李十九"],
[17, "周二十"],
[18, "吴二一"],
[19, "郑二二"], [19, "郑二二"],
]; ];
state.basicData.users = fakeUsers; state.basicData.users = fakeUsers;

Loading…
Cancel
Save