index.vue 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. <template>
  2. <div class="flex">
  3. <el-card class="w-1/2" :gutter="12" shadow="always">
  4. <template #header>
  5. <div class="card-header">
  6. <span>连接</span>
  7. </div>
  8. </template>
  9. <div class="flex items-center">
  10. <span class="text-lg font-medium mr-4"> 连接状态: </span>
  11. <el-tag :color="getTagColor">{{ status }}</el-tag>
  12. </div>
  13. <hr class="my-4" />
  14. <div class="flex">
  15. <el-input v-model="server" disabled>
  16. <template #prepend> 服务地址 </template>
  17. </el-input>
  18. <el-button :type="getIsOpen ? 'danger' : 'primary'" @click="toggle">
  19. {{ getIsOpen ? '关闭连接' : '开启连接' }}
  20. </el-button>
  21. </div>
  22. <p class="text-lg font-medium mt-4">设置</p>
  23. <hr class="my-4" />
  24. <el-input
  25. v-model="sendValue"
  26. :autosize="{ minRows: 2, maxRows: 4 }"
  27. type="textarea"
  28. :disabled="!getIsOpen"
  29. clearable
  30. />
  31. <el-button type="primary" block class="mt-4" :disabled="!getIsOpen" @click="handlerSend">
  32. 发送
  33. </el-button>
  34. </el-card>
  35. <el-card class="w-1/2" :gutter="12" shadow="always">
  36. <template #header>
  37. <div class="card-header">
  38. <span>消息记录</span>
  39. </div>
  40. </template>
  41. <div class="max-h-80 overflow-auto">
  42. <ul>
  43. <li v-for="item in getList" class="mt-2" :key="item.time">
  44. <div class="flex items-center">
  45. <span class="mr-2 text-primary font-medium">收到消息:</span>
  46. <span>{{ dayjs(item.time).format('YYYY-MM-DD HH:mm:ss') }}</span>
  47. </div>
  48. <div>
  49. {{ item.res }}
  50. </div>
  51. </li>
  52. </ul>
  53. </div>
  54. </el-card>
  55. </div>
  56. </template>
  57. <script setup lang="ts">
  58. import { computed, reactive, ref, watchEffect } from 'vue'
  59. import { ElCard, ElInput, ElTag } from 'element-plus'
  60. import { useWebSocket } from '@vueuse/core'
  61. import dayjs from 'dayjs'
  62. import { useUserStore } from '@/store/modules/user'
  63. const userStore = useUserStore()
  64. const sendValue = ref('')
  65. const server = ref(
  66. (import.meta.env.VITE_BASE_URL + '/websocket/message').replace('http', 'ws') +
  67. '?userId=' +
  68. userStore.getUser.id
  69. )
  70. const state = reactive({
  71. recordList: [] as { id: number; time: number; res: string }[]
  72. })
  73. const { status, data, send, close, open } = useWebSocket(server.value, {
  74. autoReconnect: false,
  75. heartbeat: true
  76. })
  77. watchEffect(() => {
  78. if (data.value) {
  79. try {
  80. const res = JSON.parse(data.value)
  81. state.recordList.push(res)
  82. } catch (error) {
  83. state.recordList.push({
  84. res: data.value,
  85. id: Math.ceil(Math.random() * 1000),
  86. time: new Date().getTime()
  87. })
  88. }
  89. }
  90. })
  91. const getIsOpen = computed(() => status.value === 'OPEN')
  92. const getTagColor = computed(() => (getIsOpen.value ? 'success' : 'red'))
  93. const getList = computed(() => {
  94. return [...state.recordList].reverse()
  95. })
  96. function handlerSend() {
  97. send(sendValue.value)
  98. sendValue.value = ''
  99. }
  100. function toggle() {
  101. if (getIsOpen.value) {
  102. close()
  103. } else {
  104. open()
  105. }
  106. }
  107. </script>