添加每次10人及以下抽奖排版适配

This commit is contained in:
moshang-xc 2020-01-13 14:16:35 +08:00
parent d37b213004
commit db4661f666
19 changed files with 507 additions and 360 deletions

4
.gitignore vendored
View File

@ -1,3 +1,5 @@
#npm
node_modules/
dist/
dist/
temp.json
error.json

View File

@ -84,31 +84,62 @@ Lottery
## 配置信息
1. 抽奖用户信息,按指定的格式填写在`server/data/user.xlsx`文件中,不能修改文件名
### 抽奖用户信息配置
2. 奖品的配置信息填写在`server/config.js`文件中,不能修改文件名
抽奖用户信息在**`server/data/user.xlsx`**文件中,按文件格式进行填充,不能修改文件名和列头
```js
### ### 奖品信息配置
奖品的配置信息填写在**server/config.js**文件中,不能修改文件名。
**其中奖品`prizes`的配置描述如下:**
| 参数 | 值类型 | 描述 |
| ----- | ------ | ------------------------------------------------------------ |
| type | Number | 奖品类型唯一标识0 是默认特别奖的占位符,其它奖品不可使用 |
| count | Number | 奖品数量 |
| text | String | 奖项名称 |
| title | String | 奖品描述 |
| img | String | 奖品的图片地址,图片在**img**目录下 |
````js
// 奖品信息,第一项为预留项不可修改,其他项可根据需要修改
let prizes = [{
type: 0,
count: 1000,
title: '特别奖',
img: ''
}, {
title: "",
text: "特别奖"
},
{
type: 1,
count: 1,
title: '华为Mate 20X',
img: '../img/huawei.png'
count: 2,
text: "特等奖",
title: "神秘大礼",
img: "../img/secrit.jpg"
},
{
type: 2,
count: 5,
text: "一等奖",
title: "Mac Pro",
img: "../img/mbp.jpg"
}
...
];
/**
* 一次抽取的奖品个数
* 顺序为:[特别奖,一等奖,二等奖,三等奖,四等奖,五等奖]
*/
const EACH_COUNT = [1, 1, 1, 1, 1, 5];
// 公司名称用于显示在抽奖名单的title部分
const COMPANY = 'MoShang';
### 奖品每次抽取个数配置
**`EACH_COUNT`**用于配置每次的抽奖个数与prizes奖品一一对应例如上面的奖品配置对应的抽奖个数配置如下
```js
const EACH_COUNT = [1, 1, 5];
````
如上配置,表示一次抽取的奖品个数顺序为:特别奖每次抽一个,特等奖每次抽一个,一等奖每次抽五个
### 企业标识配置
该标识用于显示在抽奖卡片上。
```js
const COMPANY = "MoShang";
```

View File

@ -1 +0,0 @@
[]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

BIN
product/src/img/edifier.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 328 KiB

BIN
product/src/img/ipad.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

BIN
product/src/img/secrit.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -36,7 +36,7 @@
<button id="lottery">抽奖</button>
<button id="reLottery">重新抽奖</button>
<button id="save">导出抽奖结果</button>
<button id="reset" style="margin-left: 40px;">重置</button>
<button id="reset" class="margin-l-40">重置</button>
</div>
</div>

View File

@ -1,145 +1,143 @@
html,
body {
height: 100%;
height: 100%;
}
body {
background: linear-gradient(to bottom, #131313 0%, #02101c 100%);
margin: 0;
font-family: Helvetica, sans-serif;
;
overflow: hidden;
background: linear-gradient(to bottom, #131313 0%, #02101c 100%);
margin: 0;
font-family: Helvetica, sans-serif;
overflow: hidden;
}
a {
color: #ffffff;
color: #ffffff;
}
.none {
display: none;
display: none;
}
#container {
z-index: 3;
position: relative;
margin: 0 15vh;
z-index: 3;
position: relative;
margin: 0 15vh;
}
#menu {
z-index: 4;
margin-left: 15vh;
z-index: 4;
margin-left: 15vh;
}
.canvas-box {
position: fixed;
left: 0;
top: 0;
z-index: -1;
position: fixed;
left: 0;
top: 0;
z-index: -1;
}
#info {
position: absolute;
width: 100%;
color: #ffffff;
padding: 5px;
font-family: Monospace;
font-size: 13px;
font-weight: bold;
text-align: center;
z-index: 1;
position: absolute;
width: 100%;
color: #ffffff;
padding: 5px;
font-family: Monospace;
font-size: 13px;
font-weight: bold;
text-align: center;
z-index: 1;
}
#menu {
position: absolute;
bottom: 2vh;
width: 100%;
text-align: center;
position: absolute;
bottom: 2vh;
width: 100%;
text-align: center;
}
.element {
width: 12vh;
height: 16vh;
box-shadow: 0 0 12px rgba(0, 255, 255, 0.5);
border: 1px solid rgba(127, 255, 255, 0.25);
text-align: center;
cursor: default;
transition: background-color .3s ease-in;
width: 12vh;
height: 16vh;
box-shadow: 0 0 12px rgba(0, 255, 255, 0.5);
border: 1px solid rgba(127, 255, 255, 0.25);
text-align: center;
cursor: default;
transition: background-color 0.3s ease-in;
}
.element:hover {
box-shadow: 0 0 12px rgba(0, 255, 255, 0.75);
border: 1px solid rgba(127, 255, 255, 0.75);
box-shadow: 0 0 12px rgba(0, 255, 255, 0.75);
border: 1px solid rgba(127, 255, 255, 0.75);
}
.element .company {
position: absolute;
top: 1.2vh;
right: 1.2vh;
font-size: 2vh;
color: rgba(127, 255, 255, 0.75);
position: absolute;
top: 1.2vh;
right: 0;
width: 100%;
font-size: 2vh;
color: rgba(127, 255, 255, 0.75);
}
.element .name {
position: absolute;
top: 4.6vh;
left: 0;
right: 0;
font-size: 3.2vh;
font-weight: bold;
color: rgba(255, 255, 255, 0.75);
text-shadow: 0 0 1vh rgba(0, 255, 255, 0.95);
position: absolute;
top: 4.6vh;
left: 0;
right: 0;
font-size: 2.9vh;
font-weight: bold;
color: rgba(255, 255, 255, 0.75);
text-shadow: 0 0 1vh rgba(0, 255, 255, 0.95);
}
.element .details {
position: absolute;
bottom: 1.2vh;
left: 0;
right: 0;
font-size: 1.6vh;
color: rgba(127, 255, 255, 0.75);
position: absolute;
bottom: 1.2vh;
left: 0;
right: 0;
font-size: 1.6vh;
color: rgba(127, 255, 255, 0.75);
}
button {
color: rgba(127, 255, 255, 0.75);
background: transparent;
outline: 1px solid rgba(127, 255, 255, 0.75);
border: 0;
padding: 1.6vh 4vh;
margin: 0 4.6vh;
font-size: 2vh;
font-weight: bold;
cursor: pointer;
color: rgba(127, 255, 255, 0.75);
background: transparent;
outline: 1px solid rgba(127, 255, 255, 0.75);
border: 0;
padding: 1.6vh 4vh;
margin: 0 4.6vh;
font-size: 2vh;
font-weight: bold;
cursor: pointer;
}
button:hover {
background-color: rgba(0, 255, 255, 0.5);
background-color: rgba(0, 255, 255, 0.5);
}
button:active {
color: #000000;
background-color: rgba(0, 255, 255, 0.75);
color: #000000;
background-color: rgba(0, 255, 255, 0.75);
}
.highlight {
background-color: rgba(253, 105, 0, 0.95) !important;
box-shadow: 0 0 12px rgba(253, 105, 0, 0.95);
border: 1px solid rgba(253, 105, 0, 0.25);
background-color: rgba(253, 105, 0, 0.95) !important;
box-shadow: 0 0 12px rgba(253, 105, 0, 0.95);
border: 1px solid rgba(253, 105, 0, 0.25);
}
.highlight.element .name {
text-shadow: 0 0 16px rgba(255, 255, 255, 0.95);
text-shadow: 0 0 16px rgba(255, 255, 255, 0.95);
}
.prize.element .name {
text-shadow: none;
text-shadow: none;
}
.prize.element {
transition: background-color 1.5s ease-in .3s;
background-color: rgba(253, 105, 0, 0.85) !important;
box-shadow: 0 0 12px rgba(253, 105, 0, 0.95);
transition: background-color 1.5s ease-in 0.3s;
background-color: rgba(253, 105, 0, 0.85) !important;
box-shadow: 0 0 12px rgba(253, 105, 0, 0.95);
}
.prize .company,
@ -148,317 +146,346 @@ button:active {
.highlight .company,
.highlight .name,
.highlight .details {
color: rgba(255, 255, 255, 0.85);
color: rgba(255, 255, 255, 0.85);
}
.dan-mu {
visibility: hidden;
position: fixed;
z-index: -1;
font-size: 12px;
top: 1vh;
left: 0;
padding: 0 1.2vh;
height: 2.2vh;
line-height: 2.2vh;
border-radius: 1vh;
box-sizing: border-box;
background-color: rgba(0, 127, 127, 0.37);
box-shadow: 0 0 4px rgba(0, 255, 255, 0.5);
border: 1px solid rgba(127, 255, 255, 0.25);
color: rgba(127, 255, 255, 0.75);
visibility: hidden;
position: fixed;
z-index: -1;
font-size: 12px;
top: 1vh;
left: 0;
padding: 0 1.2vh;
height: 2.2vh;
line-height: 2.2vh;
border-radius: 1vh;
box-sizing: border-box;
background-color: rgba(0, 127, 127, 0.37);
box-shadow: 0 0 4px rgba(0, 255, 255, 0.5);
border: 1px solid rgba(127, 255, 255, 0.25);
color: rgba(127, 255, 255, 0.75);
}
.dan-mu.active {
visibility: visible;
visibility: visible;
}
#prizeBar {
position: fixed;
left: 0;
padding-left: 1.2vh;
top: 1.2vh;
z-index: 2;
position: fixed;
left: 0;
padding-left: 1.2vh;
top: 1.2vh;
z-index: 2;
}
.prize-list {
margin: 0;
padding: 0;
list-style: none;
margin: 0;
padding: 0;
list-style: none;
}
.prize-item {
padding: 9px;
margin: 6px 0;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
flex-wrap: nowrap;
background-color: rgba(0, 127, 127, 0.37);
border: 1px solid rgba(127, 255, 255, 0.25);
color: rgba(127, 255, 255, 0.75);
width: 30vh;
height: 10vh;
box-sizing: border-box;
transition: transform 1s ease-in;
padding: 9px;
margin: 6px 0;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
flex-wrap: nowrap;
background-color: rgba(0, 127, 127, 0.37);
border: 1px solid rgba(127, 255, 255, 0.25);
color: rgba(127, 255, 255, 0.75);
width: 30vh;
height: 10vh;
box-sizing: border-box;
transition: transform 1s ease-in;
}
.prize-item .prize-img {
width: 8vh;
height: 8vh;
margin-right: 1.2vh;
border-radius: 50%;
background-color: #fff;
text-shadow: 0 0 1vh rgba(0, 255, 255, 0.95);
overflow: hidden;
width: 8vh;
height: 8vh;
margin-right: 1.2vh;
border-radius: 50%;
background-color: #fff;
text-shadow: 0 0 1vh rgba(0, 255, 255, 0.95);
overflow: hidden;
}
.prize-img img {
width: 90%;
height: 90%;
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 90%;
height: 90%;
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.prize-text {
flex: 1;
flex: 1;
}
.prize-title {
margin: 4px 0;
font-size: 1.8vh;
margin: 4px 0;
font-size: 1.8vh;
}
.prize-count {
padding: 4px 0;
position: relative;
padding: 4px 0;
position: relative;
}
.prize-count .progress {
height: 1.8vh;
background: rgba(0, 0, 0, .5);
padding: 1px;
overflow: visible;
border-radius: 1vh;
height: 1.8vh;
background: rgba(0, 0, 0, 0.5);
padding: 1px;
overflow: visible;
border-radius: 1vh;
}
.progress .progress-bar {
border-radius: 1.8vh;
position: relative;
animation: animate-positive 2s;
background-color: #d9534f;
height: 1.8vh;
-webkit-transition: width .6s ease;
-o-transition: width .6s ease;
transition: width .6s ease;
border-radius: 1.8vh;
position: relative;
animation: animate-positive 2s;
background-color: #d9534f;
height: 1.8vh;
-webkit-transition: width 0.6s ease;
-o-transition: width 0.6s ease;
transition: width 0.6s ease;
}
.progress-bar.active {
animation: reverse progress-bar-stripes 0.40s linear infinite, animate-positive 2s;
animation: reverse progress-bar-stripes 0.4s linear infinite,
animate-positive 2s;
}
.progress-bar-striped {
background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
-webkit-background-size: 8px 8px;
background-size: 8px 8px;
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;
}
@-webkit-keyframes animate-positive {
0% {
width: 0;
}
0% {
width: 0;
}
}
@keyframes animate-positive {
0% {
width: 0;
}
0% {
width: 0;
}
}
@-webkit-keyframes progress-bar-stripes {
from {
background-position: 8px 0
}
from {
background-position: 8px 0;
}
to {
background-position: 0 0
}
to {
background-position: 0 0;
}
}
@-o-keyframes progress-bar-stripes {
from {
background-position: 8px 0
}
from {
background-position: 8px 0;
}
to {
background-position: 0 0
}
to {
background-position: 0 0;
}
}
@keyframes progress-bar-stripes {
from {
background-position: 8px 0
}
from {
background-position: 8px 0;
}
to {
background-position: 0 0
}
to {
background-position: 0 0;
}
}
.prize-count-left {
position: absolute;
color: #fff;
right: 9px;
font-size: 1.8vh;
line-height: 1.6vh;
top: 50%;
transform: translateY(-50%);
position: absolute;
color: #fff;
right: 9px;
font-size: 1.8vh;
line-height: 1.6vh;
top: 50%;
transform: translateY(-50%);
}
.shine {
box-shadow: 0 0 15px 0 rgba(0, 255, 255, .5);
transform: scale(1.2);
transform-origin: left center;
position: relative;
box-shadow: 0 0 15px 0 rgba(0, 255, 255, 0.5);
transform: scale(1.2);
transform-origin: left center;
position: relative;
}
.shine:before,
.shine:after {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
box-sizing: border-box;
content: '';
z-index: 1;
margin: 0;
box-shadow: inset 0 0 0 1px;
border-radius: 4px;
animation: clipMe 8s linear infinite;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
box-sizing: border-box;
content: "";
z-index: 1;
margin: 0;
box-shadow: inset 0 0 0 1px;
border-radius: 4px;
animation: clipMe 8s linear infinite;
}
.shine:before {
animation-delay: -4s;
animation-delay: -4s;
}
.done {
position: relative;
position: relative;
}
.done:after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, .5);
cursor: not-allowed;
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
cursor: not-allowed;
}
@keyframes clipMe {
0%,
100% {
clip: rect(0, 30vh, 1px, 0);
}
0%,
100% {
clip: rect(0, 30vh, 1px, 0);
}
25% {
clip: rect(0, 1px, 10vh, 0);
}
25% {
clip: rect(0, 1px, 10vh, 0);
}
50% {
clip: rect(9.9vh, 30vh, 10vh, 0);
}
50% {
clip: rect(9.9vh, 30vh, 10vh, 0);
}
75% {
clip: rect(0, 30vh, 10vh, 29.9vh);
}
75% {
clip: rect(0, 30vh, 10vh, 29.9vh);
}
}
.shine.prize-item {
/* width: 24vh; */
margin: 1.8vh 0;
/* width: 24vh; */
margin: 1.8vh 0;
}
.prize-mess {
color: #fff;
line-height: 5vh;
font-size: 1.6vh;
margin: 2.4vh 0;
color: #fff;
line-height: 5vh;
font-size: 1.6vh;
margin: 2.4vh 0;
}
.prize-shine {
font-size: 5vh;
font-weight: bold;
color: #db5c58;
vertical-align: middle;
padding: 0 6px;
font-size: 5vh;
font-weight: bold;
color: #db5c58;
vertical-align: middle;
padding: 0 6px;
}
.qipao-container {
position: fixed;
right: 0;
top: 10vh;
bottom: 1vh;
width: 24vh;
z-index: 2;
position: fixed;
right: 0;
top: 10vh;
bottom: 1vh;
width: 24vh;
z-index: 2;
}
.qipao {
width: 100%;
padding: 1.8vh 1.4vh;
line-height: 1.414;
margin: 4px 0;
box-sizing: border-box;
font-size: 14px;
background-color: rgba(127, 255, 255, 0.25);
color: rgba(127, 255, 255, 0.75);
width: 100%;
padding: 1.8vh 1.4vh;
line-height: 1.414;
margin: 4px 0;
box-sizing: border-box;
font-size: 14px;
background-color: rgba(127, 255, 255, 0.25);
color: rgba(127, 255, 255, 0.75);
}
.music {
position: fixed;
top: 3vh;
right: 4vh;
z-index: 5;
position: fixed;
top: 3vh;
right: 4vh;
z-index: 5;
}
.music-item {
display: block !important;
opacity: 0;
display: block !important;
opacity: 0;
}
.music-box {
width: 5vh;
height: 5vh;
border-radius: 50%;
text-align: center;
line-height: 5vh;
font-size: 1.4vh;
color: #fff;
cursor: pointer;
background-color: rgba(253, 105, 0, 0.9);
border: 1px solid rgba(255, 255, 255, .5);
width: 5vh;
height: 5vh;
border-radius: 50%;
text-align: center;
line-height: 5vh;
font-size: 1.4vh;
color: #fff;
cursor: pointer;
background-color: rgba(253, 105, 0, 0.9);
border: 1px solid rgba(255, 255, 255, 0.5);
}
.rotate-active {
animation: rotate 4s linear infinite;
animation: rotate 4s linear infinite;
}
@keyframes rotate {
from {
transform: rotate(0);
}
from {
transform: rotate(0);
}
to {
transform: rotate(360deg);
}
}
to {
transform: rotate(360deg);
}
}
.margin-l-40 {
margin-left: 40px;
}

View File

@ -23,7 +23,7 @@ let TOTAL_CARDS,
ROW_COUNT = 7,
COLUMN_COUNT = 17,
COMPANY,
HIGHLIGHT_CELL,
HIGHLIGHT_CELL = [],
// 当前的比例
Resolution = 1;
@ -46,7 +46,7 @@ let selectedCardIndex = [],
leftUsers: [] //未中奖人员
},
interval,
// 当前抽的奖项,从五等奖开始抽
// 当前抽的奖项,从最低奖开始抽,直到抽到大奖
currentPrizeIndex,
currentPrize,
// 正在抽奖
@ -450,11 +450,44 @@ function render() {
function selectCard(duration = 600) {
rotate = false;
let width = 140,
tag = -(currentLuckys.length - 1) / 2;
tag = -(currentLuckys.length - 1) / 2,
locates = [];
// 计算位置信息, 大于5个分两排显示
if (currentLuckys.length > 5) {
let yPosition = [-87, 87],
l = selectedCardIndex.length,
mid = Math.ceil(l / 2);
tag = -(mid - 1) / 2;
for (let i = 0; i < mid; i++) {
locates.push({
x: tag * width * Resolution,
y: yPosition[0] * Resolution
});
tag++;
}
tag = -(l - mid - 1) / 2;
for (let i = mid; i < l; i++) {
locates.push({
x: tag * width * Resolution,
y: yPosition[1] * Resolution
});
tag++;
}
} else {
for (let i = selectedCardIndex.length; i > 0; i--) {
locates.push({
x: tag * width * Resolution,
y: 0 * Resolution
});
tag++;
}
}
let text = currentLuckys.map(item => item[1]);
addQipao(
`恭喜${text.join("、")}获得${currentPrize.title}, 2019年必定旺旺旺。`
`恭喜${text.join("、")}获得${currentPrize.title}, 新的一年必定旺旺旺。`
);
selectedCardIndex.forEach((cardIndex, index) => {
@ -463,8 +496,8 @@ function selectCard(duration = 600) {
new TWEEN.Tween(object.position)
.to(
{
x: tag * width * Resolution,
y: 50 * Resolution,
x: locates[index].x,
y: locates[index].y * Resolution,
z: 2200
},
Math.random() * duration + duration
@ -655,9 +688,9 @@ function shine(cardIndex, color) {
* 随机切换背景和人员信息
*/
function shineCard() {
let maxCard = 15,
let maxCard = 10,
maxUser;
let shineCard = random(maxCard);
let shineCard = 10 + random(maxCard);
setInterval(() => {
// 正在抽奖停止闪烁

View File

@ -7,19 +7,15 @@ let prizes;
const DEFAULT_MESS = [
"我是该抽中一等奖还是一等奖呢纠结ing...",
"听说要提前一个月吃素才能中大奖喔!",
"好想要无人机啊!!!",
"好想要一等奖啊!!!",
"一等奖有没有人想要呢?",
"五等奖也不错,只要自己能中奖就行",
"祝大家新年快乐!",
"中不中奖不重要,大家吃好喝好。",
"我已经有了天猫精灵了,要是再中个小度,那我该宠谁呢?",
"2019年祝福大家事事顺遂。",
"新年,祝福大家事事顺遂。",
"作为专业陪跑的我,我就看看你们有谁跟我一样",
"2019祝福大家越来越好",
"2019了有没有要生猪宝宝的",
"来年再战!!!",
"去年UI组全员陪跑今年是否还是如此呢",
"我们UI组至少要重一个大奖吧"
"新的一年祝福大家越来越好!",
"来年再战!!!"
];
let lastDanMuList = [];
@ -162,12 +158,7 @@ function showPrizeList(currentPrizeIndex) {
if (currentPrize.type === defaultType) {
currentPrize.count === "不限制";
}
let htmlCode = `<div class="prize-mess">正在抽取<label id="prizeType" class="prize-shine">${currentPrize.type +
"等奖"}</label><label id="prizeText" class="prize-shine">${
currentPrize["title"]
}</label><label id="prizeLeft" class="prize-shine">${
currentPrize["count"]
}</label></div><ul class="prize-list">`;
let htmlCode = `<div class="prize-mess">正在抽取<label id="prizeType" class="prize-shine">${currentPrize.text}</label><label id="prizeText" class="prize-shine">${currentPrize.title}</label>,剩余<label id="prizeLeft" class="prize-shine">${currentPrize.count}</label>个</div><ul class="prize-list">`;
prizes.forEach(item => {
if (item.type === defaultType) {
return true;
@ -179,7 +170,7 @@ function showPrizeList(currentPrizeIndex) {
<img src="${item.img}" alt="${item.title}">
</div>
<div class="prize-text">
<h5 class="prize-title">${item.type}等奖 ${
<h5 class="prize-title">${item.text} ${
item.title
}</h5>
<div class="prize-count">
@ -248,7 +239,7 @@ let setPrizeData = (function() {
lastBox.classList.remove("shine");
lastBox.classList.add("done");
elements.box && elements.box.classList.add("shine");
prizeElement.prizeType.textContent = currentPrize.type + "等奖";
prizeElement.prizeType.textContent = currentPrize.text;
prizeElement.prizeText.textContent = currentPrize.title;
lasetPrizeIndex = currentPrizeIndex;

View File

@ -1 +0,0 @@
{}

View File

@ -1,55 +1,77 @@
/**
* 奖品设置
* type
* count
* title:
* img:
* type: 唯一标识0是默认特别奖的占位符其它奖品不可使用
* count: 奖品数量
* title: 奖品描述
* text: 奖品标题
* img: 图片地址
*/
const prizes = [
{
type: 0,
count: 100,
title: "特别奖",
img: "../img/mbp.jpg"
count: 1000,
title: "",
text: "特别奖"
},
{
type: 1,
count: 1,
title: "MacBook Pro",
img: "../img/mbp.jpg"
count: 2,
text: "特等奖",
title: "神秘大礼",
img: "../img/secrit.jpg"
},
{
type: 2,
count: 2,
title: "华为 Mate30 ",
img: "../img/huawei.png"
count: 5,
text: "一等奖",
title: "Mac Pro",
img: "../img/mbp.jpg"
},
{
type: 3,
count: 3,
count: 6,
text: "二等奖",
title: "华为 Mate30",
img: "../img/huawei.png"
},
{
type: 4,
count: 7,
text: "三等奖",
title: "Ipad Mini5",
img: "../img/ipad.jpg"
},
{
type: 5,
count: 8,
text: "四等奖",
title: "大疆无人机",
img: "../img/spark.jpg"
},
{
type: 4,
count: 20,
type: 6,
count: 9,
text: "五等奖",
title: "Kindle",
img: "../img/kindle.jpg"
},
{
type: 5,
title: "小度在家",
count: 50,
img: "../img/baidu.jpg"
type: 7,
count: 10,
text: "六等奖",
title: "漫步者蓝牙耳机",
img: "../img/edifier.jpg"
}
];
/**
* 一次抽取的奖品个数
* 顺序为[特别奖一等奖二等奖三等奖四等奖五等奖]
* 一次抽取的奖品个数与prizes对应
*/
const EACH_COUNT = [1, 1, 1, 1, 1, 5];
const EACH_COUNT = [1, 1, 5, 6, 7, 8, 9, 10];
/**
* 卡片公司名称标识
*/
const COMPANY = "MoShang";
module.exports = {

View File

@ -1,7 +1,11 @@
const fs = require("fs");
const path = require("path");
const xlsx = require("node-xlsx").default;
let cwd = process.cwd();
let cwd = path.join(__dirname, "cache");
if (!fs.existsSync(cwd)) {
fs.mkdirSync(cwd);
}
/**
* 读取缓存的数据内容
@ -64,7 +68,7 @@ function writeXML(data, name) {
]);
return new Promise((resolve, reject) => {
fs.writeFile(path.join(cwd, name), buffer, err => {
fs.writeFile(path.join(process.cwd(), name), buffer, err => {
if (err) {
reject(err);
return;
@ -81,6 +85,10 @@ function writeXML(data, name) {
function saveDataFile(data) {
data = JSON.stringify(data, "", 2);
if (!fs.existsSync(cwd)) {
fs.mkdirSync(cwd);
}
return new Promise((resolve, reject) => {
fs.writeFile(path.join(cwd, "temp.json"), data, err => {
if (err) {
@ -99,6 +107,9 @@ function saveDataFile(data) {
*/
function saveErrorDataFile(data) {
data = JSON.stringify(data, "", 2);
if (!fs.existsSync(cwd)) {
fs.mkdirSync(cwd);
}
return new Promise((resolve, reject) => {
fs.writeFile(path.join(cwd, "error.json"), data, err => {
@ -112,9 +123,24 @@ function saveErrorDataFile(data) {
});
}
/**
* 洗牌算法
* @param {*} arr
*/
function shuffle(arr) {
let i = arr.length;
while (i) {
let j = Math.floor(Math.random() * i--);
let temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
}
module.exports = {
loadTempData,
loadXML,
shuffle,
writeXML,
saveDataFile,
saveErrorDataFile

View File

@ -678,11 +678,13 @@
},
"balanced-match": {
"version": "1.0.0",
"bundled": true
"bundled": true,
"optional": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@ -695,15 +697,18 @@
},
"code-point-at": {
"version": "1.1.0",
"bundled": true
"bundled": true,
"optional": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true
"bundled": true,
"optional": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true
"bundled": true,
"optional": true
},
"core-util-is": {
"version": "1.0.2",
@ -806,7 +811,8 @@
},
"inherits": {
"version": "2.0.4",
"bundled": true
"bundled": true,
"optional": true
},
"ini": {
"version": "1.3.5",
@ -816,6 +822,7 @@
"is-fullwidth-code-point": {
"version": "1.0.0",
"bundled": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@ -828,17 +835,20 @@
"minimatch": {
"version": "3.0.4",
"bundled": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "0.0.8",
"bundled": true
"bundled": true,
"optional": true
},
"minipass": {
"version": "2.9.0",
"bundled": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@ -855,6 +865,7 @@
"mkdirp": {
"version": "0.5.1",
"bundled": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@ -935,7 +946,8 @@
},
"number-is-nan": {
"version": "1.0.1",
"bundled": true
"bundled": true,
"optional": true
},
"object-assign": {
"version": "4.1.1",
@ -945,6 +957,7 @@
"once": {
"version": "1.4.0",
"bundled": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@ -1050,6 +1063,7 @@
"string-width": {
"version": "1.0.2",
"bundled": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",

View File

@ -10,6 +10,7 @@ const {
loadTempData,
writeXML,
saveDataFile,
shuffle,
saveErrorDataFile
} = require("./help");
@ -108,7 +109,7 @@ router.post("/saveData", (req, res, next) => {
});
log(`保存奖品数据成功`);
})
.catch(res => {
.catch(data => {
res.json({
type: "设置失败!"
});
@ -126,7 +127,7 @@ router.post("/errorData", (req, res, next) => {
});
log(`保存没来人员数据成功`);
})
.catch(res => {
.catch(data => {
res.json({
type: "设置失败!"
});
@ -138,9 +139,9 @@ router.post("/errorData", (req, res, next) => {
router.post("/export", (req, res, next) => {
let type = [1, 2, 3, 4, 5, defaultType],
outData = [["工号", "姓名", "部门"]];
type.forEach(item => {
outData.push(item === defaultType ? ["特别奖"] : [`${item}等奖`]);
outData = outData.concat(luckyData[item] || []);
cfg.prizes.forEach(item => {
outData.push([item.text]);
outData = outData.concat(luckyData[item.type] || []);
});
writeXML(outData, "/抽奖结果.xlsx")
@ -208,8 +209,10 @@ function loadData() {
// curData.users = loadXML(path.join(cwd, "data/users.xlsx"));
curData.users = loadXML(path.join(dataBath, "data/users.xlsx"));
// 读取已经抽取的结果
// 重新洗牌
shuffle(curData.users);
// 读取已经抽取的结果
loadTempData()
.then(data => {
luckyData = data[0];