2 Commits 9b963ea038 ... 7e8ec1fdd1

Auteur SHA1 Bericht Datum
  double 7e8ec1fdd1 feat: 新增消息提醒 2 jaren geleden
  double 6a2c8df7a2 feat: 更新消息提醒 2 jaren geleden

BIN
src/assets/audio/order_ready.mp3


BIN
src/assets/audio/order_ready_15.mp3


BIN
src/assets/audio/order_ready_5.mp3


BIN
src/assets/audio/order_success.mp3


+ 545 - 42
src/components/common/layout/layout.vue

@@ -23,7 +23,7 @@
23 23
         </div>
24 24
         <div class="right">
25 25
           <div @click="onAppMessage" class="news">
26
-            <span class="dot"></span>
26
+            <span class="dot" v-show="hasUnreadMessage"></span>
27 27
             <img src="https://we-spa.oss-cn-shenzhen.aliyuncs.com/pad_clerk/home/news.png" />
28 28
           </div>
29 29
           <div class="head-img"><img :src="userInfo.avatar_url"></div>
@@ -46,16 +46,162 @@
46 46
     </div>
47 47
     <minePupop :show="msgPupopVisible">
48 48
       <div class="block">
49
-          <div class="delete-pupop" @click="msgPupopVisible=false">
50
-            <img src="https://we-spa.oss-cn-shenzhen.aliyuncs.com/pad_clerk/icon/slices/delete.png" alt />
49
+          <div class="title">
50
+            <div @click="clearUnreadMsgsByType(0)" class="clear">
51
+              <img src="https://we-spa.oss-cn-shenzhen.aliyuncs.com/pad_clerk/home/clearMsg.png" alt="">
52
+              <div class="">清除未读</div>
53
+            </div>
54
+            <div class="txt">消息</div>
55
+            <div class="delete-pupop" @click="closeMsgPanel">
56
+              <img src="https://we-spa.oss-cn-shenzhen.aliyuncs.com/pad_clerk/icon/slices/delete.png" alt />
57
+            </div>
51 58
           </div>
59
+          <div class="msg-con">
60
+            <van-list 
61
+              v-model="mainPanelMsgListLoading"
62
+              :finished="mainPanelMsgListFinished"
63
+              finished-text="没有更多了"
64
+              @load="getMainPanelMessageList"
65
+              :immediate-check="false"
66
+            >
67
+              <div class="order-msg">
68
+                <div class="success">
69
+                  <div class="flex justify-between" @click="toMsgDetail(1)">
70
+                    <div class="desc flex items-center">
71
+                      <img src="https://we-spa.oss-cn-shenzhen.aliyuncs.com/pad_clerk/home/make.png" alt="" />
72
+                      <div class="title">预约成功信息</div>
73
+                    </div>
74
+                    <div class="count flex flex-column justify-center items-center">
75
+                      <!-- <div class="time">10:23</div> -->
76
+                      <div class="num" v-if="orderSuccessUnreadNum">{{orderSuccessUnreadNum}}</div>
77
+                    </div>
78
+                  </div>
79
+                </div>
80
+                <div class="cancel">
81
+                  <div class="flex justify-between" @click="toMsgDetail(2)">
82
+                    <div class="desc flex items-center">
83
+                      <img src="https://we-spa.oss-cn-shenzhen.aliyuncs.com/pad_clerk/home/cancelOrder.png" alt="" />
84
+                      <div class="title">预约取消信息</div>
85
+                    </div>
86
+                    <div class="count flex flex-column justify-center items-center">
87
+                      <!-- <div class="time">10:23</div> -->
88
+                      <div class="num" v-if="orderCancelUnreadNum">{{orderCancelUnreadNum}}</div>
89
+                    </div>
90
+                  </div>
91
+                </div>
92
+              </div>
93
+              <div class="ready-msg flex justify-between items-center" 
94
+                v-for="(item, index) in msgPanelList" 
95
+                :key="index"
96
+                @click="readMsgToOrderDetails(item)"
97
+              >
98
+                <div class="content-bar flex flex-column">
99
+                  <div class="desc-info">{{item.sender_name}}</div>
100
+                  <div class="desc-time">{{item.msg | ellipsis(80)}}</div>
101
+                </div>
102
+                <div class="count flex flex-column items-center">
103
+                  <div class="time">{{item.create_time}}</div>
104
+                  <div class="dot" v-if="!item.is_read && allUnread"></div>
105
+                </div>
106
+              </div>
107
+            </van-list>
108
+          </div>
109
+      </div>
110
+    </minePupop>
111
+    <minePupop :show="msgSuccessDetailPupopVisible">
112
+      <div class="block detail">
113
+        <div class="title">
114
+          <div @click="backMsgPanel" class="back flex items-center">
115
+            <img src="https://we-spa.oss-cn-shenzhen.aliyuncs.com/pad_clerk/icon/slices/back.png" alt="" />
116
+          </div>
117
+          <div class="txt">消息</div>
118
+          <div class="delete-msg flex items-center" @click="clearUnreadMsgsByType(1)">
119
+            <img src="https://we-spa.oss-cn-shenzhen.aliyuncs.com/pad_clerk/home/clearMsg.png" alt />
120
+            <div class="">清除未读</div>
121
+          </div>
122
+        </div>
123
+        <div class="detail-msg-con">
124
+          <van-list 
125
+            v-model="detailSuccessMsgListLoading"
126
+            :finished="detailSuccessMsgListFinished"
127
+            finished-text="没有更多了"
128
+            @load="getMessageByType(orderMsgType)"
129
+            :immediate-check="false"
130
+          >
131
+            <div class="msg-bar flex justify-between items-center" 
132
+              v-for="(item, index) in msgSuccessDetailList" 
133
+              :key="index"
134
+              @click="readMsgToOrderDetails(item)"
135
+            >
136
+              <div class="info flex">
137
+                <!-- <div class="name">张三</div>
138
+                <div class="project">121212122</div> -->
139
+                {{item.msg | ellipsis(50)}}
140
+              </div>
141
+              <div class="flex flex-column items-center">
142
+                <div class="time">{{item.create_time}}</div>
143
+                <div class="dot" v-if="!item.is_read && successUnread"></div>
144
+              </div>
145
+            </div>
146
+          </van-list>
147
+        </div>
52 148
       </div>
53 149
     </minePupop>
150
+    <minePupop :show="msgCancelDetailPupopVisible">
151
+      <div class="block detail">
152
+        <div class="title">
153
+          <div @click="backMsgPanel" class="back flex items-center">
154
+            <img src="https://we-spa.oss-cn-shenzhen.aliyuncs.com/pad_clerk/icon/slices/back.png" alt="" />
155
+          </div>
156
+          <div class="txt">消息</div>
157
+          <div class="delete-msg flex items-center" @click="clearUnreadMsgsByType(2)">
158
+            <img src="https://we-spa.oss-cn-shenzhen.aliyuncs.com/pad_clerk/home/clearMsg.png" alt />
159
+            <div class="">清除未读</div>
160
+          </div>
161
+        </div>
162
+        <div class="detail-msg-con">
163
+          <van-list 
164
+            v-model="detailCancelMsgListLoading"
165
+            :finished="detailCancelMsgListFinished"
166
+            finished-text="没有更多了"
167
+            @load="getMessageByType(orderMsgType)"
168
+            :immediate-check="false"
169
+          >
170
+            <div class="msg-bar flex justify-between items-center"
171
+              v-for="(item, index) in msgCancelDetailList"
172
+              :key="index"
173
+              @click="readMsgToOrderDetails(item)"
174
+            >
175
+              <div class="info flex">
176
+                <!-- <div class="name">张三</div>
177
+                <div class="project">121212122</div> -->
178
+                {{item.msg | ellipsis(50)}}
179
+              </div>
180
+              <div class="flex flex-column items-center">
181
+                <div class="time">{{item.create_time}}</div>
182
+                <div class="dot" v-if="!item.is_read"></div>
183
+              </div>
184
+            </div>
185
+          </van-list>
186
+        </div>
187
+      </div>
188
+    </minePupop>
189
+    <audio ref="orderSuccessMp3" id="orderSuccessMp3" muted>
190
+      <source src="@/assets/audio/order_success.mp3" />
191
+    </audio>
192
+    <audio ref="orderReadyMp3_15" id="orderReadyMp3_15" muted>
193
+      <source src="@/assets/audio/order_ready_15.mp3" />
194
+    </audio>
195
+    <audio ref="orderReadyMp3_5" id="orderReadyMp3_5" muted>
196
+      <source src="@/assets/audio/order_ready_5.mp3" />
197
+    </audio>
54 198
   </div>
55 199
 </template>
56 200
 
57 201
 <script type="text/javascript">
58 202
 import { mapMutations } from 'vuex'
203
+import vanList from 'vant/lib/list';
204
+import 'vant/lib/list/style';
59 205
 import leftMenu from './leftMenu'
60 206
 import minePupop from "../../../components/minePupop/index.vue";
61 207
 import api from '@/server/home'
@@ -72,42 +218,92 @@ export default {
72 218
         name: '333'
73 219
       },
74 220
       msgPupopVisible: false,
221
+      msgSuccessDetailPupopVisible: false,
222
+      msgCancelDetailPupopVisible: false,
75 223
       timer: null,
76
-      wsInstance: null
224
+      timer1: null,
225
+      wsInstance: null,
226
+      hasUnreadMessage: null,
227
+      msgPanelList: [],
228
+      mainPanelMsgListLoading: false,
229
+      mainPanelMsgListFinished: false,
230
+      mainPanelMessagePage: 1,
231
+      mainPanelMessageLimit: 5,
232
+      type: 0,
233
+      orderSuccessUnreadNum: null,
234
+      orderCancelUnreadNum: null,
235
+      detailMessageLimit: 10,
236
+      detailSuccessMessagePage: 1,
237
+      msgSuccessDetailList: [],
238
+      detailSuccessMsgListLoading: false,
239
+      detailSuccessMsgListFinished: false,
240
+      detailCancelMessagePage: 1,
241
+      msgCancelDetailList: [],
242
+      detailCancelMsgListLoading: false,
243
+      detailCancelMsgListFinished: false,
244
+      MsgType: null,
245
+      successUnread: true,
246
+      cancelUnread: true,
247
+      allUnread: true,
77 248
     }
78 249
   },
79
-  created () {
250
+  async created () {
80 251
     this.getUserInfo()
81 252
 
82
-      console.log('开始连接...')
83
-      let token = this.$store.state.comVal.token || localStorage.getItem('token')
84
-      //申请一个WebSocket对象,参数是服务端地址,同http协议使用http://开头一样,WebSocket协议的url使用ws://开头,另外安全的WebSocket协议使用wss://开头
85
-      this.wsInstance = new WebSocket(`wss://ws.ijolijoli.com?access_token=${token}`);
86
-      this.wsInstance.onopen = () => {
87
-        //当WebSocket创建成功时,触发onopen事件
88
-        console.log("连接成功");
89
-        this.timer = setInterval(() => {
90
-          this.wsInstance.send(JSON.stringify({type:'ping'}));
91
-        }, 30000);
92
-      }
93
-      this.wsInstance.onmessage = (e) => {
94
-        //当客户端收到服务端发来的消息时,触发onmessage事件,参数e.data包含server传递过来的数据
95
-        console.log('收到消息',e.data)
96
-        let data = JSON.parse(e.data);
97
-        console.log(data)
98
-      }
99
-      this.wsInstance.onclose = (e) => {
100
-        //当客户端收到服务端发送的关闭连接请求时,触发onclose事件
101
-        console.log("连接已关闭");
102
-      }
103
-      this.wsInstance.onerror = (e) => {
104
-        //如果出现连接、处理、接收、发送数据失败的时候触发onerror事件
105
-        console.log(e);
253
+    console.log('开始连接...')
254
+    let token = this.$store.state.comVal.token || localStorage.getItem('token')
255
+    //申请一个WebSocket对象,参数是服务端地址,同http协议使用http://开头一样,WebSocket协议的url使用ws://开头,另外安全的WebSocket协议使用wss://开头
256
+    this.wsInstance = new WebSocket(`wss://ws.ijolijoli.com?access_token=${token}`);
257
+    this.wsInstance.onopen = () => {
258
+      //当WebSocket创建成功时,触发onopen事件
259
+      console.log("连接成功");
260
+      this.timer = setInterval(() => {
261
+        this.wsInstance.send(JSON.stringify({type:'ping'}));
262
+      }, 30000);
263
+    }
264
+    this.wsInstance.onmessage = (e) => {
265
+      //当客户端收到服务端发来的消息时,触发onmessage事件,参数e.data包含server传递过来的数据
266
+      console.log('收到消息',e.data)
267
+      let data = JSON.parse(e.data);
268
+      if (data.data.type === 'order_success') {
269
+        console.log('预约成功信息播报')
270
+        this.$refs.orderSuccessMp3.play()
271
+      } else if (data.data.type === 'order_ready') {
272
+        // TODO: 播报动态语音还是固定的语音有待产品商榷
273
+        console.log('项目即将开始信息播报')
274
+        if (data.data.minute == 15) {
275
+          this.$refs.orderReadyMp3_15.play()
276
+        } else if (data.data.minute == 5) {
277
+          this.$refs.orderReadyMp3_5.play()
278
+        }
106 279
       }
280
+      console.log(data)
281
+    }
282
+    this.wsInstance.onclose = (e) => {
283
+      //当客户端收到服务端发送的关闭连接请求时,触发onclose事件
284
+      console.log("连接已关闭");
285
+    }
286
+    this.wsInstance.onerror = (e) => {
287
+      //如果出现连接、处理、接收、发送数据失败的时候触发onerror事件
288
+      console.log(e);
289
+    }
290
+
291
+    await this.queryHasUnreadMessage()
292
+    this.timer1 = setInterval(async() => {
293
+      await this.queryHasUnreadMessage()
294
+    }, 20000)
295
+  },
296
+  mounted () {},
297
+  beforeDestroy () {
298
+    // 关闭WebSocket连接并清除定时器
299
+    this.wsInstance.close()
300
+    clearInterval(this.timer)
301
+    clearInterval(this.timer1)
107 302
   },
108 303
   components: {
109 304
     leftMenu,
110
-    minePupop
305
+    minePupop,
306
+    vanList
111 307
   },
112 308
   methods: {
113 309
     ...mapMutations(['SAVE_COMMON_VALUE']),
@@ -134,6 +330,7 @@ export default {
134 330
       // 关闭WebSocket连接并清除定时器
135 331
       this.wsInstance.close()
136 332
       clearInterval(this.timer)
333
+      clearInterval(this.timer1)
137 334
       
138 335
       this.$router.replace('/login')
139 336
     },
@@ -146,9 +343,166 @@ export default {
146 343
     goBack () {
147 344
       this.$router.back()
148 345
     },
346
+    async queryHasUnreadMessage () {
347
+      let resp = await api.hasUnreadMessage()
348
+      if (resp.code === 200) {
349
+        this.hasUnreadMessage =  resp.data ? true : false
350
+      }
351
+    },
352
+    async getMainPanelMessageList (page = this.mainPanelMessagePage) {
353
+      // setTimeout(async() => {
354
+        let resp = await api.getMessageList({ page: page, limit: this.mainPanelMessageLimit })
355
+        if (resp.code = 200) {
356
+          this.orderSuccessUnreadNum = resp.data.reserved
357
+          this.orderCancelUnreadNum = resp.data.cancel
358
+
359
+          if (this.mainPanelMessagePage === 1) {
360
+            this.msgPanelList = resp.data.list
361
+          } else {
362
+            this.msgPanelList = [...this.msgPanelList, ...resp.data.list]
363
+          }
364
+
365
+          this.mainPanelMessagePage++
366
+          this.mainPanelMsgListLoading = false;
367
+          if (this.msgPanelList.length >= resp.data.total) {
368
+            this.mainPanelMsgListFinished = true;
369
+          }
370
+        }
371
+      // }, 1000);
372
+    },
373
+    async getMessageByType (type, page = this.detailSuccessMessagePage) {
374
+      if (type === 1) {
375
+        let resp = await api.getMessageByType({ type: type, page: page, limit: this.detailMessageLimit })
376
+        if (resp.code = 200) {
377
+
378
+          if (this.detailSuccessMessagePage === 1) {
379
+            this.msgSuccessDetailList = resp.data.list
380
+          } else {
381
+            this.msgSuccessDetailList = [...this.msgSuccessDetailList, ...resp.data.list]
382
+          }
383
+          
384
+          this.detailSuccessMessagePage++
385
+          this.detailSuccessMsgListLoading = false;
386
+          if (this.msgSuccessDetailList.length >= resp.data.total) {
387
+            this.detailSuccessMsgListFinished = true;
388
+          }
389
+        }
390
+      } else if (type === 2) {
391
+        let resp = await api.getMessageByType({ type: type, page: page, limit: this.detailMessageLimit })
392
+        if (resp.code = 200) {
393
+          this.msgCancelDetailList = [...this.msgCancelDetailList, ...resp.data.list]
394
+
395
+          if (this.detailSuccessMessagePage === 1) {
396
+            this.msgCancelDetailList = resp.data.list
397
+          } else {
398
+            this.msgCancelDetailList = [...this.msgCancelDetailList, ...resp.data.list]
399
+          }
400
+
401
+          this.detailCancelMessagePage++
402
+          this.detailCancelMsgListLoading = false;
403
+          if (this.msgCancelDetailList.length >= resp.data.total) {
404
+            this.detailCancelMsgListFinished = true;
405
+          }
406
+        }
407
+      }
408
+    },
149 409
     onAppMessage () {
410
+      this.msgPanelList = []
411
+      this.mainPanelMessagePage = 1
412
+      this.mainPanelMsgListLoading = false
413
+      this.mainPanelMsgListFinished = false
414
+      this.getMainPanelMessageList(1)
150 415
       this.msgPupopVisible = true
151
-    }
416
+    },
417
+    closeMsgPanel () {
418
+      this.msgPupopVisible = false
419
+    },
420
+    toMsgDetail (param) {
421
+      this.msgPupopVisible = false
422
+      // this.getMessageByType(param)
423
+      if (param === 1) {
424
+      this.msgSuccessDetailList = []
425
+      this.detailSuccessMessagePage = 1
426
+      this.detailSuccessMsgListLoading = false
427
+      this.detailSuccessMsgListFinished = false
428
+      this.getMessageByType(param, 1)
429
+
430
+        this.msgSuccessDetailPupopVisible = true
431
+      } else {
432
+      this.msgCancelDetailList = []
433
+      this.detailCancelMessagePage = 1
434
+      this.detailCancelMsgListLoading = false
435
+      this.detailCancelMsgListFinished = false
436
+      
437
+      this.getMessageByType(param, 1)
438
+
439
+        this.msgCancelDetailPupopVisible = true
440
+      }
441
+      this.orderMsgType = param
442
+      console.log(this.orderMsgType)
443
+    },
444
+    backMsgPanel () {
445
+      this.msgSuccessDetailPupopVisible = false
446
+      this.msgCancelDetailPupopVisible = false
447
+      
448
+      this.getMainPanelMessageList()
449
+      this.msgPupopVisible = true
450
+    },
451
+    async clearUnreadMsgsByType (type) {
452
+      let resp = await api.clearMessage({ type: type })
453
+      if (resp.code === 200) {
454
+        if (type === 1) {
455
+          this.getMessageByType(this.orderMsgType)
456
+          this.successUnread = false
457
+        } else if (type === 2) {
458
+          this.getMessageByType(this.orderMsgType)
459
+          this.cancelUnread = false
460
+        } else if (type === 0) {
461
+          this.getMainPanelMessageList()
462
+          this.allUnread = false
463
+        }
464
+      }
465
+    },
466
+    async readMsgToOrderDetails (source) {
467
+      // console.log(source)
468
+      if (!source.is_read) {
469
+        let clearMsgByIdResp = await api.clearMessageById({id: source.id})
470
+        if (clearMsgByIdResp.code === 200) {
471
+          this.getMainPanelMessageList()
472
+        }
473
+      }
474
+      if (source.type === 'BUY' || source.type === 'BUY_CARD') return
475
+      // return
476
+      let orderInfoResp = await api.getOrderInfo({ id: source.order_id })
477
+      if (orderInfoResp.code === 200) {
478
+        if (orderInfoResp.data.order_data.status == 0) {
479
+          // 跳转前关闭所有弹窗
480
+          this.msgPupopVisible = false
481
+          this.msgSuccessDetailPupopVisible = false
482
+          this.msgCancelDetailPupopVisible = false
483
+
484
+          this.$router.push({
485
+            path: '/confirmOrder/details',
486
+            query: {
487
+              id: source.order_id
488
+            }
489
+          })
490
+        } else {
491
+          this.msgPupopVisible = false
492
+          this.msgSuccessDetailPupopVisible = false
493
+          this.msgCancelDetailPupopVisible = false
494
+          
495
+          this.$router.push({
496
+            path: "/historicalOrder/details",
497
+            query: {
498
+              id: source.order_id
499
+            }
500
+          });
501
+        }
502
+      } else {
503
+        this.$message.error("未查到此订单")
504
+      }
505
+    },
152 506
   },
153 507
   computed: {
154 508
     routerItems () {
@@ -168,6 +522,14 @@ export default {
168 522
         }
169 523
       }
170 524
       return resultArr;
525
+    },
526
+    orderMsgType: {
527
+      get () {
528
+        return this.MsgType
529
+      },
530
+      set (val) {
531
+        this.MsgType = val
532
+      } 
171 533
     }
172 534
   },
173 535
 }
@@ -177,6 +539,25 @@ export default {
177 539
 <style lang="less" scoped>
178 540
 @import url(../../../style/root.less);
179 541
 
542
+.flex {
543
+  display: flex;
544
+}
545
+.flex-column {
546
+  flex-direction: column;
547
+}
548
+.justify-center {
549
+  justify-content: center;
550
+}
551
+.justify-between {
552
+  justify-content: space-between;
553
+}
554
+.justify-around {
555
+  justify-content: space-around;
556
+}
557
+.items-center {
558
+  align-items: center;
559
+}
560
+
180 561
 .layout {
181 562
   height: 100vh;
182 563
   display: flex;
@@ -286,23 +667,145 @@ export default {
286 667
     background-color: #f7f8fa;
287 668
   }
288 669
 }
670
+.dot {
671
+  width: 9px;
672
+  height: 9px;
673
+  border-radius: 50%;
674
+  background-color: #FF6945;
675
+  margin-top: 10px;
676
+}
677
+.dot-activated {
678
+  background-color: #fff;
679
+}
289 680
 .block {
290 681
   width: 540px;
291
-  height: 550px;
682
+  height: 400px;
683
+  padding: 20px;
684
+  box-sizing: border-box;
292 685
   background: #ffffff;
293 686
   border-radius: 8px;
294 687
   position: relative;
295
-  .delete-pupop {
296
-    position: absolute;
297
-    width: 32px;
298
-    height: 32px;
299
-    top: 5px;
300
-    right: 5px;
301
-    img {
302
-      width: 100%;
303
-      height: 100%;
304
-      display: block;
688
+  .title {
689
+    display: flex;
690
+    justify-content: space-between;
691
+    font-size: 14px;
692
+    .clear {
693
+      display: flex;
694
+      align-items: center;
695
+      color: #999999;
696
+      img {
697
+        width: 32px;
698
+        height: 32px;
699
+      }
700
+    }
701
+    .txt {
702
+      display: flex;
703
+      align-items: center;
704
+    }
705
+    .delete-pupop {
706
+      width: 32px;
707
+      height: 32px;
708
+      img {
709
+        width: 100%;
710
+        height: 100%;
711
+        display: block;
712
+      }
305 713
     }
306 714
   }
715
+  .msg-con {
716
+    height: 290px;
717
+    overflow: auto;
718
+    margin-top: 21px;
719
+    .order-msg {
720
+      .success, .cancel {
721
+        .desc {
722
+          img {
723
+            width: 36px;
724
+            height: 36px;
725
+          }
726
+          .title {
727
+            margin-left: 17px;
728
+          }
729
+        }
730
+        .count {
731
+          .time {
732
+            color: #999999;
733
+            margin-bottom: 4px;
734
+          }
735
+          .num {
736
+            width: 25px;
737
+            height: 25px;
738
+            // line-height: 21px;
739
+            // text-align: center;
740
+            display: flex;
741
+            justify-content: center;
742
+            align-items: center;
743
+            padding: 8px;
744
+            box-sizing: border-box;
745
+            color: #ffffff;
746
+            border-radius: 50%;
747
+            background-color: #FF6945;
748
+            
749
+          }
750
+        }
751
+      }
752
+      .cancel {
753
+        margin-top: 23px;
754
+      }
755
+    }
756
+    .ready-msg {
757
+      margin-top: 20px;
758
+      .content-bar {
759
+        .desc-info {
760
+          color: #666666;
761
+          font-weight: 400;
762
+        }
763
+        .desc-time {
764
+          width: 400px;
765
+          margin-top: 5px;
766
+          font-weight: 500;
767
+          line-height: 18px;
768
+        }
769
+        
770
+      }
771
+      .count {
772
+        .time {
773
+          color: #999999;
774
+        }
775
+      }
776
+    }
777
+  }
778
+}
779
+.detail {
780
+  .title {
781
+    .back {
782
+      img {
783
+        width: 24px;
784
+        height: 24px;
785
+      }
786
+    }
787
+    .delete-msg {
788
+      img {
789
+        width: 32px;
790
+        height: 32px;
791
+      }
792
+    }
793
+  }
794
+  .msg-bar {
795
+    margin-top: 18px;
796
+    .info {
797
+      width: 400px;
798
+      line-height: 18px;
799
+      .name {
800
+        font-weight: 600;
801
+        margin-right: 5px;
802
+      }
803
+      .project {}
804
+    }
805
+  }
806
+}
807
+.detail-msg-con {
808
+  height: 330px;
809
+  overflow: auto;
307 810
 }
308 811
 </style>

+ 24 - 0
src/server/home.js

@@ -157,4 +157,28 @@ export default class Home {
157 157
     return $http.get(url.reservedRecords, params)
158 158
   }
159 159
 
160
+  // 清除未读消息  0清除所有 1清除预约成功 2清除取消
161
+  static clearMessage (type) {
162
+    return $http.get(url.clearMessage, type)
163
+  }
164
+
165
+  // 根据Id清除未读消息  消息记录id
166
+  static clearMessageById (id) {
167
+    return $http.get(url.clearMessageById, id)
168
+  }
169
+
170
+  // 获取消息列表 (成功/失败)  1预约成功 2取消预约
171
+  static getMessageByType ({ type, page, limit }) {
172
+    return $http.get(url.getMessageByType, { type, page, limit })
173
+  }
174
+
175
+  // 获取消息列表
176
+  static getMessageList ({ page, limit }) {
177
+    return $http.get(url.getMessageList, { page, limit })
178
+  }
179
+
180
+  // 获取是否有未读消息
181
+  static hasUnreadMessage () {
182
+    return $http.get(url.hasUnreadMessage)
183
+  }
160 184
 }

+ 17 - 2
src/server/urls.js

@@ -94,7 +94,22 @@ export default {
94 94
   // 创建标签
95 95
   schemeSave: '/v2/pad/scheme/save',
96 96
 
97
-    // 用户预约记录
98
-    reservedRecords: '/v2/pad/reserved/index'
97
+  // 用户预约记录
98
+  reservedRecords: '/v2/pad/reserved/index',
99
+
100
+  // 清除未读消息
101
+  clearMessage: '/v2/pad/message/batch_read',
102
+
103
+  // 根据Id清除未读消息
104
+  clearMessageById: '/v2/pad/message/read',
105
+
106
+  // 获取消息列表 (成功/失败)
107
+  getMessageByType: '/v2/pad/message/type_list',
108
+
109
+  // 获取消息列表
110
+  getMessageList: '/v2/pad/message/get_list',
111
+
112
+  // 获取是否有未读消息
113
+  hasUnreadMessage: '/v2/pad/message/get_message'
99 114
 
100 115
 }