index.vue 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. <template>
  2. <div class="default-width message pa-3" :style="`height: calc(100vh - ${isEnterprise ? '130px' : '50px'});`">
  3. <div class="message-left">
  4. <div class="message-left-search d-flex align-center justify-center">
  5. <!-- {{ connected ? '连接成功': '连接失败' }} -->
  6. <TextInput v-model="searchInputVal" :item="textItem" @appendInnerClick="handleSearch" @enter="handleSearch"></TextInput>
  7. </div>
  8. <div class="message-chat-box mt-5">
  9. <v-overlay
  10. :model-value="!connected"
  11. contained
  12. class="align-center justify-center"
  13. >
  14. <v-progress-circular
  15. color="primary"
  16. size="64"
  17. indeterminate
  18. ></v-progress-circular>
  19. </v-overlay>
  20. <div v-if="conversationList.length">
  21. <v-list density="compact">
  22. <v-list-item
  23. v-for="(val, i) in conversationList"
  24. :key="i"
  25. :value="val"
  26. color="primary"
  27. :title="val.channel_id"
  28. :subtitle="val.timestamp"
  29. >
  30. <template v-slot:prepend>
  31. <v-avatar :image="val.avatar || 'https://minio.citupro.com/dev/menduner/7.png'"></v-avatar>
  32. </template>
  33. <template v-slot:append>
  34. <v-badge
  35. v-if="val.unread > 0"
  36. color="error"
  37. :content="val.unread"
  38. inline
  39. ></v-badge>
  40. </template>
  41. </v-list-item>
  42. </v-list>
  43. <div class="message-no-more-text mt-3">没有更多了</div>
  44. </div>
  45. <div v-else class="left-noData">
  46. <Empty :elevation="false" message="暂无30天内联系人" width="300" height="150"></Empty>
  47. </div>
  48. </div>
  49. </div>
  50. <div class="message-right">
  51. <div v-if="showRightNoData" class="right-noData">
  52. <Empty :elevation="false" message="与您进行过沟通的 Boss 都会在左侧列表中显示"></Empty>
  53. </div>
  54. <Chatting :items="messageItems" :info="info" :uid="uid" @handleSend="handleUpdate"></Chatting>
  55. </div>
  56. </div>
  57. </template>
  58. <script setup>
  59. defineOptions({ name: 'personal-message-index'})
  60. import { ref, inject } from 'vue'
  61. import Chatting from './components/chatting.vue'
  62. import { initConnect, send, initKey } from '@/hooks/web/useIM'
  63. import { useRoute } from 'vue-router'
  64. import { getPositionDetails } from '@/api/position'
  65. // import { useUserStore } from '@/store/user'
  66. // const userStore = useUserStore()
  67. const isEnterprise = inject('isEnterprise')
  68. // 实例
  69. const route = useRoute()
  70. // const channel = ref(null)
  71. // const enterpriseId = isEnterprise ? userStore.baseInfo.enterpriseId : route.query.enterprise
  72. const { uid } = await initKey()
  73. const {
  74. connected,
  75. conversationList,
  76. messageItems,
  77. channel
  78. } = initConnect(route.query.id, route.query.enterprise)
  79. const showRightNoData = ref(false)
  80. const searchInputVal = ref()
  81. const textItem = ref({
  82. type: 'text',
  83. value: null,
  84. width: 336,
  85. clearable: true,
  86. hideDetails: true,
  87. appendInnerIcon: 'mdi-magnify',
  88. label: '搜索30天内的联系人'
  89. })
  90. const info = ref({})
  91. if (route.query.job) {
  92. const res = await getPositionDetails({ id: route.query.job })
  93. info.value = res
  94. }
  95. // 左侧聊天列表
  96. // const chatList = ref([
  97. // {
  98. // id: 1,
  99. // name: '钟女士',
  100. // avatar: 'https://minio.citupro.com/dev/menduner/tx1.jpg',
  101. // enterpriseName: '泰康泰康泰康泰康泰康泰康',
  102. // postName: '人事HR',
  103. // updateTime: 1715337950000,
  104. // tip: '你好'
  105. // },
  106. // {
  107. // id: 2,
  108. // name: '林先生',
  109. // avatar: 'https://minio.citupro.com/dev/menduner/tx1.jpg',
  110. // enterpriseName: '众宝联合',
  111. // postName: '人力资源主管',
  112. // updateTime: 1715337950000,
  113. // tip: '你好'
  114. // }
  115. // ])
  116. const handleUpdate = (val) => {
  117. send(val.value, channel.value)
  118. }
  119. const handleSearch = () => {
  120. console.log(searchInputVal.value, 'search')
  121. }
  122. </script>
  123. <style scoped lang="scss">
  124. .message {
  125. display: flex;
  126. &-left {
  127. position: relative;
  128. height: 100%;;
  129. width: 360px;
  130. background-color: #fff;
  131. border-radius: 8px;
  132. margin-right: 12px;
  133. .message-left-search {
  134. width: 100%;
  135. height: 60px;
  136. background: linear-gradient(90deg, #f5fcfc, #fcfbfa);
  137. border-radius: 8px 8px 0 0;
  138. }
  139. .message-chat-box {
  140. .chat-item {
  141. position: relative;
  142. width: 100%;
  143. height: 78px;
  144. padding: 14px 12px;
  145. cursor: pointer;
  146. &:hover {
  147. background-color: #f8f8f8;
  148. }
  149. .chat-item-time {
  150. position: absolute;
  151. right: 12px;
  152. top: 50%;
  153. transform: translateY(-50%);
  154. }
  155. .title-box {
  156. max-width: 114px;
  157. overflow: hidden;
  158. white-space: nowrap;
  159. text-overflow: ellipsis;
  160. display: inline-block;
  161. }
  162. }
  163. }
  164. .message-no-more-text {
  165. color: var(--color-999);
  166. font-size: 14px;
  167. text-align: center
  168. }
  169. .left-noData {
  170. position: absolute;
  171. top: 50%;
  172. left: 50%;
  173. transform: translate(-50%, -50%);
  174. }
  175. }
  176. &-right {
  177. height: 100%;
  178. flex: 1;
  179. position: relative;
  180. background-color: #fff;
  181. border-radius: 8px;
  182. .right-noData {
  183. position: absolute;
  184. top: 50%;
  185. left: 50%;
  186. transform: translate(-50%, -50%);
  187. }
  188. }
  189. }
  190. </style>