Ben Lin
2024-06-18 ebbd788fbb2c0b45d4473798efc57eec8ba74a25
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
<template>
  <PageWrapper title="WebSocket 示例">
    <div class="flex">
      <div class="w-1/3 bg-white p-4">
        <div class="flex items-center">
          <span class="text-lg font-medium mr-4"> 连接状态: </span>
          <Tag :color="getTagColor">{{ status }}</Tag>
        </div>
        <hr class="my-4" />
 
        <div class="flex">
          <a-input v-model:value="state.server" addon-before="服务地址" disabled />
          <a-button :type="getIsOpen ? 'danger' : 'primary'" @click="toggle">
            {{ getIsOpen ? '关闭连接' : '开启连接' }}
          </a-button>
        </div>
        <p class="text-lg font-medium mt-4">设置</p>
        <hr class="my-4" />
 
        <InputTextArea
          placeholder="需要发送到服务器的内容"
          :disabled="!getIsOpen"
          v-model:value="state.sendValue"
          allowClear
        />
 
        <a-button type="primary" block class="mt-4" :disabled="!getIsOpen" @click="handlerSend">
          发送
        </a-button>
      </div>
 
      <div class="w-2/3 bg-white ml-4 p-4">
        <span class="text-lg font-medium mr-4"> 消息记录: </span>
        <hr class="my-4" />
 
        <div class="max-h-80 overflow-auto">
          <ul>
            <li v-for="item in getList" class="mt-2" :key="item.time">
              <div class="flex items-center">
                <span class="mr-2 text-primary font-medium">收到消息:</span>
                <span>{{ formatToDateTime(item.time) }}</span>
              </div>
              <div>
                {{ item.res }}
              </div>
            </li>
          </ul>
        </div>
      </div>
    </div>
  </PageWrapper>
</template>
<script lang="ts" setup>
  import { reactive, watchEffect, computed } from 'vue';
  import { Tag, Input } from 'ant-design-vue';
  import { PageWrapper } from '@/components/Page';
  import { useWebSocket } from '@vueuse/core';
  import { formatToDateTime } from '@/utils/dateUtil';
 
  const InputTextArea = Input.TextArea;
 
  const state = reactive({
    server: 'ws://localhost:3300/test',
    sendValue: '',
    recordList: [] as { id: number; time: number; res: string }[],
  });
 
  const { status, data, send, close, open } = useWebSocket(state.server, {
    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>