Explorar el Código

feat: 增加断线重连功能,引入element的message和loading,修复翻牌后能翻回去

zhusiqing hace 3 años
padre
commit
b0e5cfb85d
Se han modificado 11 ficheros con 920 adiciones y 676 borrados
  1. 1 1
      .env.production
  2. 18 0
      CHANGELOG
  3. 2 1
      package.json
  4. 0 0
      server/data/data.txt
  5. 26 20
      server/server.js
  6. 2 3
      src/components/Card.vue
  7. 54 4
      src/components/Game.vue
  8. 9 0
      src/components/Start.vue
  9. 6 0
      src/main.js
  10. 4 4
      src/views/Main.vue
  11. 798 643
      yarn.lock

+ 1 - 1
.env.production

@@ -1,2 +1,2 @@
 NODE_ENV="production"
-VUE_APP_WS_URL="ws://39.104.169.128:5556"
+VUE_APP_WS_URL="ws://1.15.245.207:5556"

+ 18 - 0
CHANGELOG

@@ -0,0 +1,18 @@
+## 0.2.0
+
+服务运行一年后迎来的首次更新
+
+#### Features
+
+- 增加websocket断线重连功能
+- 增加客户端的消息提示
+- 修复队员翻牌后还能翻回去的bug
+
+## 0.1.0
+
+#### Features
+
+- 行动代号客户端
+- 行动代号服务端
+- 支持websocket
+- 支持添加新词(需要审核)

+ 2 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "codenames",
-  "version": "0.1.0",
+  "version": "0.2.0",
   "private": true,
   "scripts": {
     "serve": "vue-cli-service serve",
@@ -9,6 +9,7 @@
   },
   "dependencies": {
     "core-js": "^3.4.4",
+    "element-ui": "^2.15.6",
     "vue": "^2.6.10",
     "vue-router": "^3.1.4",
     "vuex": "^3.1.2"

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
server/data/data.txt


+ 26 - 20
server/server.js

@@ -50,27 +50,33 @@ app.use(koaStatic(path.join(__dirname, staticPath)))
 
 wss.on('connection', ws => {
   ws.on('message', msg => {
-    const res = JSON.parse(msg)
-    console.log('msg: ', res)
-    if (res.code) {
-      const list = cache.get(res.code)
-      if (res.status === 'update') {
-        const data = JSON.stringify({ data: list })
-        wss.clients.forEach(client => {
-          if (client.readyState === WebSocket.OPEN) {
-            client.send(data)
+    if (msg) {
+      try {
+        const res = JSON.parse(msg)
+        console.log('msg: ', res)
+        if (res.code) {
+          const list = cache.get(res.code)
+          if (res.status === 'update') {
+            const data = JSON.stringify({ data: list })
+            wss.clients.forEach(client => {
+              if (client.readyState === WebSocket.OPEN) {
+                client.send(data)
+              }
+            })
+          } else if (res.status === 'over') {
+            list.forEach(el => {
+              el.status = 1
+            })
+            const data = JSON.stringify({ data: list })
+            wss.clients.forEach(client => {
+              if (client.readyState === WebSocket.OPEN) {
+                client.send(data)
+              }
+            })
           }
-        })
-      } else if (res.status === 'over') {
-        list.forEach(el => {
-          el.status = 1
-        })
-        const data = JSON.stringify({ data: list })
-        wss.clients.forEach(client => {
-          if (client.readyState === WebSocket.OPEN) {
-            client.send(data)
-          }
-        })
+        }
+      } catch (error) {
+        console.error(error)
       }
     }
   })

+ 2 - 3
src/components/Card.vue

@@ -73,10 +73,9 @@ export default {
   },
   methods: {
     async onReverse() {
-      const { index, isCaptain, winner } = this
+      const { index, isCaptain, winner, isBack } = this
       const code = this.$store.getters.code
-      if (!code || isCaptain || winner) return
-
+      if (!code || isCaptain || winner || isBack) return
       const { success, data = {} } = await http.put(`/api/status/${code}`, { index })
       if (success) {
         this.$emit('statusChange', index, data.status)

+ 54 - 4
src/components/Game.vue

@@ -30,7 +30,11 @@ export default {
       code: '',
       ws: null,
       height: '20vh',
-      winner: ''
+      winner: '',
+      heartbeat: null,
+      limitConnect: 3,
+      timeConnect: 0,
+      loading: null
     }
   },
   watch: {
@@ -58,6 +62,7 @@ export default {
   },
   beforeDestroy() {
     this.ws.close()
+    clearInterval(this.heartbeat)
   },
   methods: {
     async init() {
@@ -74,8 +79,14 @@ export default {
       this.createWebsocket()
     },
     async getDataByCode(code) {
-      const { data = [] } = await http.get('/api/list', { code })
-      this.list = data
+      const loading = this.$loading()
+      try {
+        const { data = [] } = await http.get('/api/list', { code })
+        this.list = data
+      } catch (error) {
+        this.$message.error('获取数据失败')
+      }
+      loading.close()
     },
     onStatusChange(cardIndex, status) {
       this.list[cardIndex].status = status
@@ -88,7 +99,19 @@ export default {
       const ws = new WebSocket(process.env.VUE_APP_WS_URL)
       this.ws = ws
       ws.onopen = () => {
+        if (this.timeConnect) {
+          this.$message.success('连接成功')
+        }
         console.log('连接成功')
+        this.timeConnect = 0
+        this.limitConnect = 3
+        if (this.loading) {
+          this.loading.close()
+          this.loading = null
+        }
+        this.heartbeat = setInterval(() => {
+          ws.send('')
+        }, 5000)
         ws.send(JSON.stringify({ status: 'connect' }))
       }
       ws.onmessage = e => {
@@ -99,11 +122,38 @@ export default {
           this.list = list
         } catch (error) {
           console.error(error)
+          this.$message.error('websocket获取信息失败')
+        }
+      }
+      ws.onerror = e => {
+        console.error(e)
+        if (this.timeConnect === 3) {
+          this.$message.error('与服务器失去连接,请重新刷新页面')
+          this.loading.close()
+          this.loading = null
         }
       }
-      ws.onerror = e => console.error(e)
       ws.onclose = () => {
         console.log('connection closed')
+        if (this.timeConnect === 0) {
+          this.$message.error('与服务器断开连接,正在重新连接...')
+          this.loading = this.$loading()
+        }
+        clearInterval(this.heartbeat)
+        setTimeout(() => {
+          this.reconnect()
+        }, 1000)
+      }
+    },
+    reconnect() {
+      const { limitConnect } = this
+      if (limitConnect > 0) {
+        this.limitConnect -= 1
+        this.timeConnect += 1
+        this.$message.error(`尝试第${this.timeConnect}次重连...`)
+        setTimeout(() => {
+          this.createWebsocket()
+        }, 10e3)
       }
     },
     isOverHandle() {

+ 9 - 0
src/components/Start.vue

@@ -7,6 +7,7 @@
         <button class="start-button" @click.prevent="onSubmit">进入房间</button>
         <button class="start-button" @click.prevent="onToWords">添加新词</button>
       </div>
+      <p class="start-tip">分<span class="red">红</span><span class="blue">蓝</span>两队,<span class="blue">蓝队</span>9个,<span class="red">红队</span>8个,所以<span class="blue">蓝队</span><strong>优先</strong>开始</p>
     </form>
   </div>
 </template>
@@ -94,5 +95,13 @@ export default {
     font-size: 16px;
     margin: 0 10px;
   }
+  .start-tip {
+    .red {
+      color: red;
+    }
+    .blue {
+      color: #409EFF;
+    }
+  }
 }
 </style>

+ 6 - 0
src/main.js

@@ -2,9 +2,15 @@ import Vue from 'vue'
 import router from './router'
 import App from './App.vue'
 import store from './store'
+import { Message, Loading } from 'element-ui'
+import 'element-ui/packages/theme-chalk/lib/message.css'
+import 'element-ui/packages/theme-chalk/lib/loading.css'
 
 Vue.config.productionTip = false
 
+Vue.prototype.$loading = Loading.service
+Vue.prototype.$message = Message
+
 new Vue({
   store,
   router,

+ 4 - 4
src/views/Main.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="main">
+  <div class="main-app">
     <Game v-if="selectMode === 'game'"></Game>
     <Start v-else @game="onStartGame"></Start>
   </div>
@@ -10,7 +10,7 @@ import Game from '@/components/Game'
 import Start from '@/components/Start'
 
 export default {
-  name: 'main',
+  name: 'mainApp',
   components: {
     Game,
     Start
@@ -27,8 +27,8 @@ export default {
   }
 }
 </script>
-<style lang="scss" scoped>
-.main {
+<style lang="css">
+.main-app {
   height: 100%;
 }
 </style>

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 798 - 643
yarn.lock


Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio