ConversationList.vue 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. <script setup lang="ts">
  2. import { formatDate } from '@/utils/formatTime'
  3. import { reactive } from 'vue'
  4. /* 头像相关 */
  5. import informIcon from '@/assets/imgs/im/avatar/inform.png'
  6. /* route */
  7. const route = useRoute()
  8. /* router */
  9. const router = useRouter()
  10. //取系统通知数据
  11. const informDetail = computed(() => {
  12. const informDetailArr = reactive([
  13. {
  14. from: '系统通知',
  15. desc: '您有一条新的通知',
  16. time: new Date(),
  17. untreated: 1
  18. }
  19. ])
  20. const lastInformDeatail = informDetailArr[0] || {}
  21. const untreated = 1
  22. return { untreated, lastInformDeatail }
  23. })
  24. //取好友列表(主要使用好友下的用户属性相关)
  25. const friendList = reactive({
  26. 1: {
  27. avatarurl: 'https://img.yzcdn.cn/vant/cat.jpeg'
  28. }
  29. })
  30. //取会话数据
  31. const conversationList = reactive([
  32. {
  33. conversationKey: 1,
  34. conversationInfo: { avatarUrl: 'https://img.yzcdn.cn/vant/cat.jpeg' },
  35. name: '好友1',
  36. conversationType: 2,
  37. latestMessage: {
  38. msg: 'hello word!'
  39. },
  40. latestSendTime: new Date(),
  41. unreadMessageNum: 5,
  42. isMention: false
  43. }
  44. ])
  45. //处理会话name
  46. const handleConversationName = computed(() => {
  47. return ''
  48. })
  49. //处理lastmsg的from昵称
  50. const handleLastMsgNickName = computed(() => {
  51. return ''
  52. })
  53. const emit = defineEmits(['toInformDetails', 'toChatMessage'])
  54. //普通会话
  55. const checkedConverItemIndex = ref(null)
  56. const toChatMessage = (item, itemKey, index) => {
  57. checkedConverItemIndex.value = index
  58. console.log('选中的会话key', itemKey)
  59. //跳转至对应的消息界面
  60. emit('toChatMessage', itemKey, item.conversationType)
  61. }
  62. //删除某条会话
  63. const deleteConversation = (itemKey) => {
  64. console.log('选中的会话key', itemKey)
  65. }
  66. </script>
  67. <template>
  68. <el-scrollbar class="session_list" style="overflow: auto" tag="ul">
  69. <!-- 系统通知会话 -->
  70. <li
  71. v-if="JSON.stringify(informDetail.lastInformDeatail) !== '{}' && informDetail.untreated >= 1"
  72. class="session_list_item"
  73. @click="$emit('toInformDetails')"
  74. >
  75. <div class="item_body item_left">
  76. <!-- 通知头像 -->
  77. <div class="session_other_avatar">
  78. <el-avatar :size="34" :src="informIcon" />
  79. </div>
  80. </div>
  81. <div class="item_body item_main">
  82. <div class="name">系统通知</div>
  83. <div class="last_msg_body">
  84. {{ informDetail.lastInformDeatail.from }}:{{ informDetail.lastInformDeatail.desc }}
  85. </div>
  86. </div>
  87. <div class="item_body item_right">
  88. <span class="time">{{
  89. formatDate(informDetail.lastInformDeatail.time, 'MM/DD/HH:mm')
  90. }}</span>
  91. <span class="unReadNum_box" v-if="informDetail.untreated >= 1">
  92. <sup
  93. class="unReadNum_count"
  94. v-text="informDetail.untreated >= 99 ? '99+' : informDetail.untreated"
  95. ></sup>
  96. </span>
  97. </div>
  98. </li>
  99. <!-- 普通会话 -->
  100. <template v-if="Object.keys(conversationList).length > 0">
  101. <li
  102. v-for="(item, itemKey, index) in conversationList"
  103. :key="itemKey"
  104. @click="toChatMessage(item, itemKey, index)"
  105. :style="{
  106. background: checkedConverItemIndex === index ? '#E5E5E5' : ''
  107. }"
  108. >
  109. <el-popover
  110. popper-class="conversation_popover"
  111. placement="right-end"
  112. trigger="contextmenu"
  113. :show-arrow="false"
  114. :offset="-10"
  115. >
  116. <template #reference>
  117. <div class="session_list_item">
  118. <div class="item_body item_left">
  119. <div class="session_other_avatar">
  120. <el-avatar
  121. :size="34"
  122. :src="
  123. friendList[item.conversationKey] && friendList[item.conversationKey].avatarurl
  124. ? friendList[item.conversationKey].avatarurl
  125. : item.conversationInfo.avatarUrl
  126. "
  127. />
  128. </div>
  129. </div>
  130. <div class="item_body item_main">
  131. <div class="name"> 好友 </div>
  132. <div class="last_msg_body">
  133. <span class="last_msg_body_mention" v-if="item.isMention">[有人@我]</span>
  134. <span v-show="item.conversationType === 2">好友</span>
  135. {{ item.latestMessage.msg }}
  136. </div>
  137. </div>
  138. <div class="item_body item_right">
  139. <span class="time">{{ formatDate(item.latestSendTime, 'MM/DD/HH:mm') }}</span>
  140. <span class="unReadNum_box" v-if="item.unreadMessageNum >= 1">
  141. <sup
  142. class="unReadNum_count"
  143. v-text="item.unreadMessageNum >= 99 ? '99+' : item.unreadMessageNum"
  144. ></sup>
  145. </span>
  146. </div>
  147. </div>
  148. </template>
  149. <template #default>
  150. <div class="session_list_delete" @click="deleteConversation(itemKey)"> 删除会话 </div>
  151. </template>
  152. </el-popover>
  153. </li>
  154. </template>
  155. <template v-else>
  156. <el-empty description="暂无最近会话" />
  157. </template>
  158. </el-scrollbar>
  159. </template>
  160. <style scoped lang="scss">
  161. .session_list {
  162. position: relative;
  163. height: 100%;
  164. padding: 0;
  165. margin: 0;
  166. }
  167. .offline_hint {
  168. width: 100%;
  169. height: 30px;
  170. text-align: center;
  171. line-height: 30px;
  172. color: #f35f81;
  173. background: #fce7e8;
  174. font-size: 7px;
  175. .plaint_icon {
  176. display: inline-block;
  177. width: 15px;
  178. height: 15px;
  179. color: #e5e5e5;
  180. text-align: center;
  181. line-height: 15px;
  182. font-size: 7px;
  183. font-weight: bold;
  184. background: #e6686e;
  185. border-radius: 50%;
  186. }
  187. }
  188. .session_list .session_list_item {
  189. display: flex;
  190. flex-direction: row;
  191. justify-content: flex-start;
  192. align-items: center;
  193. height: 66px;
  194. background: #f0f0f0;
  195. color: var(--el-color-primary);
  196. border-bottom: 1px solid var(--el-border-color);
  197. cursor: pointer;
  198. &:hover {
  199. background: #e5e5e5;
  200. }
  201. .item_body {
  202. display: flex;
  203. height: 100%;
  204. }
  205. .item_left {
  206. flex-direction: row;
  207. align-items: center;
  208. justify-content: center;
  209. margin-left: 14px;
  210. margin-right: 10px;
  211. }
  212. .item_main {
  213. width: 225px;
  214. max-width: 225px;
  215. height: 34px;
  216. flex-direction: column;
  217. justify-content: space-between;
  218. align-items: flex-start;
  219. .name {
  220. min-width: 56px;
  221. max-width: 180px;
  222. height: 17px;
  223. font-weight: 400;
  224. font-size: 14px;
  225. /* identical to box height */
  226. color: #333333;
  227. overflow: hidden;
  228. text-overflow: ellipsis;
  229. white-space: nowrap;
  230. }
  231. .last_msg_body {
  232. max-width: 185px;
  233. height: 17px;
  234. font-weight: 400;
  235. font-size: 12px;
  236. line-height: 17px;
  237. letter-spacing: 0.3px;
  238. color: #a3a3a3;
  239. overflow: hidden;
  240. text-overflow: ellipsis;
  241. white-space: nowrap;
  242. }
  243. .last_msg_body_mention {
  244. font-size: 12px;
  245. line-height: 17px;
  246. font-weight: bold;
  247. color: red;
  248. }
  249. }
  250. .item_right {
  251. width: 25%;
  252. height: 34px;
  253. flex-direction: column;
  254. align-items: flex-end;
  255. margin-right: 10px;
  256. .time {
  257. font-size: 10px;
  258. font-weight: 400;
  259. font-size: 10px;
  260. line-height: 14px;
  261. letter-spacing: 0.25px;
  262. color: #a3a3a3;
  263. }
  264. .unReadNum_box {
  265. margin-top: 10px;
  266. vertical-align: middle;
  267. .unReadNum_count {
  268. display: inline-block;
  269. min-width: 20px;
  270. height: 20px;
  271. padding: 0 6px;
  272. color: #fff;
  273. font-weight: normal;
  274. font-size: 12px;
  275. line-height: 20px;
  276. white-space: nowrap;
  277. text-align: center;
  278. background: #f5222d;
  279. border-radius: 10px;
  280. box-sizing: border-box;
  281. }
  282. }
  283. }
  284. }
  285. .session_list_item_active {
  286. background: #d2d2d2;
  287. }
  288. .session_list .session_list_item + .list_item {
  289. margin-top: 10px;
  290. }
  291. .session_list_delete {
  292. cursor: pointer;
  293. transition: all 0.5s;
  294. &:hover {
  295. background: #e1e1e1;
  296. }
  297. }
  298. </style>