用vue3显示websocket的状态

发布于:2025-03-20 ⋅ 阅读:(21) ⋅ 点赞:(0)

在上次vue3项目上增加一个标签,显示当前的连接状态,两个按钮:重新连接 和 断开连接

修改App.vue

<template>
  <header>
    <title>ws状态测试</title>
  </header>

  <main>
    <WsStatus />
  </main>
</template>

<script setup lang="ts">
import WsStatus from './components/WsStatus.vue'
</script>

<style scoped>
header {
  line-height: 1.5;
}

.logo {
  display: block;
  margin: 0 auto 2rem;
}

@media (min-width: 1024px) {
  header {
    display: flex;
    place-items: center;
    padding-right: calc(var(--section-gap) / 2);
  }

  .logo {
    margin: 0 2rem 0 0;
  }

  header .wrapper {
    display: flex;
    place-items: flex-start;
    flex-wrap: wrap;
  }
}
</style>

WsStatus.vue

创建一个组件WsStatus.vue

<template>
    <div class="WsStatus">
        <h1>WebSocket 测试</h1>
        <div class="status">
            连接状态: <span :class="statusClass">{{ connectionStatus }}</span>
        </div>
        <button @click="reconnect" :disabled="isConnecting">
            {{ isConnecting ? '连接中...' : '重新连接' }}
        </button>
        <button @click="closeConnect" :disabled="connectStatus">断开连接</button>
        <canvas></canvas>
    </div>
</template>

<script setup lang="ts" name="WsStatus">
import { ref, onMounted, onUnmounted } from 'vue'

const ws = ref()
const imageUrl = ref()
const connectionStatus = ref('未连接')
const isConnecting = ref(false)
const connectStatus = ref(false)
const statusClass = ref('disconnected')

function get_appropriate_ws_url(extra_url: string) {
    var pcol;
    // 获得页面上的url
    var u = document.URL;

    /*
     * We open the websocket encrypted if this page came on an
     * https:// url itself, otherwise unencrypted
     */

    // 去掉http://或者https://
    if (u.substring(0, 5) === "https") {
        pcol = "wss://";
        u = u.substr(8);
    } else {
        pcol = "ws://";
        if (u.substring(0, 4) === "http")
            u = u.substr(7);
    }

    /* + "/xxx" bit is for IE10 workaround */

    //回来的url就城了ws://地址或者wss://地址
    return pcol + u.split('/')[0] + "/" + extra_url;
}


// WebSocket配置(修改为你的服务器地址)
const wsUrl = get_appropriate_ws_url("")

const connectWebSocket = () => {
    if (isConnecting.value) return

    isConnecting.value = true
    connectionStatus.value = '连接中...'
    statusClass.value = 'connecting'

    ws.value = new WebSocket(wsUrl)

    ws.value.onopen = () => {
        connectionStatus.value = '已连接'
        statusClass.value = 'connected'
        isConnecting.value = false
        connectStatus.value = false
    }

    ws.value.onmessage = (event: any) => {
        console.log('收到数据')

    }

    ws.value.onerror = (error: any) => {
        console.error('WebSocket错误:', error)
        connectionStatus.value = '连接错误'
        statusClass.value = 'error'
        isConnecting.value = false
    }

    ws.value.onclose = () => {
        connectionStatus.value = '连接已关闭'
        statusClass.value = 'disconnected'
        isConnecting.value = false
        connectStatus.value = true
    }
}


// 组件挂载时自动连接
onMounted(() => {
    connectWebSocket()
})

// 组件卸载时关闭连接
onUnmounted(() => {
    if (ws.value) {
        ws.value.close()
    }
})

function reconnect() {
    if (ws.value) {
        ws.value.close()
    }
    connectWebSocket()
}

function closeConnect() {
    if (ws.value) {
        ws.value.close()
    }
}

</script>

<style scoped>
.websocket-page {
    padding: 20px;
    max-width: 800px;
    margin: 0 auto;
}

.status {
    margin: 20px 0;
    font-size: 18px;
}

.status span {
    font-weight: bold;
}

.connected {
    color: #4CAF50;
}

.connecting {
    color: #FFC107;
}

.disconnected {
    color: #F44336;
}

.error {
    color: #F44336;
}

button {
    padding: 10px 20px;
    background-color: #2196F3;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
}

button:disabled {
    background-color: #BBDEFB;
    cursor: not-allowed;
}

.messages {
    margin-top: 30px;
    border-top: 1px solid #eee;
    padding-top: 20px;
    background-size: 100% 100%;
}

ul {
    list-style-type: none;
    padding: 0;
    max-height: 300px;
    overflow-y: auto;
    border: 1px solid #ddd;
    padding: 10px;
    border-radius: 4px;
}

li {
    padding: 5px 0;
    border-bottom: 1px solid #eee;
}

.live-image {
    position: fixed;
    top: 50%;
    left: 50%;
    width: 100vw;
    /* 根据需要设置宽度 */
    height: 100vw;

    object-fit: cover;
    transform: translate(-50%, -50%);
}

#camImage,
#canvas {
    position: fixed;
    left: 0;
    top: 0;
    width: 100%;
    /* height: 100%; */
    z-index: -1;
}

/* 竖屏 */
@media screen and (orientation: portrait) {}

/* 横屏 */
@media screen and (orientation: landscape) {}
</style>

编译打包上传部署

$ npm run build
$ scp -r ./dist/* root@192.168.9.163:/oem/usr/www

测试

在rv1106摄像头打开运行ws服务器

# /oem/usr/bin/ws_cam

浏览器访问 http://192.168.9.163:7681/
看到相应页面,按按键会有相应的变换。