提交 666de122 authored 作者: 王鹏飞's avatar 王鹏飞

init

上级 92e5e24a
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA9MjUExxOj6tfMUaU+t/k0+VokVkh1GVZACLPdxR2VcjjOkaI
qloY4TK4/uybncLhoqu9ggyiJFNmXVLxe2TxReGXhR8tAc0RTCuaFv0oHJ7HXI48
CZ/zc8sgjyd7XsuyRurKwpHWXfy9FMHE7r/9R+IUHAkIPmZ17qlwqphlePK8I1fn
DU/LOvglXPIlR55TUe6NKVoCPZXQEHHPZClH0qdnXFiUq5I1f6GMUoGCbV5DLECb
OAndCP/snqakw8oeLmoBGSig/FGrc/41l2DJxyIxm/CfaEhfnSN4hvOTAFXcro9c
gyy88H1BfT/bEhM7OO+RRaKUrV5CieeIOEmvGQIDAQABAoIBAGmkcsJ8qPsgPskJ
aSqMjjlU/Lgd+5eq1apVW6xMzHVhaY+w+TJsB+jI90Yt30tK3A5UiEkkIqYCyF7m
eQmEGwzJu5bcSZRJaHmzJ6FcSH9xlyC+0fJlcbA7riWaKIhU6O/qTO+D+Tw+42ud
5NwVR75KN9uRmlkz5xnFTraRZtm3MJmA7dwXK3hrN+dFJR2vLO3KBAtpgtpPdkK1
ObpJQ1Q7jsnEmODVRZ7n1CKZEDmXd8GBPA/jCVqgiEbVVCdkhHkyxyIMQenBReyy
tJIPf7CdL3O3PPsThhMa1P2CP/xehS4bcQSLw9wtNTJcvVPHTvffHKOKUfhUxkHu
0cpl+zECgYEA/jzySW/br7W+xS2e4VBHzY+UZJwxd/3mY3d/kasMV1zuipr6WOhQ
FVsd5uJXPRr+rHBypwyOIlP205V2K5oQEK0yT+tF+IBvKGdJv89wskCgrXcD3Kfb
dCFbt014pHw89A8jb8LBbGOPH6jhZhGkxP33CJdVPtncUc4m0hj4HHcCgYEA9nsc
KcCZOIYRlZmJ93DoukhjxaouGFDTOZoujaqasrfXUaWRnpZYekDZWa1NneOzLBEz
h1RwPcmeYLCVRmXtpRzLOKXfJY0gGSJr979I0AVkzj8A9NZcU/HxUP0GqpwBbzAp
EEShQVhjYppQ62KAwZ1tbsVWX2V1SBsa3McExO8CgYEA6kVy5aTDhOgugDeHnguB
/rN9hDBBjVZTQ/jLfolld+NUlDg21FJN6T/rD+Qli1MitfdwTupM1ukUGugw2gC/
KP7Py8D62wBObaav2KXoLPlMlkuDLYMnv501jHVA5CDvcd25Q7Ts01nyerP97zX2
5Oc5CZuZm67ZTDBwqU0E5AUCgYBIC2wL+DPRBb8WDy74mJQt/wLKwBeBG/7hk2OQ
HRHis0HIp7CMvj1WXqYpRDKvt+KjOtPo9pFoPgqBEJxRW3G/FU+BW1qCS2HadulA
HTVXOHxinJ/W8OFD2DBFD/Bm5fq1WUpnaugHhaJnK9wDMWOZND7MZfn9IFbLoMCV
T8bhGQKBgG7qsZhI9ldAqooZQ1xSua/2SBc8GI8d03g7y8kZkkx/XclbEz6X6wUu
U3PVL+neY8Qw3JxC1cHS++KIdHR2ZSoTpF00A4QvDJL0+eo1KgI88vRV8QaWLxPB
ahvXwmkKW2+jgvCAqFtepZx/KsKpQW+x3GOJyhl2tIT8sZwRmE6u
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIFhzCCBG+gAwIBAgIQCzEi4VmynSzbyBV1UEXGojANBgkqhkiG9w0BAQsFADBu
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMS0wKwYDVQQDEyRFbmNyeXB0aW9uIEV2ZXJ5d2hlcmUg
RFYgVExTIENBIC0gRzEwHhcNMjAxMTA5MDAwMDAwWhcNMjExMTA5MjM1OTU5WjAa
MRgwFgYDVQQDEw9kZXYuZXppamluZy5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB
DwAwggEKAoIBAQD0yNQTHE6Pq18xRpT63+TT5WiRWSHUZVkAIs93FHZVyOM6Roiq
WhjhMrj+7JudwuGiq72CDKIkU2ZdUvF7ZPFF4ZeFHy0BzRFMK5oW/SgcnsdcjjwJ
n/NzyyCPJ3tey7JG6srCkdZd/L0UwcTuv/1H4hQcCQg+ZnXuqXCqmGV48rwjV+cN
T8s6+CVc8iVHnlNR7o0pWgI9ldAQcc9kKUfSp2dcWJSrkjV/oYxSgYJtXkMsQJs4
Cd0I/+yepqTDyh4uagEZKKD8Uatz/jWXYMnHIjGb8J9oSF+dI3iG85MAVdyuj1yD
LLzwfUF9P9sSEzs475FFopStXkKJ54g4Sa8ZAgMBAAGjggJzMIICbzAfBgNVHSME
GDAWgBRVdE+yck/1YLpQ0dfmUVyaAYca1zAdBgNVHQ4EFgQUkRHkmubxZAvEWtCY
IBT9sw/3Yb8wGgYDVR0RBBMwEYIPZGV2LmV6aWppbmcuY29tMA4GA1UdDwEB/wQE
AwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwTAYDVR0gBEUwQzA3
BglghkgBhv1sAQIwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQu
Y29tL0NQUzAIBgZngQwBAgEwgYAGCCsGAQUFBwEBBHQwcjAkBggrBgEFBQcwAYYY
aHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEoGCCsGAQUFBzAChj5odHRwOi8vY2Fj
ZXJ0cy5kaWdpY2VydC5jb20vRW5jcnlwdGlvbkV2ZXJ5d2hlcmVEVlRMU0NBLUcx
LmNydDAJBgNVHRMEAjAAMIIBBAYKKwYBBAHWeQIEAgSB9QSB8gDwAHYA9lyUL9F3
MCIUVBgIMJRWjuNNExkzv98MLyALzE7xZOMAAAF1qpa6jQAABAMARzBFAiAwHOcp
Ua1H0WK4OZUHiQ1rndqnYxPHhP9XWunwpRMoagIhAOB2MPSW9M4qj6Yih7eQkydl
lgawpoBZzRzhisU+TN67AHYAXNxDkv7mq0VEsV6a1FbmEDf71fpH3KFzlLJe5vbH
DsoAAAF1qpa63gAABAMARzBFAiEA92ZeW0PgyWW3j+3wypLS0O/wI63C+x0WTvMZ
Vngp6AMCIBoThjaKif+XY11YbaV89ndqs1nDlzbEfBrFftoB9fchMA0GCSqGSIb3
DQEBCwUAA4IBAQA2geo9wQAd+vx+lwAafVRxCBQyBiS0qT413ewYpZYDnSkLX0l1
5kRdxDGWQhPzOio0ckj/jOtOlbbSsiovBBVTyYPB8WfkNjMd0psMNx2e6Wy/WKkQ
X3DqEOB4XGg0RwpebiAmz6lWxyFwIAbCrwCntkkaIF4LnIvczn6pvPFBtK2nXJJC
HL0Igbxo+xJLt3Hql7TcwkFDXz/LIB8AwhhkkhhwW45r3Eyjw8eOyzvflDPwSNH+
ByadQ+AH4H4vYYVo0ILNIPCdaokLQ+u4FttB9VQ+iGmpJ56Yg2muxWh8Qckca+vH
40RbC5aK1RSy2RIRpC5fwvq2JuV/CksP5G5Q
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEqjCCA5KgAwIBAgIQAnmsRYvBskWr+YBTzSybsTANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
QTAeFw0xNzExMjcxMjQ2MTBaFw0yNzExMjcxMjQ2MTBaMG4xCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xLTArBgNVBAMTJEVuY3J5cHRpb24gRXZlcnl3aGVyZSBEViBUTFMgQ0EgLSBH
MTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALPeP6wkab41dyQh6mKc
oHqt3jRIxW5MDvf9QyiOR7VfFwK656es0UFiIb74N9pRntzF1UgYzDGu3ppZVMdo
lbxhm6dWS9OK/lFehKNT0OYI9aqk6F+U7cA6jxSC+iDBPXwdF4rs3KRyp3aQn6pj
pp1yr7IB6Y4zv72Ee/PlZ/6rK6InC6WpK0nPVOYR7n9iDuPe1E4IxUMBH/T33+3h
yuH3dvfgiWUOUkjdpMbyxX+XNle5uEIiyBsi4IvbcTCh8ruifCIi5mDXkZrnMT8n
wfYCV6v6kDdXkbgGRLKsR4pucbJtbKqIkUGxuZI2t7pfewKRc5nWecvDBZf3+p1M
pA8CAwEAAaOCAU8wggFLMB0GA1UdDgQWBBRVdE+yck/1YLpQ0dfmUVyaAYca1zAf
BgNVHSMEGDAWgBQD3lA1VtFMu2bwo+IbG8OXsj3RVTAOBgNVHQ8BAf8EBAMCAYYw
HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBIGA1UdEwEB/wQIMAYBAf8C
AQAwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp
Y2VydC5jb20wQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2NybDMuZGlnaWNlcnQu
Y29tL0RpZ2lDZXJ0R2xvYmFsUm9vdENBLmNybDBMBgNVHSAERTBDMDcGCWCGSAGG
/WwBAjAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BT
MAgGBmeBDAECATANBgkqhkiG9w0BAQsFAAOCAQEAK3Gp6/aGq7aBZsxf/oQ+TD/B
SwW3AU4ETK+GQf2kFzYZkby5SFrHdPomunx2HBzViUchGoofGgg7gHW0W3MlQAXW
M0r5LUvStcr82QDWYNPaUy4taCQmyaJ+VB+6wxHstSigOlSNF2a6vg4rgexixeiV
4YSB03Yqp2t3TeZHM9ESfkus74nQyW7pRGezj+TC44xCagCQQOzzNmzEAP2SnCrJ
sNE2DpRVMnL8J6xBRdjmOsC3N6cQuKuRXbzByVBjCqAA8t1L0I+9wXJerLPyErjy
rMKWaBFLmfK/AHNF4ZihwPGOc7w6UHczBZXH5RFzJNnww+WnKuTPI0HfnVH8lg==
-----END CERTIFICATE-----
<template>
<header class="header">
<div class="logo"></div>
<div class="message"></div>
</header>
</template>
<script>
import Message from '@/main'
export default {
mounted() {
new Message({ el: '.message', source: 'MESSAGE_WEB' })
}
}
</script>
<style scoped>
.header {
display: flex;
justify-content: space-between;
max-width: 1000px;
margin: 0 auto;
padding: 10px 0;
}
</style>
\ No newline at end of file
import Vue from 'vue'
import App from './App.vue'
new Vue({
render: h => h(App)
}).$mount('#app')
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"name": "web-message-sdk",
"version": "0.1.0",
"private": true,
"private": false,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"build": "vue-cli-service build --target lib --name message ./src/main.js --report",
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^0.21.1",
"core-js": "^3.6.5",
"crypto-js": "^4.0.0",
"element-ui": "^2.15.1",
"qs": "^6.5.2",
"vue": "^2.6.11"
},
"devDependencies": {
......
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<title><%= htmlWebpackPlugin.options.title %></title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script>
<!-- 引入样式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css" />
<!-- 引入组件库 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
<strong
>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please
enable it to continue.</strong
>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
......
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
<div class="app-message">
<el-popover trigger="hover" width="350px" @show="handlePopoverShow">
<template #reference>
<div class="app-message-icon" @click="show">
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-bell"
viewBox="0 0 16 16"
>
<path
d="M8 16a2 2 0 0 0 2-2H6a2 2 0 0 0 2 2zM8 1.918l-.797.161A4.002 4.002 0 0 0 4 6c0 .628-.134 2.197-.459 3.742-.16.767-.376 1.566-.663 2.258h10.244c-.287-.692-.502-1.49-.663-2.258C12.134 8.197 12 6.628 12 6a4.002 4.002 0 0 0-3.203-3.92L8 1.917zM14.22 12c.223.447.481.801.78 1H1c.299-.199.557-.553.78-1C2.68 10.2 3 6.88 3 6c0-2.42 1.72-4.44 4.005-4.901a1 1 0 1 1 1.99 0A5.002 5.002 0 0 1 13 6c0 .88.32 4.2 1.22 6z"
/>
</svg>
<div class="dot" v-if="!!unreadCount"></div>
</div>
</template>
<message-popover
:unreadCount="unreadCount"
@read-success="getUnreadCount"
@view-more="show"
ref="message"
></message-popover>
</el-popover>
<el-dialog :visible.sync="visible" title="消息中心" :fullscreen="true">
<message v-if="visible" />
</el-dialog>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
import Message from '@/components/Message'
import MessagePopover from '@/components/MessagePopover'
import * as api from '@/api'
export default {
name: 'App',
components: {
HelloWorld
components: { Message, MessagePopover },
data() {
return {
visible: false,
unreadCount: 0
}
},
methods: {
// 获取未读消息总数
getUnreadCount() {
api.getUnreadCount().then(response => {
this.unreadCount = response.count
})
},
show() {
this.visible = true
},
handlePopoverShow() {
this.getUnreadCount()
this.$refs.message && this.$refs.message.getMessages()
}
},
mounted() {
this.getUnreadCount()
}
}
</script>
<style lang="scss">
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
<style scoped>
.app-message {
position: relative;
display: inline-block;
}
.app-message-icon {
position: relative;
display: inline-block;
cursor: pointer;
padding: 0 5px;
}
.dot {
position: absolute;
top: 0;
right: 0;
width: 3px;
height: 3px;
border-radius: 50%;
background-color: #ba053f;
}
</style>
</style>
\ No newline at end of file
import httpRequest from '@/utils/axios'
// 获取消息列表
export function getMessages(params) {
return httpRequest.get('/v1/messages/intra-station-messages', { params })
}
// 设置消息已读
export function readMessage(params) {
return httpRequest.get('/v1/messages/read', { params })
}
// 设置全部消息已读
export function readAllMessage(params) {
return httpRequest.get('/v1/messages/read-all', { params })
}
// 获取未读消息数量
export function getUnreadCount(params) {
return httpRequest.get('/v1/messages/unread-count', { params })
}
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
</ul>
<h3>Essential Links</h3>
<ul>
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
<template>
<div class="message">
<div class="message-hd">
<el-menu :default-active="type" @select="handleSelect">
<el-submenu v-for="item in menus" :key="item.id" :index="item.id">
<template #title>
<span>{{ item.title }}</span>
</template>
<el-menu-item v-for="item in item.children" :key="item.id" :index="item.id">
<template #title>{{ item.title }}</template>
</el-menu-item>
</el-submenu>
</el-menu>
</div>
<div class="message-bd">
<message-list :type="type" :key="type" v-bind="$attrs" v-on="$listeners"></message-list>
</div>
</div>
</template>
<script>
import MessageList from './MessageList.vue'
export default {
components: { MessageList },
data() {
return {
menus: [
{
title: '系统',
id: '0',
children: [
{ title: '公告', id: '2' },
{ title: '通知', id: '1' }
]
}
],
type: '2' // 2公告; 1通知
}
},
methods: {
handleTabClick(data) {
this.tabActive = data.value
},
handleSelect(index) {
this.type = index
}
}
}
</script>
<style scoped>
Ul,
li {
margin: 0;
padding: 0;
list-style: none;
}
.message {
display: flex;
}
.message-hd {
width: 125px;
min-height: 200px;
border-right: 1px solid #eee;
}
::v-deep .el-menu {
border-right: 0;
}
::v-deep .message-hd .el-submenu__title {
height: 40px;
font-size: 16px;
line-height: 40px;
color: #222;
padding: 0 !important;
}
::v-deep .message-hd .el-submenu .el-menu-item {
padding: 0 !important;
min-width: auto;
color: #999;
}
::v-deep .message-hd .el-submenu__title:hover {
background-color: transparent;
}
::v-deep .message-hd .el-menu-item:focus,
::v-deep .message-hd .el-menu-item:hover {
background-color: transparent;
color: #ba053f;
}
::v-deep .message-hd .el-submenu .el-menu-item {
height: 30px;
line-height: 30px;
}
::v-deep .message-hd .el-submenu .el-menu-item.is-active {
color: #ba053f;
}
.message-bd {
flex: 1;
padding-left: 20px;
}
</style>
\ No newline at end of file
<template>
<div class="message-content">
<div class="message-content-hd">
<h1>{{ data.title }}</h1>
<p>{{ data.send_time }}</p>
</div>
<div class="message-content-bd" v-html="data.payload"></div>
<el-button type="primary" @click="$emit('close')">我知道了</el-button>
</div>
</template>
<script>
import * as api from '@/api'
export default {
props: {
data: { type: Object, default: () => {} }
},
data() {
return {}
},
methods: {
readMessage() {
if (this.data.is_read) {
return
}
api.readMessage({ message_id: this.data.id }).then(() => {
this.$emit('read', this.data.id, this.data)
console.log('消息读取成功')
})
}
},
mounted() {
this.readMessage()
}
}
</script>
<style scoped>
.message-content-hd h1 {
margin: 0;
font-size: 16px;
font-weight: normal;
color: #222;
}
.message-content-hd p {
margin: 0;
padding: 10px 0;
color: #999;
}
.message-content-bd {
margin-bottom: 40px;
font-size: 14px;
color: #444;
}
.message-content .el-button {
display: block;
margin: 0 auto;
width: 140px;
}
</style>
\ No newline at end of file
<template>
<div class="message-item" :class="classes" @click="visible = true">
<div class="message-item-title">{{ data.title }}</div>
<div class="message-item-time">{{ data.send_time }}</div>
<el-dialog :visible.sync="visible" :append-to-body="true" title="消息详情" width="600px" v-if="visible">
<message-content :data="data" v-bind="$attrs" @close="visible = false" />
</el-dialog>
</div>
</template>
<script>
import MessageContent from '@/components/MessageContent'
export default {
props: {
data: { type: Object, default: () => {} }
},
inheritAttrs: false,
components: { MessageContent },
data() {
return {
visible: false
}
},
computed: {
classes() {
return {
'is-read': this.data.is_read
}
}
}
}
</script>
<style scoped>
.message-item {
padding: 8px 0;
font-size: 14px;
line-height: 20px;
color: #222;
border-top: 1px solid #eee;
cursor: pointer;
}
.message-item:first-child {
border-top: 0;
}
.message-item.is-read {
color: #999;
}
.message-item-time {
font-size: 12px;
color: #999;
}
</style>
\ No newline at end of file
<template>
<div v-loading="loading">
<el-radio-group size="small" v-model="tabActive" @change="init">
<el-radio-button v-for="item in tabList" :label="item.value" :key="item.value">{{ item.title }}</el-radio-button>
</el-radio-group>
<div class="message-list" v-if="messages.length">
<message-item v-for="item in messages" :data="item" :key="item.id" @read="handleRead" />
</div>
<p v-else>暂无消息</p>
<el-pagination
background
layout="prev, pager, next"
:total="total"
:current-page.sync="page"
@current-change="handleCurrentChange"
:hide-on-single-page="true"
class="message-pagination"
></el-pagination>
</div>
</template>
<script>
import * as api from '@/api'
import MessageItem from './MessageItem.vue'
export default {
props: { type: { type: String, default: '1' } },
components: { MessageItem },
data() {
return {
loading: false,
messages: [],
page: 1, // 当前页
total: 0, // 总数
tabList: [
{ title: '全部', value: '9999' },
{ title: '未读', value: '0' },
{ title: '已读', value: '1' }
],
tabActive: '9999'
}
},
methods: {
init() {
this.page = 1
this.getMessages()
},
getMessages() {
this.loading = true
api
.getMessages({ limit: 10, page: this.page, type: this.type, is_read: this.tabActive })
.then(response => {
this.messages = response.data
this.total = response.total
})
.finally(() => {
this.loading = false
})
},
// 翻页
handleCurrentChange() {
this.getMessages()
},
// 读取消息
handleRead(messageId) {
this.messages = this.messages.map(item => {
if (item.id === messageId) {
item.is_read = 1
}
return item
})
}
},
beforeMount() {
this.init()
}
}
</script>
<style scoped>
.message-list {
padding: 10px 0;
}
.message-pagination {
padding: 15px 0;
text-align: center;
}
</style>
\ No newline at end of file
<template>
<div class="message-popover">
<div class="message-popover-hd">
<div class="message-popover-hd__title">消息({{ unreadCount }}条未读)</div>
<div class="message-popover-hd__button" @click="handleReadAll">全部已读</div>
</div>
<div class="message-list" v-if="messages.length">
<message-item v-for="item in messages" :data="item" :key="item.id" @read="handleRead" />
</div>
<p v-else>暂无未读消息</p>
<el-button type="primary" size="small" @click="$emit('view-more')">查看更多</el-button>
</div>
</template>
<script>
import * as api from '@/api'
import MessageItem from './MessageItem.vue'
export default {
props: { unreadCount: { type: Number, default: 0 } },
components: { MessageItem },
data() {
return {
messages: []
}
},
methods: {
getMessages() {
const source = this.$option.source
api.getMessages({ limit: 4, type: 0, is_read: 0, source }).then(response => {
this.messages = response.data
})
},
// 读取消息
handleRead(messageId) {
this.messages = this.messages.map(item => {
if (item.id === messageId) {
item.is_read = 1
}
return item
})
this.$emit('read-success')
},
// 全部已读
handleReadAll() {
api.readAllMessage().then(this.handleReadAllSuccess)
},
handleReadAllSuccess() {
this.messages = this.messages.map(item => {
item.is_read = 1
return item
})
this.$emit('read-success')
}
},
beforeMount() {
this.getMessages()
}
}
</script>
<style scoped>
.message-popover-hd {
display: flex;
align-items: center;
padding: 10px 0;
}
.message-popover-hd__title {
flex: 1;
font-size: 16px;
}
.message-popover-hd__button {
font-size: 14px;
cursor: pointer;
color: #409eff;
}
.message-popover .el-button {
display: block;
width: 200px;
margin: 20px auto 10px;
}
</style>
\ No newline at end of file
import Vue from 'vue'
// import ElementUI from 'element-ui'
// import 'element-ui/lib/theme-chalk/index.css'
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
export default class Message {
constructor(option = {}) {
window.messageOption = option
Vue.prototype.$option = option
if (!Message.instance) {
Message.renderDom(option)
Message.instance = this
}
return Message.instance
}
// 渲染vue
static renderDom(option) {
new Vue({
render: h => h(App)
}).$mount(option.el)
}
// 初始化
static init(option, cb) {
if (!this.instance) {
this.instance = new Message(option, cb)
}
return this.instance
}
}
import axios from 'axios'
import qs from 'qs'
import md5 from 'crypto-js/md5'
const httpRequest = axios.create({
timeout: 60000,
withCredentials: true
})
// 请求拦截
httpRequest.interceptors.request.use(
function (config) {
const option = window.messageOption
config.baseURL = option.baseURL || 'https://test-microservices-message-service-api.ezijing.com'
// 默认参数
const defaultParams = {
source: option.source,
timestamp: parseInt(Date.now() / 1000),
nonce: Math.random().toString(36).slice(-8)
}
// 接口请求参数
let params = config.params || config.data
// 排序
function alphabeticalSort(a, b) {
return a.localeCompare(b)
}
// https://gitlab.ezijing.com/root/api-documents/-/blob/master/messages/api/%E7%8E%AF%E5%A2%83%E8%AF%B4%E6%98%8E.md#%E6%8E%A5%E5%8F%A3%E7%AD%BE%E5%90%8D
params = Object.assign({}, defaultParams, params)
let str = qs.stringify(Object.assign({}, params, { salt: 'n7xAav2tSjn9Ysnr' }), { sort: alphabeticalSort })
params.signature = md5(str).toString().toUpperCase()
if (config.method === 'post') {
config.data = params
} else {
config.params = params
}
return config
},
function (error) {
return Promise.reject(error)
}
)
// 响应拦截
httpRequest.interceptors.response.use(
function (response) {
return response.data.code ? Promise.reject(response.data) : response.data.data
},
function (error) {
return Promise.reject(error)
}
)
export default httpRequest
const fs = require('fs')
const path = require('path')
module.exports = {
pages: {
index: { entry: 'examples/main.js' }
},
css: {
extract: false
},
configureWebpack: {
externals: {
vue: 'Vue',
'element-ui': 'ElementUI'
},
output: {
libraryExport: 'default'
}
},
devServer: {
host: 'dev.ezijing.com',
https: {
key: fs.readFileSync(path.join(__dirname, './cert/dev.ezijing.com.key')),
cert: fs.readFileSync(path.join(__dirname, './cert/dev.ezijing.com.pem'))
},
proxy: {
'/v1': {
target: 'https://test-microservices-message-service-api.ezijing.com'
}
}
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论