You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
112 lines
3.2 KiB
112 lines
3.2 KiB
<script lang="ts" setup> |
|
import { computed, reactive, ref, watchEffect } from 'vue' |
|
import { Input, Tag } from 'ant-design-vue' |
|
import { useWebSocket } from '@vueuse/core' |
|
import { PageWrapper } from '@/components/Page' |
|
import { formatToDateTime } from '@/utils/dateUtil' |
|
import { useUserStore } from '@/store/modules/user' |
|
|
|
defineOptions({ name: 'InfraWebSocket' }) |
|
|
|
const InputTextArea = Input.TextArea |
|
|
|
const userStore = useUserStore() |
|
|
|
const state = reactive({ |
|
sendValue: '', |
|
recordList: [] as { id: number, time: number, res: string }[], |
|
}) |
|
const server = ref( |
|
`${(`${import.meta.env.VITE_GLOB_BASE_URL}/websocket/message`).replace('http', 'ws')}?userId=${userStore.getUserInfo.user.id}`, |
|
) |
|
const { status, data, send, close, open } = useWebSocket(server.value, { |
|
autoReconnect: false, |
|
heartbeat: true, |
|
}) |
|
watchEffect(() => { |
|
if (data.value) { |
|
try { |
|
const res = JSON.parse(data.value) |
|
state.recordList.push(res) |
|
} |
|
catch (error) { |
|
state.recordList.push({ |
|
res: data.value, |
|
id: Math.ceil(Math.random() * 1000), |
|
time: new Date().getTime(), |
|
}) |
|
} |
|
} |
|
}) |
|
const getIsOpen = computed(() => status.value === 'OPEN') |
|
const getTagColor = computed(() => (getIsOpen.value ? 'success' : 'red')) |
|
const getList = computed(() => { |
|
return [...state.recordList].reverse() |
|
}) |
|
function handlerSend() { |
|
send(state.sendValue) |
|
state.sendValue = '' |
|
} |
|
function toggle() { |
|
if (getIsOpen.value) |
|
close() |
|
else |
|
open() |
|
} |
|
</script> |
|
|
|
<template> |
|
<PageWrapper title="WebSocket 示例"> |
|
<div class="flex"> |
|
<div class="w-1/3 p-4"> |
|
<div class="flex items-center"> |
|
<span class="mr-4 text-lg font-medium"> 连接状态: </span> |
|
<Tag :color="getTagColor"> |
|
{{ status }} |
|
</Tag> |
|
</div> |
|
<hr class="my-4"> |
|
|
|
<div class="flex"> |
|
<Input v-model:value="server" disabled> |
|
<template #addonBefore> |
|
服务地址 |
|
</template> |
|
</Input> |
|
<a-button :type="getIsOpen ? 'danger' : 'primary'" @click="toggle"> |
|
{{ getIsOpen ? '关闭连接' : '开启连接' }} |
|
</a-button> |
|
</div> |
|
<p class="mt-4 text-lg font-medium"> |
|
设置 |
|
</p> |
|
<hr class="my-4"> |
|
|
|
<InputTextArea v-model:value="state.sendValue" placeholder="需要发送到服务器的内容" :disabled="!getIsOpen" allow-clear /> |
|
|
|
<a-button type="primary" block class="mt-4" :disabled="!getIsOpen" @click="handlerSend"> |
|
发送 |
|
</a-button> |
|
</div> |
|
|
|
<div class="ml-4 w-2/3 p-4"> |
|
<span class="mr-4 text-lg font-medium"> 消息记录: </span> |
|
<hr class="my-4"> |
|
|
|
<div class="max-h-80 overflow-auto"> |
|
<ul> |
|
<li v-for="item in getList" :key="item.time" class="mt-2"> |
|
<div class="flex items-center"> |
|
<span class="mr-2 font-medium text-primary">收到消息:</span> |
|
<span>{{ formatToDateTime(item.time) }}</span> |
|
</div> |
|
<div> |
|
{{ item.res }} |
|
</div> |
|
</li> |
|
</ul> |
|
</div> |
|
</div> |
|
</div> |
|
</PageWrapper> |
|
</template>
|
|
|