Browse Source

公告 websocket对接

chenrui 4 years ago
parent
commit
a447db4f2d

+ 1 - 0
.env

@@ -1,6 +1,7 @@
 NODE_ENV=production
 VUE_APP_PREVIEW=false
 VUE_APP_API_BASE_URL=http://qpls-md.360arrow.com/qpls-md
+VUE_APP_WX_BASE_URL=//qpls-md.360arrow.com/qpls-md/websocket/
 VUE_APP_VERSION=V1.0.1
 VUE_APP_PRO_NAME=箭冠汽配连锁系统
 VUE_APP_LOGO=@/assets/logo.png

+ 1 - 0
.env.development

@@ -1,6 +1,7 @@
 NODE_ENV=development
 VUE_APP_PREVIEW=true
 VUE_APP_API_BASE_URL=/api
+VUE_APP_WX_BASE_URL=//192.168.16.103:8503/qpls-md/websocket/
 VUE_APP_VERSION=V1.0.1
 VUE_APP_PRO_NAME=箭冠汽配连锁系统-dev
 VUE_APP_LOGO=@/assets/logo.png

+ 1 - 0
.env.preview

@@ -1,6 +1,7 @@
 NODE_ENV=production
 VUE_APP_PREVIEW=true
 VUE_APP_API_BASE_URL=http://qpls-md.360arrow.com.cn/qpls-md
+VUE_APP_WX_BASE_URL=//qpls-md.360arrow.com.cn/qpls-md/websocket/
 VUE_APP_VERSION=V1.0.1
 VUE_APP_PRO_NAME=箭冠汽配连锁系统-pre
 VUE_APP_LOGO=@/assets/logo.png

+ 15 - 0
src/api/noticeUser.js

@@ -19,3 +19,18 @@ export const noticeUserDetail = (params) => {
     method: 'get'
   })
 }
+
+// 获取通知消息未读数
+export const getUnreadCount = params => {
+  return axios({
+    url: 'noticeUser/queryNotReadCount',
+    method: 'post'
+  })
+}
+// 设置已读消息
+export const hasRead = id => {
+  return axios({
+    url: `noticeUser/setRead/${id}`,
+    method: 'get'
+  })
+}

+ 38 - 1
src/components/NoticeIcon/NoticeIcon.vue

@@ -47,13 +47,14 @@
     </span>
   </a-popover> -->
   <span @click="fetchNotice" class="header-notice" ref="noticeRef">
-    <a-badge count="12">
+    <a-badge :count="unreadCount">
       <a-icon style="font-size: 16px; padding: 0 5px" type="bell" />
     </a-badge>
   </span>
 </template>
 
 <script>
+import { mapGetters, mapActions } from 'vuex'
 export default {
   name: 'HeaderNotice',
   data () {
@@ -62,7 +63,31 @@ export default {
       visible: false
     }
   },
+  computed: {
+    ...mapGetters([
+      'unreadCount'
+    ]),
+    unreadCount () {
+      return this.$store.getters.unreadCount
+    },
+    // 接受到ws消息
+    wsMessage () {
+      return this.$store.getters.wsMessageData()
+    }
+  },
+  mounted () {
+    // webSocket 连接
+    this.WEBSOCKET_INIT()
+  },
+  destroyed () {
+    this.WEBSOCKET_CLOSE()
+  },
   methods: {
+    ...mapActions([
+      'WEBSOCKET_INIT',
+      'WEBSOCKET_CLOSE',
+      'updateUnreadcount'
+    ]),
     fetchNotice () {
       // if (!this.visible) {
       //   this.loading = true
@@ -75,6 +100,18 @@ export default {
       // this.visible = !this.visible
       this.$router.push({ path: '/notice' })
     }
+  },
+  watch: {
+    // 监听ws消息通知
+    wsMessage (a, b) {
+      if (a !== b && a) {
+        console.log(a)
+        // 新未读消息
+        if (a.type == 'no_read_count') {
+          this.updateUnreadcount(a.data.no_read_count)
+        }
+      }
+    }
   }
 }
 </script>

+ 3 - 1
src/store/index.js

@@ -3,6 +3,7 @@ import Vuex from 'vuex'
 
 import app from './modules/app'
 import user from './modules/user'
+import socket from './modules/websocketStore'
 
 // default router permission control
 import permission from './modules/permission'
@@ -17,7 +18,8 @@ export default new Vuex.Store({
   modules: {
     app,
     user,
-    permission
+    permission,
+    socket
   },
   state: {
 

+ 121 - 0
src/store/modules/websocketStore.js

@@ -0,0 +1,121 @@
+// import Vue from 'vue'
+import { noticeUserList, hasRead, getUnreadCount } from '@/api/noticeUser'
+export default {
+  state: {
+    websock: null,
+    wsMessageData: null,
+    wsMessageHomeData: null,
+    unreadCount: 0,
+    updateMessage: null, // 判断是否刷新未读消息数据
+    heartInterId: null
+  },
+  getters: {
+    wsMessageData: state => {
+      return () => state.wsMessageData
+    },
+    wsMessageHomeData: state => {
+      return () => state.wsMessageHomeData
+    },
+    unreadCount: state => state.unreadCount,
+    updateMessage: state => {
+      return () => state.updateMessage
+    }
+  },
+  mutations: {
+    WEBSOCKET_INIT (state, url) {
+      const _this = this
+      const baseUrl = process.env.VUE_APP_WX_BASE_URL
+      const sid = 'pc/u' + this.getters.userInfo.userid + 'epc'
+      const protocol = process.env.NODE_ENV == 'production' ? (window.location.protocol == 'http:' ? 'ws:' : 'wss:') : 'ws:'
+      const wsUrl = protocol + baseUrl + sid
+      console.log(process.env.NODE_ENV, wsUrl)
+      state.websock = new WebSocket(wsUrl)
+      state.websock.onopen = function () {
+        console.log('连接成功!')
+        _this.dispatch('getUnreadMessageCount')
+      }
+      state.websock.onmessage = function (e) {
+        console.log('ws接收!', e.data)
+        if (e.data != 'pong') {
+          console.log('进来----------')
+          state.wsMessageData = JSON.parse(e.data)
+        }
+      }
+      state.websock.οnerrοr = function (e) { // 错误
+        console.log('ws错误!', e)
+      }
+      state.websock.onclose = function (e) { // 关闭
+        console.log('ws关闭!', e)
+      }
+
+      // 发送心跳包
+      state.heartInterId = setInterval(function () {
+        console.log('ws发送心跳!')
+        if (state.websock.readyState == 3) {
+          clearInterval(state.heartInterId)
+          _this.commit('WEBSOCKET_INIT', url)
+        }
+        state.websock.send('ping')
+      }, 10000)
+    },
+    WEBSOCKET_CLOSE (state) {
+      state.websock.close()
+      clearInterval(state.heartInterId)
+    },
+    WEBSOCKET_SEND (state, p) {
+      console.log('ws发送!', p)
+      state.websock.send(p)
+    },
+    UPDATE_HOME (state, p) {
+      state.wsMessageHomeData = p
+    },
+    setMessageCount (state, count) {
+      state.unreadCount = count
+    }
+  },
+  actions: {
+    WEBSOCKET_INIT ({ commit }, url) {
+      commit('WEBSOCKET_INIT', url)
+    },
+    WEBSOCKET_SEND ({ commit }, p) {
+      commit('WEBSOCKET_SEND', p)
+    },
+    UPDATE_HOME ({ commit }, p) {
+      commit('UPDATE_HOME', p)
+    },
+    WEBSOCKET_CLOSE ({ commit }) {
+      commit('WEBSOCKET_CLOSE')
+    },
+    // 此方法用来获取未读消息条数,接口只返回数值,不返回消息列表
+    getUnreadMessageCount ({ state, commit }) {
+      getUnreadCount().then(res => {
+        console.log(res, '---------------请求未读消息', res.data ? res.data.no_read_count : 0)
+        commit('setMessageCount', res.data ? res.data.no_read_count : 0)
+      })
+    },
+    // 获取消息列表,其中包含未读、已读、回收站三个列表
+    getMessageList ({ state, commit }, params) {
+      return new Promise((resolve, reject) => {
+        noticeUserList(params).then(res => {
+          resolve(res)
+        }).catch(error => {
+          reject(error)
+        })
+      })
+    },
+    // 把一个未读消息标记为已读
+    hasRead ({ state, commit }, { msg_id }) {
+      return new Promise((resolve, reject) => {
+        hasRead(msg_id).then((res) => {
+          resolve(res)
+        }).catch(error => {
+          reject(error)
+        })
+      })
+    },
+    // 更新未读数
+    updateUnreadcount ({ state, commit }, count) {
+      commit('setMessageCount', count)
+    }
+  }
+}

+ 108 - 29
src/views/notice/list.vue

@@ -2,7 +2,7 @@
   <a-card size="small" :bordered="false" class="noticeList-wrap">
     <!-- 搜索条件 -->
     <div class="table-page-search-wrapper">
-      <a-form layout="inline" @keyup.enter.native="$refs.table.refresh(true)">
+      <a-form layout="inline" @keyup.enter.native="handelSearch(1)">
         <a-row :gutter="15">
           <a-col :md="6" :sm="24">
             <a-form-item label="创建时间">
@@ -22,26 +22,38 @@
             </a-form-item>
           </a-col>
           <a-col :md="6" :sm="24">
-            <a-button type="primary" @click="$refs.table.refresh(true)" :disabled="disabled" id="noticeList-refresh">查询</a-button>
+            <a-button type="primary" @click="handelSearch(1)" :disabled="disabled" id="noticeList-refresh">查询</a-button>
             <a-button style="margin-left: 8px" @click="resetSearchForm" :disabled="disabled" id="noticeList-reset">重置</a-button>
           </a-col>
         </a-row>
       </a-form>
     </div>
     <!-- 列表 -->
-    <s-table
+    <!-- <s-table
       class="sTable"
       ref="table"
       size="default"
       :rowKey="(record) => record.id"
       :columns="columns"
       :data="loadData"
+      bordered> -->
+    <a-table
+      class="sTable"
+      ref="table"
+      size="default"
+      :rowKey="(record) => record.id"
+      :columns="columns"
+      :dataSource="loadData"
+      :loading="listLoading"
+      :pagination="paginationProps"
       bordered>
       <!-- 操作 -->
       <template slot="action" slot-scope="text, record">
-        <a-button size="small" type="primary" class="button-success" @click="handleDetail(record)" id="noticeList-detail-btn">详情</a-button>
+        <a-badge :count="record.readFlag=='0'? 1 : 0" dot>
+          <a-button size="small" type="primary" class="button-success" @click="handleDetail(record)" id="noticeList-detail-btn">详情</a-button>
+        </a-badge>
       </template>
-    </s-table>
+    </a-table>
     <!-- 公告详情 -->
     <notice-detail-modal :openModal="openModal" :itemId="itemId" @close="closeModal" />
   </a-card>
@@ -50,8 +62,8 @@
 <script>
 import moment from 'moment'
 import { STable } from '@/components'
+import { mapActions } from 'vuex'
 import noticeDetailModal from './detailModal.vue'
-import { noticeUserList } from '@/api/noticeUser'
 export default {
   components: { STable, noticeDetailModal },
   data () {
@@ -60,7 +72,6 @@ export default {
         notice: {
           title: ''
         }
-        // buyerName: undefined //  客户名称
       },
       disabled: false, //  查询、重置按钮是否可操作
       dateFormat: 'YYYY-MM-DD',
@@ -68,55 +79,123 @@ export default {
       columns: [
         { title: '序号', dataIndex: 'no', width: 80, align: 'center' },
         { title: '创建时间', dataIndex: 'createDate', align: 'center' },
-        { title: '公告名称', dataIndex: 'notice.title', align: 'center', ellipsis: true, customRender: function (text) { return text || '--' } },
+        { title: '公告名称', dataIndex: 'notice.title', align: 'center', customRender: function (text) { return text || '--' } },
         { title: '操作', scopedSlots: { customRender: 'action' }, width: 200, align: 'center' }
       ],
-      // 加载数据方法 必须为 Promise 对象
-      loadData: parameter => {
-        this.disabled = true
-        // 创建时间
-        if (this.time && this.time.length > 0) {
-          this.queryParam.beginDate = moment(this.time[0]).format(this.dateFormat)
-          this.queryParam.endDate = moment(this.time[1]).format(this.dateFormat)
-        } else {
-          this.queryParam.beginDate = undefined
-          this.queryParam.endDate = undefined
-        }
-        return noticeUserList(Object.assign(parameter, this.queryParam)).then(res => {
-          const data = res.data
-          const no = (data.pageNo - 1) * data.pageSize
-          for (var i = 0; i < data.list.length; i++) {
-            data.list[i].no = no + i + 1
-          }
-          this.disabled = false
-          return data
-        })
+      loadData: [],
+      pageNo: 1, //  分页页码
+      pageSize: 10, //  分页 每页多少条
+      paginationProps: {
+        showSizeChanger: true, //  是否可以改变 pageSize
+        total: 0, //  分页总条数
+        current: 1,
+        onShowSizeChange: (current, pageSize) => this.changePageSize(current, pageSize),
+        onChange: (current) => this.changePage(current)
       },
+      listLoading: false,
       openModal: false, //  查看客户详情  弹框
       itemId: '' //  当前id
     }
   },
+  computed: {
+    // 接受到ws消息
+    wsMessage () {
+      return this.$store.getters.wsMessageData()
+    }
+  },
+  watch: {
+    // 监听ws消息通知
+    wsMessage (a, b) {
+      if (a !== b && a) {
+        // 新未读消息
+        if (a.type == 'no_read_count') {
+          this.resetSearchForm()
+        }
+      }
+    }
+  },
   methods: {
+    ...mapActions([
+      'getMessageList', // 查询列表
+      'hasRead' // 设置已读
+    ]),
     // 不可选日期
     disabledDate (date, dateStrings) {
       return date && date.valueOf() > Date.now()
     },
+    // 查询列表
+    handelSearch (pageNo) {
+      this.pageNo = pageNo || this.pageNo
+      this.disabled = true
+      // 创建时间
+      if (this.time && this.time.length > 0) {
+        this.queryParam.beginDate = moment(this.time[0]).format(this.dateFormat)
+        this.queryParam.endDate = moment(this.time[1]).format(this.dateFormat)
+      } else {
+        this.queryParam.beginDate = undefined
+        this.queryParam.endDate = undefined
+      }
+      const params = {
+        pageNo: this.pageNo,
+        pageSize: this.pageSize,
+        notice: {
+          title: this.queryParam.notice.title
+        },
+        beginDate: this.queryParam.beginDate,
+        endDate: this.queryParam.endDate
+      }
+      // 开始查询
+      this.listLoading = true
+      this.getMessageList(params).then((res) => {
+        this.listLoading = false
+        if (res.status == 200) {
+          const data = res.data
+          this.paginationProps.total = Number(res.data.count) || 0
+          this.paginationProps.current = data.pageNo
+          const no = (data.pageNo - 1) * data.pageSize
+          for (var i = 0; i < data.list.length; i++) {
+            data.list[i].no = no + i + 1
+          }
+          this.loadData = data.list
+          this.disabled = false
+        } else {
+          this.paginationProps.total = 0
+          this.paginationProps.current = 1
+          this.loadData = []
+        }
+      })
+    },
     //  重置
     resetSearchForm () {
       this.queryParam.notice.title = undefined
       this.time = []
-      this.$refs.table.refresh(true)
+      this.handelSearch(1)
     },
     //  详情
     handleDetail (row) {
       this.itemId = row.notice.id
       this.openModal = true
+      // 设置已读
+      if (row.readFlag == '0') {
+        this.hasRead({ msg_id: row.id }).then(res => {
+          // 刷新列表
+          if (res.status == 200) {
+            this.handelSearch()
+          }
+        })
+      }
     },
     //  关闭弹框
     closeModal () {
       this.itemId = ''
       this.openModal = false
     }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {
+      vm.openModal = false
+      vm.handelSearch(1)
+    })
   }
 }
 </script>