chat
This commit is contained in:
parent
2906012920
commit
e3db4d2f29
45
assets/js/socket.js
Normal file
45
assets/js/socket.js
Normal file
@ -0,0 +1,45 @@
|
||||
const that = {
|
||||
controller: new Map(),
|
||||
connection: null,
|
||||
onclose: null,
|
||||
onerror: null,
|
||||
onopen: null,
|
||||
onmessage: null,
|
||||
delay: 0,
|
||||
init: (link) => {
|
||||
that.connection = new WebSocket(link)
|
||||
that.connection.onopen = (event) => {
|
||||
that.delay = 0
|
||||
console.log("Open connection")
|
||||
that.connection.send(JSON.stringify({ fm: "chat", data: `Link Start! ${that.delay}` }))
|
||||
// 检查消息版本, 从最后时间向前查20条
|
||||
// 当向上滚动时, 从本地最早时间向前查询20条
|
||||
// 落日志与合并日志
|
||||
if (that.onopen) that.onopen();
|
||||
}
|
||||
that.connection.onmessage = (event) => {
|
||||
console.log("[message]", event.data)
|
||||
let data = JSON.parse(event.data)
|
||||
console.log(event.data, "xxxxxxxxxxxxxx")
|
||||
let call = that.controller.get(data.fm)
|
||||
if (call) call(data)
|
||||
if (that.onmessage) that.onmessage();
|
||||
}
|
||||
that.connection.onclose = (event) => {
|
||||
if (event.wasClean) {
|
||||
console.log(`[close] code=${event.code} reason=${event.reason}`);
|
||||
} else {
|
||||
that.delay++
|
||||
console.log(`[close] 连接中断${that.delay}第次, 尝试重连(延时${that.delay} s)`);
|
||||
setTimeout(that.init(link), that.delay * 1000)
|
||||
}
|
||||
if (that.onclose) that.onclose()
|
||||
};
|
||||
that.connection.onerror = (error) => {
|
||||
console.log(`[error] ${error.message}`);
|
||||
if (that.onerror) that.onerror()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default that
|
@ -21,7 +21,11 @@ button
|
||||
color: #ffffff
|
||||
border: none
|
||||
border-radius: .25rem
|
||||
|
||||
cursor: pointer
|
||||
padding-left: 1rem
|
||||
padding-right: 1rem
|
||||
min-height: 2rem
|
||||
font-weight: 600
|
||||
a
|
||||
text-decoration: none
|
||||
a:link //未访问的
|
||||
|
50
components/DialogueList.vue
Normal file
50
components/DialogueList.vue
Normal file
@ -0,0 +1,50 @@
|
||||
<template lang="pug">
|
||||
.dialogue-list
|
||||
.post(v-for="item in data", :key="item._id")
|
||||
.left
|
||||
.avatar
|
||||
.right
|
||||
.name Last
|
||||
.message {{ item.data }}
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ["data"],
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
.dialogue-list
|
||||
.post
|
||||
display: flex
|
||||
margin: 1rem 0
|
||||
.left
|
||||
justify-content: center
|
||||
align-items: center
|
||||
.avatar
|
||||
width: 2rem
|
||||
height: 2rem
|
||||
background: #ccc
|
||||
border-radius: 50%
|
||||
margin: .5rem auto
|
||||
.right
|
||||
padding: 0 2rem
|
||||
.name
|
||||
color: #999
|
||||
font-size: .8rem
|
||||
.message
|
||||
background: #ffffff
|
||||
padding: 1rem
|
||||
border-radius: 1rem
|
||||
position: relative
|
||||
|
||||
&::before
|
||||
content: ""
|
||||
position: absolute
|
||||
top: 10px
|
||||
left: -1rem
|
||||
border-top: 20px solid #ffffff
|
||||
border-left: 1rem solid transparent
|
||||
border-right: 1rem solid transparent
|
||||
</style>
|
@ -1,10 +1,13 @@
|
||||
<template lang="pug">
|
||||
.main
|
||||
header.header
|
||||
nav.navbar.main-width
|
||||
NuxtLink.navbar-logo(to="/") Kana
|
||||
NuxtLink.navbar-item(to="/") 主页
|
||||
.expnone
|
||||
.circumscription
|
||||
.logo Kana
|
||||
nav.navbar
|
||||
NuxtLink.navbar-item(to="/") 论坛
|
||||
NuxtLink.navbar-item(to="/docs") 文档
|
||||
NuxtLink.navbar-item(to="/chat") 聊天室
|
||||
.online
|
||||
.navbar-user(v-if="account.online")
|
||||
NuxtLink.userinfo(to="/account")
|
||||
img.avatar(:src="account.avatar")
|
||||
@ -12,21 +15,42 @@
|
||||
.navbar-sign(v-else)
|
||||
NuxtLink.button(to="/account/signin") Signin
|
||||
NuxtLink.button(to="/account/create") Login
|
||||
.websocket(:class="{ on: websocket }")
|
||||
Nuxt
|
||||
footer.footer
|
||||
p
|
||||
b Kana
|
||||
.github
|
||||
a(href="https://github.com/InvisibleFuture/kana")
|
||||
span.fab.fa-github
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import "assets/sass/main.sass";
|
||||
import "assets/sass/default.sass";
|
||||
import "@/assets/sass/main.sass";
|
||||
import "@/assets/sass/default.sass";
|
||||
|
||||
import socket from "@/assets/js/socket.js";
|
||||
|
||||
export default {
|
||||
data: () => ({
|
||||
websocket: false,
|
||||
}),
|
||||
computed: {
|
||||
account() {
|
||||
return this.$store.state.account;
|
||||
},
|
||||
},
|
||||
beforeMount() {
|
||||
// 如果掉线调用变红, 如果上线调用变绿
|
||||
socket.onclose = () => {
|
||||
this.websocket = false;
|
||||
};
|
||||
socket.onopen = () => {
|
||||
this.websocket = true;
|
||||
};
|
||||
let protocol = location.protocol === "https:" ? "wss:" : "ws:";
|
||||
socket.init(`${protocol}//${location.host}/api/`);
|
||||
},
|
||||
mounted() {
|
||||
console.log(
|
||||
"%c こめいじ さとり %c satori.love ",
|
||||
@ -39,40 +63,39 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="sass">
|
||||
.block
|
||||
padding-top: 10rem
|
||||
padding-bottom: 10rem
|
||||
.websocket
|
||||
background: red
|
||||
border-radius: 50%
|
||||
width: 1rem
|
||||
height: 1rem
|
||||
margin: .25rem .5rem
|
||||
.websocket.on
|
||||
background: green
|
||||
|
||||
@media (min-width: 480px)
|
||||
.main-width
|
||||
margin: 0 2rem
|
||||
|
||||
@media (min-width: 1280px)
|
||||
.main-width
|
||||
max-width: 1200px
|
||||
margin: auto
|
||||
|
||||
header.header
|
||||
//background-color: rgba(0, 0, 0, .8)
|
||||
nav.navbar
|
||||
.main
|
||||
>header.header>div
|
||||
display: flex
|
||||
align-items: flex-end
|
||||
padding-top: .5rem
|
||||
>.logo
|
||||
font-size: 2rem
|
||||
font-weight: 900
|
||||
margin-right: 1.5rem
|
||||
>nav.navbar
|
||||
flex: 1
|
||||
display: flex
|
||||
align-items: center
|
||||
.navbar-logo
|
||||
//color: #fff
|
||||
margin: 0 1rem
|
||||
font-size: 1.2rem
|
||||
font-weight: 600
|
||||
//justify-content: center
|
||||
.navbar-item
|
||||
//color: #eee
|
||||
padding: 1rem
|
||||
font-size: 1.2rem
|
||||
margin: 0 .25rem
|
||||
padding: 0 .75rem
|
||||
height: 2rem
|
||||
line-height: 2rem
|
||||
text-align: center
|
||||
font-weight: 600
|
||||
.navbar-item:hover
|
||||
//color: #fff
|
||||
.expnone
|
||||
flex: 1
|
||||
>.online
|
||||
.navbar-user
|
||||
.userinfo
|
||||
//color: #ffffff
|
||||
font-weight: 600
|
||||
display: flex
|
||||
align-items: center
|
||||
@ -81,15 +104,10 @@ header.header
|
||||
height: 24px
|
||||
border-radius: 50%
|
||||
margin-right: .5rem
|
||||
|
||||
footer.footer
|
||||
text-align: center
|
||||
margin: 4rem
|
||||
|
||||
a.button
|
||||
border: none
|
||||
border-radius: .25rem
|
||||
padding: .5rem 1rem
|
||||
margin: 1rem .5rem
|
||||
background-color: #007bff
|
||||
color: #ffffff
|
||||
padding: 4rem
|
||||
.github
|
||||
font-size: 2rem
|
||||
</style>
|
||||
|
64
pages/chat/index.vue
Normal file
64
pages/chat/index.vue
Normal file
@ -0,0 +1,64 @@
|
||||
<template lang="pug">
|
||||
.chat-index
|
||||
.circumscription
|
||||
p Chat 频道列表 {{ chatlist.length }}
|
||||
ul(v-if="chatlist.length")
|
||||
li(v-for="item in chatlist", :key="item._id")
|
||||
p {{ item.name }}
|
||||
button(@click="create") 创建频道
|
||||
.ceremony
|
||||
.circumscription
|
||||
span chat
|
||||
DialogueList(:data="chatactive")
|
||||
textarea.dialogue(v-model="chat.data", rows="12")
|
||||
button.submit(@click="submit") 发表
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import socket from "@/assets/js/socket.js";
|
||||
|
||||
export default {
|
||||
asyncData({ $axios }) {
|
||||
return $axios("/api/chat").then((res) => {
|
||||
return {
|
||||
chatlist: res.data,
|
||||
chat: { data: "" },
|
||||
chatactive: [{ _id: "2333", data: "cacd" }],
|
||||
};
|
||||
});
|
||||
},
|
||||
mounted() {
|
||||
socket.controller.set("chat", (data) => {
|
||||
this.chatactive.push(data);
|
||||
console.log(data);
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
create() {
|
||||
let data = { name: "FM DEMO", data: "23333" };
|
||||
this.$axios.post("/api/chat", data).then((res) => {
|
||||
console.log(res.data);
|
||||
});
|
||||
},
|
||||
submit() {
|
||||
socket.connection.send(
|
||||
JSON.stringify({
|
||||
fm: "chat",
|
||||
data: this.chat.data,
|
||||
})
|
||||
);
|
||||
this.chat.data = "";
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="sass">
|
||||
.chat-index
|
||||
textarea.dialogue
|
||||
width: 100%
|
||||
padding: 1rem
|
||||
border: 1px solid #eee
|
||||
border-radius: .5rem
|
||||
box-sizing: border-box
|
||||
</style>
|
Loading…
Reference in New Issue
Block a user