ChatMessageItem.vue 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. <template>
  2. <div class="chat-msg-item">
  3. <div class="chat-msg-tip" v-show="msgInfo.type==$enums.MESSAGE_TYPE.RECALL">{{msgInfo.content}}</div>
  4. <div class="chat-msg-tip" v-show="msgInfo.type==$enums.MESSAGE_TYPE.TIP_TIME">
  5. {{$date.toTimeText(msgInfo.sendTime)}}
  6. </div>
  7. <div class="chat-msg-normal" v-show="msgInfo.type>=0 && msgInfo.type<10" :class="{'chat-msg-mine':mine}">
  8. <div class="head-image">
  9. <head-image :name="showName" :size="40" :url="headImage" :id="msgInfo.sendId"></head-image>
  10. </div>
  11. <div class="chat-msg-content">
  12. <div v-show="mode==1 && msgInfo.groupId && !msgInfo.selfSend" class="chat-msg-top">
  13. <span>{{showName}}</span>
  14. </div>
  15. <div v-show="mode==2" class="chat-msg-top">
  16. <span>{{showName}}</span>
  17. <span>{{$date.toTimeText(msgInfo.sendTime)}}</span>
  18. </div>
  19. <div class="chat-msg-bottom" @contextmenu.prevent="showRightMenu($event)">
  20. <span class="chat-msg-text" v-if="msgInfo.type==$enums.MESSAGE_TYPE.TEXT"
  21. v-html="$emo.transform(msgInfo.content)"></span>
  22. <div class="chat-msg-image" v-if="msgInfo.type==$enums.MESSAGE_TYPE.IMAGE">
  23. <div class="img-load-box" v-loading="loading" element-loading-text="上传中.."
  24. element-loading-background="rgba(0, 0, 0, 0.4)">
  25. <img class="send-image" :src="JSON.parse(msgInfo.content).thumbUrl"
  26. @click="showFullImageBox()" />
  27. </div>
  28. <span title="发送失败" v-show="loadFail" @click="onSendFail"
  29. class="send-fail el-icon-warning"></span>
  30. </div>
  31. <div class="chat-msg-file" v-if="msgInfo.type==$enums.MESSAGE_TYPE.FILE">
  32. <div class="chat-file-box" v-loading="loading">
  33. <div class="chat-file-info">
  34. <el-link class="chat-file-name" :underline="true" target="_blank" type="primary"
  35. :href="data.url">{{data.name}}</el-link>
  36. <div class="chat-file-size">{{fileSize}}</div>
  37. </div>
  38. <div class="chat-file-icon">
  39. <span type="primary" class="el-icon-document"></span>
  40. </div>
  41. </div>
  42. <span title="发送失败" v-show="loadFail" @click="onSendFail"
  43. class="send-fail el-icon-warning"></span>
  44. </div>
  45. <div class="chat-msg-voice" v-if="msgInfo.type==$enums.MESSAGE_TYPE.AUDIO"
  46. @click="onPlayVoice()">
  47. <audio controls :src="JSON.parse(msgInfo.content).url"></audio>
  48. </div>
  49. <span class="chat-readed" v-show="msgInfo.selfSend && !msgInfo.groupId
  50. && msgInfo.status==$enums.MESSAGE_STATUS.READED">已读</span>
  51. <span class="chat-unread" v-show="msgInfo.selfSend && !msgInfo.groupId
  52. && msgInfo.status!=$enums.MESSAGE_STATUS.READED">未读</span>
  53. </div>
  54. </div>
  55. </div>
  56. <right-menu v-show="menu && rightMenu.show" :pos="rightMenu.pos" :items="menuItems"
  57. @close="rightMenu.show=false" @select="onSelectMenu"></right-menu>
  58. </div>
  59. </template>
  60. <script>
  61. import HeadImage from "../common/HeadImage.vue";
  62. import RightMenu from '../common/RightMenu.vue';
  63. export default {
  64. name: "messageItem",
  65. components: {
  66. HeadImage,
  67. RightMenu
  68. },
  69. props: {
  70. mode: {
  71. type: Number,
  72. default: 1
  73. },
  74. mine: {
  75. type: Boolean,
  76. required: true
  77. },
  78. headImage: {
  79. type: String,
  80. required: true
  81. },
  82. showName: {
  83. type: String,
  84. required: true
  85. },
  86. msgInfo: {
  87. type: Object,
  88. required: true
  89. },
  90. menu: {
  91. type: Boolean,
  92. default: true
  93. }
  94. },
  95. data() {
  96. return {
  97. audioPlayState: 'STOP',
  98. rightMenu: {
  99. show: false,
  100. pos: {
  101. x: 0,
  102. y: 0
  103. }
  104. }
  105. }
  106. },
  107. methods: {
  108. onSendFail() {
  109. this.$message.error("该文件已发送失败,目前不支持自动重新发送,建议手动重新发送")
  110. },
  111. showFullImageBox() {
  112. let imageUrl = JSON.parse(this.msgInfo.content).originUrl;
  113. if (imageUrl) {
  114. this.$store.commit('showFullImageBox', imageUrl);
  115. }
  116. },
  117. onPlayVoice() {
  118. if (!this.audio) {
  119. this.audio = new Audio();
  120. }
  121. this.audio.src = JSON.parse(this.msgInfo.content).url;
  122. this.audio.play();
  123. this.onPlayVoice = 'RUNNING';
  124. },
  125. showRightMenu(e) {
  126. this.rightMenu.pos = {
  127. x: e.x,
  128. y: e.y
  129. };
  130. this.rightMenu.show = "true";
  131. },
  132. onSelectMenu(item) {
  133. this.$emit(item.key.toLowerCase(), this.msgInfo);
  134. }
  135. },
  136. computed: {
  137. loading() {
  138. return this.msgInfo.loadStatus && this.msgInfo.loadStatus === "loading";
  139. },
  140. loadFail() {
  141. return this.msgInfo.loadStatus && this.msgInfo.loadStatus === "fail";
  142. },
  143. data() {
  144. return JSON.parse(this.msgInfo.content)
  145. },
  146. fileSize() {
  147. let size = this.data.size;
  148. if (size > 1024 * 1024) {
  149. return Math.round(size / 1024 / 1024) + "M";
  150. }
  151. if (size > 1024) {
  152. return Math.round(size / 1024) + "KB";
  153. }
  154. return size + "B";
  155. },
  156. menuItems() {
  157. let items = [];
  158. items.push({
  159. key: 'DELETE',
  160. name: '删除',
  161. icon: 'el-icon-delete'
  162. });
  163. if (this.msgInfo.selfSend && this.msgInfo.id > 0) {
  164. items.push({
  165. key: 'RECALL',
  166. name: '撤回',
  167. icon: 'el-icon-refresh-left'
  168. });
  169. }
  170. return items;
  171. }
  172. }
  173. }
  174. </script>
  175. <style scoped lang="scss">
  176. .chat-msg-item {
  177. .chat-msg-tip {
  178. line-height: 50px;
  179. font-size: 14px;
  180. }
  181. .chat-msg-normal {
  182. position: relative;
  183. font-size: 0;
  184. padding-left: 60px;
  185. min-height: 50px;
  186. margin-top: 10px;
  187. .head-image {
  188. position: absolute;
  189. width: 40px;
  190. height: 40px;
  191. top: 0;
  192. left: 0;
  193. }
  194. .chat-msg-content {
  195. text-align: left;
  196. .send-fail {
  197. color: #e60c0c;
  198. font-size: 30px;
  199. cursor: pointer;
  200. margin: 0 20px;
  201. }
  202. .chat-msg-top {
  203. display: flex;
  204. flex-wrap: nowrap;
  205. color: #333;
  206. font-size: 14px;
  207. line-height: 20px;
  208. span {
  209. margin-right: 12px;
  210. }
  211. }
  212. .chat-msg-bottom {
  213. display: inline-block;
  214. padding-right: 80px;
  215. .chat-msg-text {
  216. display: block;
  217. position: relative;
  218. line-height: 30px;
  219. margin-top: 3px;
  220. padding: 7px;
  221. background-color: white;
  222. border-radius: 10px;
  223. color: black;
  224. display: block;
  225. font-size: 16px;
  226. text-align: left;
  227. white-space: pre-wrap;
  228. word-break: break-all;
  229. box-shadow: 1px 1px 1px #c0c0f0;
  230. &:after {
  231. content: "";
  232. position: absolute;
  233. left: -10px;
  234. top: 13px;
  235. width: 0;
  236. height: 0;
  237. border-style: solid dashed dashed;
  238. border-color: white transparent transparent;
  239. overflow: hidden;
  240. border-width: 10px;
  241. }
  242. }
  243. .chat-msg-image {
  244. display: flex;
  245. flex-wrap: nowrap;
  246. flex-direction: row;
  247. align-items: center;
  248. .send-image {
  249. min-width: 200px;
  250. min-height: 150px;
  251. max-width: 400px;
  252. max-height: 300px;
  253. border: #dddddd solid 1px;
  254. border: 5px solid #ccc;
  255. border-radius: 6px;
  256. cursor: pointer;
  257. }
  258. }
  259. .chat-msg-file {
  260. display: flex;
  261. flex-wrap: nowrap;
  262. flex-direction: row;
  263. align-items: center;
  264. cursor: pointer;
  265. .chat-file-box {
  266. display: flex;
  267. flex-wrap: nowrap;
  268. align-items: center;
  269. min-height: 80px;
  270. box-shadow: 5px 5px 2px #c0c0c0;
  271. border: #dddddd solid 1px;
  272. border-radius: 6px;
  273. background-color: #eeeeee;
  274. padding: 10px 15px;
  275. .chat-file-info {
  276. flex: 1;
  277. height: 100%;
  278. text-align: left;
  279. font-size: 14px;
  280. .chat-file-name {
  281. display: inline-block;
  282. min-width: 150px;
  283. max-width: 300px;
  284. font-size: 16px;
  285. font-weight: 600;
  286. margin-bottom: 15px;
  287. white-space: pre-wrap;
  288. word-break: break-all;
  289. }
  290. }
  291. .chat-file-icon {
  292. font-size: 50px;
  293. color: #d42e07;
  294. }
  295. }
  296. .send-fail {
  297. color: #e60c0c;
  298. font-size: 30px;
  299. cursor: pointer;
  300. margin: 0 20px;
  301. }
  302. }
  303. .chat-msg-voice {
  304. font-size: 14px;
  305. cursor: pointer;
  306. audio {
  307. height: 45px;
  308. padding: 5px 0;
  309. }
  310. }
  311. .chat-unread {
  312. font-size: 10px;
  313. color: #f23c0f;
  314. font-weight: 600;
  315. }
  316. .chat-readed {
  317. font-size: 10px;
  318. color: #888;
  319. font-weight: 600;
  320. }
  321. }
  322. }
  323. &.chat-msg-mine {
  324. text-align: right;
  325. padding-left: 0;
  326. padding-right: 60px;
  327. .head-image {
  328. left: auto;
  329. right: 0;
  330. }
  331. .chat-msg-content {
  332. text-align: right;
  333. .chat-msg-top {
  334. flex-direction: row-reverse;
  335. span {
  336. margin-left: 12px;
  337. margin-right: 0;
  338. }
  339. }
  340. .chat-msg-bottom {
  341. padding-left: 80px;
  342. padding-right: 0;
  343. .chat-msg-text {
  344. margin-left: 10px;
  345. background-color: rgb(88, 127, 240);
  346. color: #fff;
  347. vertical-align: top;
  348. box-shadow: 1px 1px 1px #ccc;
  349. &:after {
  350. left: auto;
  351. right: -10px;
  352. border-top-color: rgb(88, 127, 240);
  353. }
  354. }
  355. .chat-msg-image {
  356. flex-direction: row-reverse;
  357. }
  358. .chat-msg-file {
  359. flex-direction: row-reverse;
  360. }
  361. }
  362. }
  363. }
  364. }
  365. }
  366. </style>