许成详 6 年之前
父節點
當前提交
f4ec22dbd0
共有 5 個文件被更改,包括 692 次插入118 次删除
  1. 30
    42
      src/components/setting.vue
  2. 39
    22
      src/pages/admin.vue
  3. 582
    53
      src/pages/draw.1.vue
  4. 9
    1
      src/pages/draw.vue
  5. 32
    0
      src/utils/websocket.js

+ 30
- 42
src/components/setting.vue 查看文件

@@ -2,50 +2,32 @@
2 2
   <div>
3 3
     <div style="margin-bottom: 20px">
4 4
       <el-button @click="dialogVisible = true">新增</el-button>
5
+      <el-button @click="startDraw">开始抽奖</el-button>
6
+      <el-button @click="endDraw">结束抽奖</el-button>
5 7
     </div>
6 8
     <el-table
7 9
       :data="data"
8 10
       highlight-current-row
9 11
       border
10 12
       style="width: 100%"
11
-      :row-class-name="activeRow">
12
-      <el-table-column
13
-        prop="SettingId"
14
-        label="ID"
15
-        width="100">
16
-      </el-table-column>
17
-      <el-table-column
18
-        prop="PrizeId"
19
-        label="奖品"
20
-        :formatter="showPrizeName"
21
-        >
22
-      </el-table-column>
23
-      <el-table-column
24
-        prop="PrizeNum"
25
-        label="数量"
26
-        width="100">
27
-      </el-table-column>
28
-      <el-table-column
29
-        prop="IsRepeat"
30
-        label="允许重复抽"
31
-        :formatter="showRepeat"
32
-        width="150">
33
-      </el-table-column>
34
-      <el-table-column
35
-        prop="Status"
36
-        label="状态"
37
-        :formatter="showStatus"
38
-        width="150">
39
-      </el-table-column>
13
+      :row-class-name="activeRow"
14
+    >
15
+      <el-table-column prop="SettingId" label="ID" width="100"></el-table-column>
16
+      <el-table-column prop="PrizeId" label="奖品" :formatter="showPrizeName"></el-table-column>
17
+      <el-table-column prop="PrizeNum" label="数量" width="100"></el-table-column>
18
+      <el-table-column prop="IsRepeat" label="允许重复抽" :formatter="showRepeat" width="150"></el-table-column>
19
+      <el-table-column prop="Status" label="状态" :formatter="showStatus" width="150"></el-table-column>
40 20
     </el-table>
41
-    <el-dialog
42
-      title="提示"
43
-      :visible.sync="dialogVisible"
44
-      width="60%">
21
+    <el-dialog title="提示" :visible.sync="dialogVisible" width="60%">
45 22
       <el-form label-width="120px" :model="formData">
46 23
         <el-form-item label="奖品">
47 24
           <el-select v-model="formData.PrizeId">
48
-            <el-option v-for="item in prizes" :key="item.PrizeId" :label="`${item.PrizeType} - ${item.PrizeName}`" :value="item.PrizeId"></el-option>
25
+            <el-option
26
+              v-for="item in prizes"
27
+              :key="item.PrizeId"
28
+              :label="`${item.PrizeType} - ${item.PrizeName}`"
29
+              :value="item.PrizeId"
30
+            ></el-option>
49 31
           </el-select>
50 32
         </el-form-item>
51 33
         <el-form-item label="数量">
@@ -72,7 +54,7 @@ export default {
72 54
     'data',
73 55
     'prizes',
74 56
   ],
75
-  data() {
57
+  data () {
76 58
     return {
77 59
       dialogVisible: false,
78 60
       formData: {
@@ -83,22 +65,28 @@ export default {
83 65
     }
84 66
   },
85 67
   methods: {
86
-    activeRow({ row }) {
68
+    startDraw () {
69
+      this.$emit('startDraw')
70
+    },
71
+    endDraw () {
72
+      this.$emit('endDraw')
73
+    },
74
+    activeRow ({ row }) {
87 75
       if (row.Status === 1) {
88 76
         return 'tab-row-active'
89 77
       }
90 78
     },
91
-    showPrizeName(row, col, val) {
79
+    showPrizeName (row, col, val) {
92 80
       const prize = (this.prizes || []).filter(({ PrizeId: x }) => x === val)[0] || {}
93 81
       return `${prize.PrizeType} - ${prize.PrizeName}`;
94 82
     },
95
-    showRepeat(row, col, val) {
83
+    showRepeat (row, col, val) {
96 84
       return val === 1 ? '允许' : '不允许'
97 85
     },
98
-    showStatus(row, col, val) {
86
+    showStatus (row, col, val) {
99 87
       return val === 1 ? '有效' : '已抽过'
100 88
     },
101
-    onSubmit() {
89
+    onSubmit () {
102 90
       this.$emit('submit', { ...this.formData, IsRepeat: this.formData.IsRepeat - 0 })
103 91
       this.dialogVisible = false
104 92
     }
@@ -108,6 +96,6 @@ export default {
108 96
 
109 97
 <style>
110 98
 .el-table .tab-row-active {
111
-    background: #f0f9eb;
112
-  }
99
+  background: #f0f9eb;
100
+}
113 101
 </style>

+ 39
- 22
src/pages/admin.vue 查看文件

@@ -11,10 +11,22 @@
11 11
     <el-main>
12 12
       <el-tabs v-model="activeTab" type="card" @tab-click="tabChange">
13 13
         <el-tab-pane label="抽奖配置" name="setting">
14
-          <prize-setting :data="settings" :prizes="prizes" @submit="saveSetting"></prize-setting>
14
+          <prize-setting
15
+            :data="settings"
16
+            :prizes="prizes"
17
+            @submit="saveSetting"
18
+            @startDraw="wsSend({type: 'start'})"
19
+            @endDraw="wsSend({type: 'end'})"
20
+          ></prize-setting>
15 21
         </el-tab-pane>
16 22
         <el-tab-pane label="中奖名单" name="winner">
17
-          <winner :data="winners" :prizes="prizes" @search="searchWinner" @cancel="cancelWinner" @exportExcel="exportExcel"></winner>
23
+          <winner
24
+            :data="winners"
25
+            :prizes="prizes"
26
+            @search="searchWinner"
27
+            @cancel="cancelWinner"
28
+            @exportExcel="exportExcel"
29
+          ></winner>
18 30
         </el-tab-pane>
19 31
         <el-tab-pane label="奖品管理" name="prize">
20 32
           <prize :data="prizes" :uploadAction="uploadAction" @submit="savePrize"></prize>
@@ -27,6 +39,7 @@
27 39
 <script>
28 40
 import getApi from '../apis.js'
29 41
 import request from '../utils/request.js'
42
+import { newWebsocket, sendMsg } from '../utils/websocket.js'
30 43
 
31 44
 export default {
32 45
   name: 'admin-board',
@@ -35,14 +48,14 @@ export default {
35 48
     'winner': () => import('../components/winner.vue'),
36 49
     'prize': () => import('../components/prize.vue')
37 50
   },
38
-  created() {
51
+  created () {
52
+    this.initWebSocket()
39 53
     this.getSettingList()
40 54
     this.getPrizeList()
41 55
   },
42
-  data() {
56
+  data () {
43 57
     return {
44 58
       activeTab: 'setting',
45
-
46 59
       // 人员列表
47 60
       users: [],
48 61
       // 中奖名单
@@ -51,12 +64,17 @@ export default {
51 64
       prizes: [],
52 65
       // 抽奖配置
53 66
       settings: [],
54
-
55 67
       uploadAction: getApi('file.upload').url,
56 68
     }
57 69
   },
58 70
   methods: {
59
-    tabChange(tab) {
71
+    initWebSocket () {
72
+      newWebsocket('ws://192.168.0.11:8080/api/ws?id=admin')
73
+    },
74
+    wsSend (target) {
75
+      sendMsg(target)
76
+    },
77
+    tabChange (tab) {
60 78
       switch (tab.name) {
61 79
         case 'winner':
62 80
           this.getWinnerList()
@@ -66,54 +84,54 @@ export default {
66 84
           break;
67 85
       }
68 86
     },
69
-    getSettingList() {
87
+    getSettingList () {
70 88
       const api = getApi('setting.prize.list')
71 89
       request(api).then(({ settings }) => {
72 90
         this.settings = settings
73 91
       })
74 92
     },
75
-    saveSetting(data) {
93
+    saveSetting (data) {
76 94
       const api = getApi('setting.prize.save')
77 95
       request({ ...api, data: { data: window.JSON.stringify(data) } }).then(({ settings }) => {
78 96
         this.settings = settings
79 97
       })
80 98
     },
81
-    getPrizeList() {
99
+    getPrizeList () {
82 100
       const api = getApi('prize.list')
83 101
       request(api).then(({ prizes }) => {
84 102
         this.prizes = prizes
85 103
       })
86 104
     },
87
-    getWinnerList() {
105
+    getWinnerList () {
88 106
       const api = getApi('winner.list')
89 107
       request({ ...api }).then(({ winners }) => {
90 108
         this.winners = winners
91 109
       })
92 110
     },
93
-    searchWinner(params) {
111
+    searchWinner (params) {
94 112
       const api = getApi('winner.list')
95 113
       request({ ...api, params }).then(({ winners }) => {
96 114
         this.winners = winners
97 115
       })
98 116
     },
99
-    cancelWinner({ UserId, PrizeId: pid }) {
117
+    cancelWinner ({ UserId, PrizeId: pid }) {
100 118
       const api = getApi('winner.cancel', { UserId })
101
-      request({ ...api, params: { pid }}).then(() => {
119
+      request({ ...api, params: { pid } }).then(() => {
102 120
         this.winners = this.winners.filter(x => x.Status != -1)
103 121
 
104 122
         this.$message({
105
-            type: 'success',
106
-            message: '取消成功!'
107
-          })
123
+          type: 'success',
124
+          message: '取消成功!'
125
+        })
108 126
       })
109 127
     },
110
-    savePrize(data) {
128
+    savePrize (data) {
111 129
       const api = getApi('prize.save')
112 130
       request({ ...api, data: { data: window.JSON.stringify(data) } }).then(({ prizes }) => {
113 131
         this.prizes = prizes
114 132
       })
115 133
     },
116
-    exportExcel(params) {
134
+    exportExcel (params) {
117 135
       const api = getApi('excel.winner')
118 136
       const searchStr = !params ? '' : ['?'].concat(Object.keys(params).map((k) => `${k}=${params[k]}`)).join('&')
119 137
       window.open(`http://localhost:8080${api.url}${searchStr}`)
@@ -124,8 +142,8 @@ export default {
124 142
 
125 143
 
126 144
 <style>
127
-
128
-.el-header, .el-footer {
145
+.el-header,
146
+.el-footer {
129 147
   color: #fff;
130 148
   background-color: rgb(84, 92, 100);
131 149
   border-bottom: 1px solid #ebebeb;
@@ -134,6 +152,5 @@ export default {
134 152
 .el-header .logo {
135 153
   line-height: 60px;
136 154
 }
137
-
138 155
 </style>
139 156
 

+ 582
- 53
src/pages/draw.1.vue 查看文件

@@ -17,6 +17,133 @@
17 17
       @load="imgLoad"
18 18
       alt
19 19
     >
20
+    <img
21
+      src="../assets/images/icon15.png"
22
+      width="100%"
23
+      class="bg"
24
+      :class="{'grey': bgGrey}"
25
+      style="display:block;position:absolute;z-index: 3;bottom:0;left:0"
26
+      @load="imgLoad"
27
+      alt
28
+    >
29
+    <div class="canvasBox" :class="{'grey': bgGrey}" id="canvasBox">
30
+      <canvas id="canvas"></canvas>
31
+    </div>
32
+    <div class="animateBg centerLabel" :class="{'active': animationOff}" style="z-index: 10;">
33
+      <img src="../assets/images/icon4.png" alt>
34
+    </div>
35
+    <div class="prizeList centerLabel" :class="{'hide': !projectStart}">
36
+      <img src="../assets/images/icon14.png" alt>
37
+      <ul>
38
+        <li v-for="(item, index) in prizeList" :key="index">
39
+          <img src="../assets/images/icon6.png" width="100%" alt>
40
+          <div class="flex-v">
41
+            <div class="title">
42
+              <img src="../assets/images/icon7.png" v-if="item.PrizeType === '特等奖'" alt>
43
+              <img src="../assets/images/icon8.png" v-if="item.PrizeType === '一等奖'" alt>
44
+              <img src="../assets/images/icon9.png" v-if="item.PrizeType === '二等奖'" alt>
45
+              <img src="../assets/images/icon10.png" v-if="item.PrizeType === '三等奖'" alt>
46
+              <img src="../assets/images/icon11.png" v-if="item.PrizeType === '纪念奖'" alt>
47
+              <img src="../assets/images/icon12.png" v-if="item.PrizeType === '附加奖'" alt>
48
+            </div>
49
+            <div class="flex-item" style="margin-top: -20px;">
50
+              <div class="centerLabel" style="width: 100%;">
51
+                <div class="listImg">
52
+                  <a>
53
+                    <img :src="item.Picture" class="centerLabel contain" style="width: 80%;" alt>
54
+                  </a>
55
+                </div>
56
+                <span>{{item.PrizeName}}</span>
57
+              </div>
58
+            </div>
59
+          </div>
60
+        </li>
61
+      </ul>
62
+    </div>
63
+    <div class="prizeBox centerLabel" :class="{'hide': hidePrize}">
64
+      <div>
65
+        <div>
66
+          <img src="../assets/images/icon6.png" class="prizeBg" alt>
67
+          <div class="prizeFlex flex-v">
68
+            <div class="prizeTitle">
69
+              <img
70
+                src="../assets/images/icon7.png"
71
+                width="100%"
72
+                v-if="currentPrize.type === '特等奖'"
73
+                alt
74
+              >
75
+              <img
76
+                src="../assets/images/icon8.png"
77
+                width="100%"
78
+                v-if="currentPrize.type === '一等奖'"
79
+                alt
80
+              >
81
+              <img
82
+                src="../assets/images/icon9.png"
83
+                width="100%"
84
+                v-if="currentPrize.type === '二等奖'"
85
+                alt
86
+              >
87
+              <img
88
+                src="../assets/images/icon10.png"
89
+                width="100%"
90
+                v-if="currentPrize.type === '三等奖'"
91
+                alt
92
+              >
93
+              <img
94
+                src="../assets/images/icon11.png"
95
+                width="100%"
96
+                v-if="currentPrize.type === '纪念奖'"
97
+                alt
98
+              >
99
+              <img
100
+                src="../assets/images/icon12.png"
101
+                width="100%"
102
+                v-if="currentPrize.type === '附加奖'"
103
+                alt
104
+              >
105
+            </div>
106
+            <div class="flex-item">
107
+              <div>
108
+                <div class="centerLabel" style="width:80%;">
109
+                  <div class="prizeImg">
110
+                    <a>
111
+                      <img
112
+                        :src="currentPrize.img"
113
+                        class="centerLabel"
114
+                        style="max-width: 80%;max-height:80%;"
115
+                        alt
116
+                      >
117
+                    </a>
118
+                  </div>
119
+                  <span>{{currentPrize.name}} {{currentPrize.num}}人</span>
120
+                </div>
121
+              </div>
122
+            </div>
123
+          </div>
124
+        </div>
125
+        <div>
126
+          <img src="../assets/images/icon5.png" class="prizeBg" alt>
127
+          <div class="prizeFlex flex-v">
128
+            <div class="prizeNameListTitle"></div>
129
+            <div class="prizeNameList flex-item">
130
+              <div>
131
+                <div class="centerLabel" style="width:80%;margin-top: -30px;">
132
+                  <ul class="flex-h">
133
+                    <li
134
+                      class="flex-item endListLi"
135
+                      v-for="(item, index) in drawUsersArr"
136
+                      :key="index"
137
+                      :style="{maxWidth: item.width + 'px', minWidth: item.width + 'px'}"
138
+                    >{{item.orgName}}-{{item.UserName}}</li>
139
+                  </ul>
140
+                </div>
141
+              </div>
142
+            </div>
143
+          </div>
144
+        </div>
145
+      </div>
146
+    </div>
20 147
     <div class="userList centerLabel">
21 148
       <ul class="flex-h">
22 149
         <li
@@ -26,7 +153,7 @@
26 153
           :key="index"
27 154
           :class="{'active': item.active, 'activeLi': item.active, 'hide': !item.show}"
28 155
         >
29
-          <span>{{item.UserName}}</span>
156
+          <span>{{item.orgName}}-{{item.UserName}}</span>
30 157
         </li>
31 158
       </ul>
32 159
     </div>
@@ -38,7 +165,7 @@
38 165
           :key="index"
39 166
           :class="{'active': item.active}"
40 167
         >
41
-          <span>{{item.UserName}}</span>
168
+          <span>{{item.orgName}}-{{item.UserName}}</span>
42 169
         </li>
43 170
       </ul>
44 171
     </div>
@@ -48,23 +175,37 @@
48 175
         :key="index"
49 176
         :style="{width: item.width + 'px', left: item.startX + 'px', top: item.startY + 'px'}"
50 177
       >
51
-        <span>{{item.UserName}}</span>
178
+        <span>{{item.orgName}}-{{item.UserName}}</span>
52 179
       </a>
53 180
     </div>
181
+    <!-- <div class="line"></div> -->
54 182
   </div>
55 183
 </template>
56 184
 
57 185
 <script>
58 186
 /* eslint-disable */
59 187
 import '../assets/reset.css'
188
+import getApi from '../apis.js'
189
+import request from '../utils/request.js'
60 190
 export default {
61 191
   name: 'draw',
62 192
   data () {
63 193
     return {
194
+      animationOff: false,
195
+      currentPrize: {
196
+        img: '',
197
+        name: '',
198
+        num: '',
199
+        type: ''
200
+      },
201
+      projectStart: true,
202
+      hidePrize: true,
203
+      prizeList: [],
204
+      hidePrize: true,
64 205
       bgGrey: false,
65 206
       time: 300,
66 207
       drawCount: 10,
67
-      imgTotal: 2,
208
+      imgTotal: 3,
68 209
       curImgNum: 0,
69 210
       status: false,
70 211
       sureStatus: true,
@@ -79,21 +220,127 @@ export default {
79 220
     }
80 221
   },
81 222
   created () {
82
-    for (var n = 0; n < 500; n++) {
83
-      this.initUsers.push({
84
-        UserId: n + 1,
85
-        UserName: '姓名' + n,
86
-        active: false,
87
-        show: true,
88
-        delete: false
89
-      })
90
-    }
223
+    this.getUserList()
224
+    this.getPrizeList()
91 225
   },
92 226
   mounted () {
93 227
     this.$nextTick(() => {
228
+      this.canvasInit()
94 229
     })
95 230
   },
96 231
   methods: {
232
+    canvasInit () { // canvas初始化
233
+      const Snow = (canvas, count, options) => {
234
+        canvas.width = document.body.clientWidth
235
+        canvas.height = document.body.clientHeight
236
+        const ctx = canvas.getContext('2d')
237
+        const snowflakes = []
238
+        const add = item => snowflakes.push(item(canvas))
239
+        const update = () => _.forEach(snowflakes, el => el.update())
240
+        const resize = () => {
241
+          ctx.canvas.width = canvas.offsetWidth
242
+          ctx.canvas.height = canvas.offsetHeight
243
+          _.forEach(snowflakes, el => el.resized())
244
+        }
245
+        const draw = () => {
246
+          ctx.clearRect(0, 0, canvas.offsetWidth, canvas.offsetHeight)
247
+          _.forEach(snowflakes, el => el.draw())
248
+        }
249
+        const events = () => {
250
+          window.addEventListener('resize', resize)
251
+        }
252
+        const loop = () => {
253
+          draw()
254
+          update()
255
+          animFrame(loop)
256
+        }
257
+        const init = () => {
258
+          _.times(count, () => add(canvas => new SnowItem(canvas, null, options)))
259
+          events()
260
+          loop()
261
+        }
262
+        init(count)
263
+        resize()
264
+        return {
265
+          add, resize
266
+        }
267
+      }
268
+      const defaultOptions = {
269
+        color: 'red',
270
+        radius: [0.5, 4.0],
271
+        speed: [1, 3],
272
+        wind: [-0.5, 3.0]
273
+      }
274
+      const SnowItem = (canvas, drawFn = null, opts) => {
275
+        const options = { ...defaultOptions, ...opts }
276
+        const { radius, speed, wind, color } = options
277
+        const params = {
278
+          color,
279
+          x: _.random(0, canvas.offsetWidth),
280
+          y: _.random(-canvas.offsetHeight, 0),
281
+          radius: _.random(...radius),
282
+          speed: _.random(...speed),
283
+          wind: _.random(...wind),
284
+          isResized: false
285
+        }
286
+        const ctx = canvas.getContext('2d')
287
+        const updateData = () => {
288
+          params.x = _.random(0, canvas.offsetWidth)
289
+          params.y = _.random(-canvas.offsetHeight, 0)
290
+        }
291
+        const resized = () => params.isResized = true
292
+        const drawDefault = () => {
293
+          ctx.beginPath()
294
+          ctx.arc(params.x, params.y, params.radius, 0, 2 * Math.PI)
295
+          ctx.fillStyle = params.color
296
+          ctx.fill()
297
+          ctx.closePath()
298
+        }
299
+        const draw = drawFn ? () => drawFn(ctx, params) : drawDefault
300
+        const translate = () => {
301
+          params.y += params.speed
302
+          params.x += params.wind
303
+        }
304
+        const onDown = () => {
305
+          if (params.y < canvas.offsetHeight) return
306
+          if (params.isResized) {
307
+            updateData()
308
+            params.isResized = false
309
+          } else {
310
+            params.y = 0
311
+            params.x = _.random(0, canvas.offsetWidth)
312
+          }
313
+        }
314
+        const update = () => {
315
+          translate()
316
+          onDown()
317
+        }
318
+        return {
319
+          update,
320
+          resized,
321
+          draw
322
+        }
323
+      }
324
+      const el = document.querySelector('.container')
325
+      const wrapper = document.querySelector('body')
326
+      const canvas = document.getElementById('canvas')
327
+      const animFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame
328
+      Snow(canvas, 800, {
329
+        color: 'yellow'
330
+      })
331
+    },
332
+    getUserList () { // 获取用户数据
333
+      const api = getApi('user.list')
334
+      request(api).then((res) => {
335
+        this.initUsers = res.users.map(x => ({ ...x, active: false, show: true, delete: false, orgName: x.UserOrg }))
336
+      })
337
+    },
338
+    getPrizeList () { // 获取奖品数据
339
+      const api = getApi('prize.list')
340
+      request(api).then((res) => {
341
+        this.prizeList = res.prizes || []
342
+      })
343
+    },
97 344
     imgLoad () {
98 345
       this.curImgNum += 1 // 图片加载完 + 1
99 346
       if (this.curImgNum >= this.imgTotal) { // 图片加载完毕之后执行抽奖初始化逻辑
@@ -101,31 +348,44 @@ export default {
101 348
       }
102 349
     },
103 350
     initDraw () { // 初始化抽奖
104
-      // this.arrTimer = window.setInterval(() => { // 间隔时间进行抽奖随机变换效果
105
-      //   this.users = [] // 每次变换之前置空当前显示列表
106
-      //   this.calcRandomArr(90, this.initUsers, this.users, 'UserId', this.drawCount) // 从所有名单中随机获取若干个数据(获取数据个数,所有名单对象,当前显示名单列表对象,判重关键字,抽取中奖数量)
107
-      // }, this.time)
108 351
       document.getElementsByTagName('html')[0].onkeydown = (e) => { // 页面添加键盘点击事件监听
109 352
         e = e || event
110 353
         if (e.ctrlKey && e.keyCode == 13) { // 启停抽奖组合键:Ctrl + Enter
111 354
           this.sureStatus = true
112 355
           if (!this.status) { // 重新抽奖
113
-            this.bgGrey = true
114
-            this.status = !this.status
115
-            this.users = []
116
-            this.drawUsersArr = [] // 置空中奖数据
117
-            this.calcRandomArr(90, this.initUsers, this.users, 'UserId', this.drawCount)
118
-            this.arrTimer = window.setInterval(() => {
356
+            const api = getApi('draw')
357
+            request(api).then((res) => {
358
+              this.currentPrize = {
359
+                img: this.prizeList.filter((item) => { if (item.PrizeName === res.winner[0].PrizeName) return item.Picture })[0].Picture,
360
+                name: res.winner[0].PrizeName || '未知奖品',
361
+                num: res.winner.length || 0,
362
+                type: this.prizeList.filter((item) => { if (item.PrizeName === res.winner[0].PrizeName) return item.PrizeType })[0].PrizeType
363
+              }
364
+              this.winner = res.winner || []
365
+              this.drawCount = res.winner.length || 0
366
+              this.bgGrey = true
367
+              this.projectStart = false
368
+              this.status = !this.status
119 369
               this.users = []
120
-              this.calcRandomArr(90, this.initUsers, this.users, 'UserId', this.drawCount)
121
-            }, this.time)
370
+              this.drawUsersArr = [] // 置空中奖数据
371
+              this.calcRandomArr(this.initUsers.length > 90 ? 90 : this.initUsers.length, this.initUsers, this.users, 'UserId', this.drawCount)
372
+              this.arrTimer = window.setInterval(() => {
373
+                this.users = []
374
+                this.calcRandomArr(this.initUsers.length > 90 ? 90 : this.initUsers.length, this.initUsers, this.users, 'UserId', this.drawCount)
375
+              }, this.time)
376
+            })
122 377
           } else { // 抽奖变换动画暂定
123 378
             this.status = !this.status
124 379
             clearInterval(this.arrTimer)
125 380
             this.arrTimer = null
381
+            var num = 0
126 382
             this.users.map((item) => { // 记录中奖数据,以便读取过渡动画结束位置坐标
127 383
               if (item.active) {
128
-                this.drawUsersArr.push({ ...item, width: 0, startX: '', startY: '' })
384
+                item.UserName = this.winner[num].UserName
385
+                item.orgName = this.winner[num].UserOrg
386
+                item.isReset = true
387
+                num += 1
388
+                this.drawUsersArr.push({ ...item, width: 0, startX: '', startY: '', listX: '', listY: '' })
129 389
               }
130 390
             })
131 391
             this.$nextTick(() => {
@@ -133,34 +393,52 @@ export default {
133 393
                 item.endX = document.getElementsByClassName('targetLi')[index].getBoundingClientRect().x
134 394
                 item.endY = document.getElementsByClassName('targetLi')[index].getBoundingClientRect().y
135 395
               })
396
+              window.setTimeout(() => {
397
+                this.drawUsersArr.map((item, index) => { // 记录中奖名单结束位置坐标
398
+                  item.listX = document.getElementsByClassName('endListLi')[index].getBoundingClientRect().x
399
+                  item.listY = document.getElementsByClassName('endListLi')[index].getBoundingClientRect().y
400
+                })
401
+              }, 50)
136 402
               for (var n = 0; n < this.drawCount; n++) { // 记录中奖名单开始位置坐标
137 403
                 this.drawUsersArr[n].startX = document.getElementsByClassName('activeLi')[n].getBoundingClientRect().x
138 404
                 this.drawUsersArr[n].startY = document.getElementsByClassName('activeLi')[n].getBoundingClientRect().y
139 405
                 this.drawUsersArr[n].width = document.getElementsByClassName('activeLi')[n].getBoundingClientRect().width
140 406
               }
141
-            })
142
-          }
143
-        } else if (e.ctrlKey && e.keyCode == 32) { // 确认抽奖结果组合键:Ctrl + Space
144
-          if (!this.status) {
145
-            if (this.sureStatus) { // 之前已执行过Ctrl + Enter的前提下,才能执行确认动作
146
-              this.sureStatus = !this.sureStatus
147
-              this.users.map((item) => { // 隐藏未抽中数据
148
-                item.show = false
149
-              })
150
-              this.drawUsersArr.map((item) => {
151
-                item.startX = item.endX
152
-                item.startY = item.endY
407
+              this.drawUsersArr.map((item, index) => {
408
+                item.UserId = this.winner[index].UserId,
409
+                  item.UserName = this.winner[index].UserName,
410
+                  item.orgName = this.winner[index].UserOrg
153 411
               })
154
-            }
412
+              window.setTimeout(() => {
413
+                this.users.map((item) => { // 隐藏未抽中数据
414
+                  item.show = false
415
+                })
416
+                this.drawUsersArr.map((item) => {
417
+                  item.startX = item.endX
418
+                  item.startY = item.endY
419
+                })
420
+                window.setTimeout(() => {
421
+                  this.animationOff = true
422
+                }, 1000)
423
+                window.setTimeout(() => {
424
+                  this.bgGrey = false
425
+                  this.hidePrize = false
426
+                  this.drawUsersArr.map((item) => {
427
+                    item.startX = item.listX
428
+                    item.startY = item.listY
429
+                  })
430
+                }, 2500)
431
+              }, 1000)
432
+            })
155 433
           }
156 434
         }
157 435
       }
158 436
     },
159 437
     calcRandomArr (num, pArr, aArr, key, activeNum) {
438
+      var randomNum = Math.floor(Math.random() * pArr.length), bool = false
160 439
       if (pArr.length > num) {
161
-        var randomNum = Math.floor(Math.random() * pArr.length), bool = false
162 440
         aArr.map((item) => {
163
-          if (item[key] === pArr[randomNum]) {
441
+          if (item[key] === pArr[randomNum][key]) {
164 442
             bool = true
165 443
           }
166 444
         })
@@ -171,7 +449,8 @@ export default {
171 449
           this.calcRandomArr(num, pArr, aArr, key, activeNum)
172 450
         }
173 451
       } else {
174
-        return { ...pArr[randomNum], active: true }
452
+        aArr.push(...pArr.map((item, index) => ({ ...item, active: false })))
453
+        return this.returnSubArr(aArr, activeNum, 'active', 0)
175 454
       }
176 455
     },
177 456
     returnSubArr (arr, subNum, key, count) {
@@ -191,28 +470,278 @@ export default {
191 470
 </script>
192 471
 
193 472
 <style>
473
+.line {
474
+  width: 1px;
475
+  height: 100%;
476
+  position: absolute;
477
+  left: 699.25px;
478
+  top: 0;
479
+  background: #fff;
480
+  z-index: 10000;
481
+}
194 482
 .mainPage {
195 483
   overflow: hidden;
196 484
   background: #000;
197 485
 }
198
-.bg{
486
+.bg {
199 487
   -webkit-filter: brightness(100%);
200 488
   filter: brightness(100%);
201
-  transition: filter .3s linear;
202
-  -webkit-transition: filter .3s linear;
489
+  transition: filter 0.3s linear;
490
+  -webkit-transition: filter 0.3s linear;
203 491
   display: block;
204 492
   position: absolute;
205 493
 }
206
-.bg.grey{
494
+.bg.grey {
495
+  -webkit-filter: brightness(20%);
496
+  filter: brightness(20%);
497
+}
498
+.canvasBox {
499
+  width: 100%;
500
+  position: absolute;
501
+  left: 0;
502
+  top: 0;
503
+  bottom: 0;
504
+  z-index: 2;
505
+  -webkit-filter: brightness(100%);
506
+  filter: brightness(100%);
507
+}
508
+.canvasBox.grey{
207 509
   -webkit-filter: brightness(20%);
208 510
   filter: brightness(20%);
209 511
 }
512
+.animateBg {
513
+  z-index: 5;
514
+  overflow: visible;
515
+}
516
+.animateBg img {
517
+  display: block;
518
+  transition: all 1s ease-in-out;
519
+  -webkit-transition: all 1s ease-in-out;
520
+  transform: scale(0, 0);
521
+  -webkit-transform: scale(0, 0);
522
+  opacity: 1;
523
+}
524
+.animateBg.active img {
525
+  transform: scale(1.3, 1.3);
526
+  -webkit-transform: scale(1.3, 1.3);
527
+  opacity: 0;
528
+}
529
+.prizeList {
530
+  width: 100%;
531
+  opacity: 1;
532
+  transition: opacity 0.2s linear;
533
+  -webkit-transition: opacity 0.2s linear;
534
+  z-index: 10000;
535
+  overflow: visible;
536
+}
537
+.prizeList.hide {
538
+  opacity: 0;
539
+}
540
+.prizeList > img:first-child {
541
+  height: 17vh;
542
+  display: block;
543
+  margin: 0 auto;
544
+}
545
+.prizeList > ul {
546
+  width: 100%;
547
+  font-size: 0;
548
+  white-space: nowrap;
549
+  overflow: visible;
550
+  text-align: center;
551
+  margin: 40px auto 0;
552
+}
553
+.prizeList > ul > li {
554
+  width: 7.4%;
555
+  min-width: 300px;
556
+  max-width: 400px;
557
+  display: inline-block;
558
+  margin-left: 20px;
559
+  position: relative;
560
+  overflow: hidden;
561
+}
562
+.prizeList > ul > li:first-child {
563
+  margin-left: 0;
564
+}
565
+.prizeList > ul > li > img {
566
+  display: block;
567
+  position: relative;
568
+  z-index: 10;
569
+}
570
+.prizeList > ul > li > div {
571
+  width: 100%;
572
+  position: absolute;
573
+  left: 0;
574
+  top: 0;
575
+  bottom: 0;
576
+  z-index: 11;
577
+}
578
+.prizeList > ul > li .title {
579
+  width: 100%;
580
+  padding-bottom: 24.4%;
581
+  position: relative;
582
+  overflow: hidden;
583
+}
584
+.prizeList > ul > li .title img {
585
+  width: 100%;
586
+  display: block;
587
+  position: absolute;
588
+  left: 0;
589
+  top: 0;
590
+}
591
+.listImg {
592
+  width: 57.5%;
593
+  position: relative;
594
+  overflow: hidden;
595
+  margin: 0 auto;
596
+}
597
+.listImg a {
598
+  width: 100%;
599
+  display: block;
600
+  height: 0;
601
+  padding-bottom: 100%;
602
+  border-radius: 100%;
603
+  position: relative;
604
+  overflow: hidden;
605
+  background: #fff;
606
+}
607
+.listImg + span {
608
+  width: 100%;
609
+  display: block;
610
+  text-align: center;
611
+  color: #fff;
612
+  font-size: 20px;
613
+  line-height: 30px;
614
+  margin-top: 20px;
615
+}
616
+.prizeList.hide {
617
+  opacity: 0;
618
+}
619
+.prizeBox {
620
+  width: 42%;
621
+  min-width: 1700px;
622
+  max-width: 1900px;
623
+  overflow: visible;
624
+  z-index: 500;
625
+  opacity: 1;
626
+  transition: opacity 0.3s linear;
627
+  -webkit-transition: opacity 0.3s linear;
628
+}
629
+.prizeBox.hide {
630
+  opacity: 0;
631
+}
632
+.prizeBox > div {
633
+  width: 100%;
634
+  position: relative;
635
+  overflow: hidden;
636
+}
637
+.prizeBox > div > div:first-child {
638
+  width: 31.8%;
639
+  position: relative;
640
+  overflow: hidden;
641
+  float: left;
642
+}
643
+.prizeBox > div > div:last-child {
644
+  width: 65%;
645
+  position: relative;
646
+  overflow: hidden;
647
+  float: right;
648
+}
649
+.prizeBox > div > div > img.prizeBg {
650
+  width: 100%;
651
+  position: relative;
652
+  display: block;
653
+  z-index: 100;
654
+}
655
+.prizeFlex {
656
+  width: 100%;
657
+  position: absolute;
658
+  left: 0;
659
+  top: 0;
660
+  bottom: 0;
661
+  z-index: 101;
662
+}
663
+.prizeTitle {
664
+  width: 100%;
665
+  padding-bottom: 24.4%;
666
+  position: relative;
667
+  overflow: hidden;
668
+  height: 0;
669
+}
670
+.prizeNameListTitle {
671
+  width: 100%;
672
+  padding-bottom: 15%;
673
+  position: relative;
674
+  overflow: hidden;
675
+  height: 0;
676
+}
677
+.prizeTitle img {
678
+  display: block;
679
+  position: absolute;
680
+  left: 0;
681
+  top: 0;
682
+}
683
+.prizeFlex > .flex-item {
684
+  margin-top: -20px;
685
+}
686
+.prizeFlex > .flex-item > div {
687
+  padding: 0 9.5%;
688
+  height: 100%;
689
+  position: relative;
690
+  overflow: hidden;
691
+}
692
+.prizeFlex > .flex-item.prizeNameList > div {
693
+  padding: 0 5.7%;
694
+  height: 100%;
695
+  position: relative;
696
+  overflow: hidden;
697
+}
698
+.prizeFlex > .flex-item.prizeNameList > div ul {
699
+  justify-content: center;
700
+  flex-wrap: wrap;
701
+  -webkit-flex-wrap: wrap;
702
+  opacity: 0;
703
+}
704
+.prizeFlex > .flex-item.prizeNameList > div ul li {
705
+  text-align: center;
706
+  color: #fff;
707
+  font-size: 20px;
708
+  line-height: 60px;
709
+  white-space: nowrap;
710
+  overflow: hidden;
711
+  text-overflow: ellipsis;
712
+  margin: 10px;
713
+}
714
+.prizeImg {
715
+  width: 70%;
716
+  position: relative;
717
+  overflow: hidden;
718
+  margin: 0 auto;
719
+}
720
+.prizeImg a {
721
+  width: 100%;
722
+  display: block;
723
+  padding-bottom: 100%;
724
+  position: relative;
725
+  overflow: hidden;
726
+  border-radius: 100%;
727
+  background: #fff;
728
+  height: 0;
729
+}
730
+.prizeImg + span {
731
+  width: 100%;
732
+  display: block;
733
+  text-align: center;
734
+  color: #fff;
735
+  font-size: 30px;
736
+  line-height: 40px;
737
+  margin-top: 20px;
738
+}
210 739
 .drawEndList {
211 740
   width: 100%;
212 741
   height: 100%;
213 742
   position: relative;
214 743
   overflow: hidden;
215
-  z-index: 200;
744
+  z-index: 600;
216 745
 }
217 746
 .drawEndList > a {
218 747
   display: inline-block;
@@ -221,8 +750,8 @@ export default {
221 750
   border: 2px solid #e7963b;
222 751
   position: absolute;
223 752
   box-shadow: 0 0 0.2rem 0.15rem rgba(231, 150, 59, 0.2);
224
-  transition: none 0.5s ease-out 1s;
225
-  -webkit-transition: none 0.5s ease-out 1s;
753
+  transition: none 0.5s ease-out;
754
+  -webkit-transition: none 0.5s ease-out;
226 755
   transition-property: left, top;
227 756
   -webkit-transition-property: left, top;
228 757
 }
@@ -233,7 +762,7 @@ export default {
233 762
   border-radius: 60px;
234 763
   color: #fff;
235 764
   text-align: center;
236
-  font-size: 27px;
765
+  font-size: 20px;
237 766
   white-space: nowrap;
238 767
   overflow: hidden;
239 768
   text-overflow: ellipsis;
@@ -241,13 +770,13 @@ export default {
241 770
 }
242 771
 .userList,
243 772
 .drawUserList {
244
-  width: 44%;
773
+  width: 22%;
245 774
   min-width: 1500px;
246 775
   overflow: visible;
247 776
   z-index: 100;
248 777
 }
249 778
 .drawUserList {
250
-  width: 22%;
779
+  width: 44%;
251 780
   min-width: 750px;
252 781
   opacity: 0;
253 782
 }
@@ -291,7 +820,7 @@ export default {
291 820
   border-radius: 60px;
292 821
   color: #777;
293 822
   text-align: center;
294
-  font-size: 27px;
823
+  font-size: 20px;
295 824
   white-space: nowrap;
296 825
   overflow: hidden;
297 826
   text-overflow: ellipsis;

+ 9
- 1
src/pages/draw.vue 查看文件

@@ -187,6 +187,7 @@
187 187
 import '../assets/reset.css'
188 188
 import getApi from '../apis.js'
189 189
 import request from '../utils/request.js'
190
+import { newWebsocket } from '../utils/websocket.js'
190 191
 export default {
191 192
   name: 'draw',
192 193
   data () {
@@ -220,6 +221,7 @@ export default {
220 221
     }
221 222
   },
222 223
   created () {
224
+    this.initWebSocket()
223 225
     this.getUserList()
224 226
     this.getPrizeList()
225 227
   },
@@ -229,6 +231,12 @@ export default {
229 231
     })
230 232
   },
231 233
   methods: {
234
+    initWebSocket () {
235
+      newWebsocket('ws://192.168.0.11:8080/api/ws?id=web', this.webSocketCallback)
236
+    },
237
+    webSocketCallback (e) {
238
+      console.log(e)
239
+    },
232 240
     canvasInit () { // canvas初始化
233 241
       const Snow = (canvas, count, options) => {
234 242
         canvas.width = document.body.clientWidth
@@ -505,7 +513,7 @@ export default {
505 513
   -webkit-filter: brightness(100%);
506 514
   filter: brightness(100%);
507 515
 }
508
-.canvasBox.grey{
516
+.canvasBox.grey {
509 517
   -webkit-filter: brightness(20%);
510 518
   filter: brightness(20%);
511 519
 }

+ 32
- 0
src/utils/websocket.js 查看文件

@@ -0,0 +1,32 @@
1
+let ws
2
+
3
+export function newWebsocket (url, cb) {
4
+  ws = new WebSocket(url)
5
+  cb = cb || function () { }
6
+  ws.onopen = () => {
7
+    window.console.log('开始连接...')
8
+    ws.send('ping')
9
+    window.setInterval(() => {
10
+      window.console.log('send ping')
11
+      ws.send('ping')
12
+    }, 60000)
13
+  }
14
+  ws.onmessage = (e) => {
15
+    window.console.log(e)
16
+    if (e === 'ping') {
17
+      ws.sendMsg('pong')
18
+    } else if (e === 'pong') {
19
+      window.console.log('心跳完成' + Date.now())
20
+    } else {
21
+      cb(e)
22
+    }
23
+    window.console.log(e)
24
+  }
25
+  ws.onclose = () => {
26
+    window.console.log('关闭连接...')
27
+  }
28
+}
29
+
30
+export function sendMsg (msg) {
31
+  ws.send(msg)
32
+}