This commit is contained in:
satori 2022-01-31 14:21:50 +08:00
parent 2906012920
commit e3db4d2f29
5 changed files with 242 additions and 61 deletions

45
assets/js/socket.js Normal file
View 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

View File

@ -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 //未访问的

View 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>

View File

@ -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
View 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>