效果图
实现
src/util/socket.ts
let websock: any = null;
let global_callback: any = null;
const serverPort = "8080"; // webSocket连接端口
const wsuri = "ws://" + window.location.hostname + ":" + serverPort + "/wsdemo";
function createWebSocket(callback: any) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
if (websock == null || typeof websock !== WebSocket) {
initWebSocket(callback);
}
}
function initWebSocket(callback: any) {
global_callback = callback;
// 初始化websocket
websock = new WebSocket(wsuri);
websock.onmessage = function (e: any) {
websocketonmessage(e);
};
websock.onclose = function (e: any) {
websocketclose(e);
};
websock.onopen = function () {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
websocketOpen();
};
// 连接发生错误的回调方法
websock.onerror = function () {
console.log("WebSocket连接发生错误");
//createWebSocket();啊,发现这样写会创建多个连接,加延时也不行
};
}
// 实际调用的方法
function sendSock(agentData: any) {
if (websock.readyState === websock.OPEN) {
// 若是ws开启状态
websocketsend(agentData);
} else if (websock.readyState === websock.CONNECTING) {
// 若是 正在开启状态,则等待1s后重新调用
setTimeout(function () {
sendSock(agentData);
}, 1000);
} else {
// 若未开启 ,则等待1s后重新调用
setTimeout(function () {
sendSock(agentData);
}, 1000);
}
}
function closeSock() {
websock.close();
}
// 数据接收
function websocketonmessage(msg: any) {
// console.log("收到数据:"+JSON.parse(e.data));
// console.log("收到数据:"+msg);
// global_callback(JSON.parse(msg.data));
// 收到信息为Blob类型时
let result: any = null;
// debugger
if (msg.data instanceof Blob) {
const reader = new FileReader();
reader.readAsText(msg.data, "UTF-8");
reader.onload = (e: any) => {
console.log(e);
if (typeof reader.result === "string") {
result = JSON.parse(reader.result);
}
//console.log("websocket收到", result);
global_callback(result);
};
} else {
result = JSON.parse(msg.data);
//console.log("websocket收到", result);
global_callback(result);
}
}
// 数据发送
function websocketsend(agentData: any) {
console.log("发送数据:" + agentData);
websock.send(agentData);
}
// 关闭
function websocketclose(e: any) {
console.log("connection closed (" + e.code + ")");
}
function websocketOpen(e: any) {
console.log(e);
console.log("连接打开");
}
export { sendSock, createWebSocket, closeSock };
src/store/webSocket.ts
import { defineStore } from "pinia";
export const webSocketStore = defineStore("webSocket", {
state: () => ({
//推送消息
data: [],
}),
getters: {},
actions: {
addMsg(val: any) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
this.data.push(val);
},
},
});
这里面放到了登录成功后在连接websocket
src/viwes/login.vue
<script setup lang="ts">
import { colorStore } from "@/store/color";
import { webSocketStore } from "@/store/webSocket";
import { createWebSocket } from "@/util/socket";
import { useRouter } from "vue-router";
import md5 from "js-md5"; //
import { ref } from "vue";
import loginApi from "@/api/loginApi";
import { ElNotification } from "element-plus";
const color = colorStore();
const webSocket = webSocketStore();
const routers = useRouter();
const username = ref("009999");
const password = ref("0");
const mes = ref();
const global_callback = (msg: any) => {
console.log("websocket的回调函数收到服务器信息:" + JSON.stringify(msg));
// console.log("收到服务器信息:" + msg);
mes.value = JSON.parse(JSON.stringify(msg));
webSocket.addMsg(mes);
ElNotification({
title: "您有一条新的消息y",
message: mes.value.key,
position: "bottom-right",
});
};
const login = () => {
let params = {
staffCode: username.value,
password: md5(password.value.toString()),
};
loginApi.login(params).then((res: any) => {
if (res) {
sessionStorage.setItem("organizationCode", res.hospitalCode);
sessionStorage.setItem("token", res.token);
sessionStorage.setItem("staffCode", res.staffCode);
sessionStorage.setItem("staffName", res.name);
sessionStorage.setItem("islogin", "true");
sessionStorage.setItem("roleList", JSON.stringify(res.roles));
sessionStorage.setItem("currectRole", JSON.stringify(res.roles[0]));
loginApi.queryMenuByRoleCode(res.roles[0].roleCode).then((res: any) => {
if (res) {
sessionStorage.setItem("menu", JSON.stringify(res));
routers.push("/");
}
});
createWebSocket(global_callback);
}
});
};
</script>
<template>
<div class="con" :style="{ '--color': color.color }">
<div id="box" class="login-container">
<div class="left-container">
<div class="title">
<span>
<img src="../../assets/hip.png" style="height: 15px" />{{
$t("base.title")
}}</span
>
</div>
<div class="input-container">
<input
type="text"
name="username"
placeholder="用户名"
v-model="username"
/>
<input
type="password"
name="password"
placeholder="密码"
v-model="password"
/>
</div>
<div class="message-container">
<span>Copyright © 2022 | {{ $t("login.GoodWill") }}</span>
</div>
</div>
<div class="right-container">
<div class="regist-container">
<span class="regist">{{ $t("login.WelcomeLogin") }}</span>
</div>
<div class="action-container" @click="login">
<span>{{ $t("login.submit") }}</span>
</div>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.con {
height: calc(100vh - 230px);
padding-top: 10%;
background-image: linear-gradient(
to bottom right,
rgb(114, 135, 254),
var(--color)
);
}
.login-container {
width: 600px;
height: 315px;
margin: 0 auto;
border-radius: 15px;
box-shadow: 0 10px 50px 0px rbg(59, 45, 159);
background-color: rgb(95, 76, 194);
}
#box {
// outline: 4px solid #fff;
position: relative;
overflow: hidden;
z-index: 1;
}
#box::before {
content: "";
position: absolute;
background: lightgray;
width: 500px;
height: 400px;
z-index: -2;
left: 50%;
top: 50%;
transform-origin: 0 0;
animation: rotate 5s infinite linear;
}
#box::after {
content: "";
position: absolute;
background: rgb(95, 76, 194);
width: calc(600px - 4px);
height: calc(315px - 4px);
left: 2px;
top: 2px;
border-radius: 15px;
z-index: -1;
}
@keyframes rotate {
to {
transform: rotate(1turn);
}
}
.left-container {
display: inline-block;
width: 330px;
// height: 315px;
height: 191px;
margin-top: 2px;
border-top-left-radius: 15px;
border-bottom-left-radius: 15px;
padding: 60px;
background-image: linear-gradient(
to bottom right,
rgb(118, 76, 163),
rgb(92, 103, 211)
);
}
.left-container::before {
content: "";
width: 200px;
height: 200px;
left: 50%;
top: 50%;
z-index: -1;
background-image: linear-gradient(
to bottom right,
rgb(118, 76, 163),
rgb(92, 103, 211)
);
}
.title {
color: #fff;
font-size: 18px;
font-weight: 200;
}
.title span {
border-bottom: 3px solid rgb(237, 221, 22);
}
.input-container {
padding: 20px 0;
}
input {
border: 0;
background: none;
outline: none;
color: #fff;
margin: 20px 0;
display: block;
width: 100%;
padding: 5px 0;
transition: 0.2s;
border-bottom: 1px solid rgb(199, 191, 219);
}
input:hover {
border-bottom-color: #fff;
}
::-webkit-input-placeholder {
color: rgb(199, 191, 219);
}
.message-container {
font-size: 14px;
transition: 0.2s;
color: rgb(199, 191, 219);
cursor: pointer;
}
.message-container:hover {
color: #fff;
}
.right-container {
width: 145px;
display: inline-block;
height: calc(100% - 120px);
vertical-align: top;
padding: 60px 0;
}
.regist-container {
text-align: center;
color: #fff;
font-size: 18px;
font-weight: 200;
}
.regist-container span {
border-bottom: 3px solid rgb(237, 221, 22);
}
.action-container {
font-size: 10px;
color: #fff;
text-align: center;
position: relative;
top: 200px;
}
.action-container span {
border: 1px solid rgb(237, 221, 22);
padding: 10px;
display: inline;
line-height: 20px;
border-radius: 20px;
position: absolute;
bottom: 10px;
left: calc(72px - 20px);
transition: 0.2s;
cursor: pointer;
}
.action-container span:hover {
background-color: rgb(237, 221, 22);
color: rgb(95, 76, 194);
}
</style>
附赠后台建议websocket服务供测试使用
链接:https://pan.baidu.com/s/1RzbWiooLwCIuDTnEfN_x0Q?pwd=p58w
提取码:p58w