chat.vue 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. <template>
  2. <div class="flow-chat" :class="{active:active}">
  3. <button class="flow-chat__toggle" @click="active=!active">=</button>
  4. <div class="flow-chat__area">
  5. <div class="flow-chat__container">
  6. <input
  7. class="handle"
  8. type="text"
  9. :value="handle"
  10. @blur="HANDLE_UPDATE($event.target.value)"
  11. @keyup.enter="HANDLE_UPDATE($event.target.value);$event.target.blur()">
  12. <div ref="messages" class="flow-chat__messages">
  13. <div v-for="m in events" class="message">
  14. <div class="handle">
  15. <div class="name">{{ m.handle }} <span v-if="m.type!='msg'">{{ m.type }}</span></div>
  16. <div class="time">{{ m.time | time }}</div>
  17. </div>
  18. <div class="text">{{ m.message }}</div>
  19. </div>
  20. </div>
  21. <input tabindex="-1" ref="input" class="message" @keyup.enter="send" type="text" v-model="input">
  22. </div> <!-- /container -->
  23. <div class="flow-chat__users">
  24. <div class="flow-chat__user" v-for="u in userList">
  25. <!--<img class="flow-chat__user-icon" src="../assets/icons/user.svg">-->
  26. <icon-user class="flow-chat__user-icon"/> <span>{{ u }}</span>
  27. </div>
  28. </div>
  29. </div>
  30. </div>
  31. </template>
  32. <script>
  33. import {mapGetters, mapActions} from 'vuex'
  34. import IconUser from '@/assets/icons/user.svg'
  35. import utils from '@/utils/utils'
  36. // Load handle from storage
  37. export default {
  38. components: {IconUser},
  39. filters: {
  40. time (value) {
  41. const d = new Date(value)
  42. const hours = utils.padStart(d.getHours(), '0', 2)
  43. const minutes = utils.padStart(d.getMinutes(), '0', 2)
  44. let msg = `${hours}:${minutes}`
  45. return msg
  46. }
  47. },
  48. data () {
  49. return {
  50. active: false,
  51. // handle: storedHandle,
  52. // events: [],
  53. // userList: [],
  54. input: ''
  55. }
  56. },
  57. computed: {
  58. ...mapGetters('chat', ['userList', 'events', 'handle'])
  59. },
  60. watch: {
  61. active (val, oldVal) {
  62. if (val === true && oldVal === false) {
  63. this.$refs.input.focus()
  64. }
  65. },
  66. events (val) {
  67. const height = this.$refs.messages.clientHeight
  68. if (this.$refs.messages.scrollTop + height >= this.$refs.messages.scrollHeight) {
  69. this.$nextTick(() => {
  70. this.$refs.messages.scrollTop = this.$refs.messages.scrollHeight
  71. })
  72. }
  73. /* if (this.active === false) {
  74. if (val.some(e => e.type === 'msg')) {
  75. this.active = true
  76. }
  77. } */
  78. }
  79. },
  80. created () {
  81. this.subscription = this.$store.subscribe(mut => {
  82. if (mut.type === 'chat/EVENT_ADD' && mut.payload.type === 'msg') {
  83. if (this.active) { return }
  84. this.NOTIFICATION_ADD(`<b>${mut.payload.handle}:</b> ${mut.payload.message}`)
  85. }
  86. })
  87. },
  88. beforeDestroy () {
  89. this.subscription()
  90. },
  91. methods: {
  92. ...mapActions('flow', ['NOTIFICATION_ADD']),
  93. ...mapActions('chat', ['EVENT_SEND', 'HANDLE_UPDATE', 'CHAT_JOIN']),
  94. send () {
  95. const msg = this.input
  96. if (msg.trim() === '') { return }
  97. this.input = ''
  98. const msgEvent = {type: 'msg', handle: this.handle, message: msg, time: new Date()}
  99. this.EVENT_SEND(msgEvent)
  100. }
  101. }
  102. }
  103. </script>
  104. <style>
  105. .flow-chat {
  106. height:100%;
  107. box-sizing:border-box;
  108. position:relative;
  109. width:0;
  110. transition: all var(--transition-speed);
  111. }
  112. .flow-chat.active {
  113. width:530px;
  114. }
  115. .flow-chat__toggle {
  116. user-select:none;
  117. cursor: pointer;
  118. position:absolute;
  119. display:flex;
  120. justify-content: center;
  121. align-items: center;
  122. width:30px;
  123. height:50px;
  124. left:-30px;
  125. top:calc(50% - 25px);
  126. }
  127. .flow-chat__area {
  128. height:100%;
  129. overflow:hidden;
  130. display:flex;
  131. flex-flow:row;
  132. padding:8px 0;
  133. }
  134. .flow-chat__container {
  135. height:100%;
  136. display:flex;
  137. flex-flow:column;
  138. flex:1;
  139. padding:0 8px;
  140. }
  141. .flow-chat__container >*:not(last-child) {
  142. margin-bottom:10px;
  143. }
  144. .flow-chat__users {
  145. flex-basis:100px;
  146. padding:20px 8px;
  147. }
  148. .flow-chat__user {
  149. display:flex;
  150. flex-flow:row;
  151. justify-content: space-between;
  152. align-items: center;
  153. }
  154. .flow-chat__user-icon{
  155. height:10px;
  156. width:auto;
  157. }
  158. .flow-chat__user span {
  159. text-align:center;
  160. flex:1;
  161. width: 100px;
  162. overflow:hidden;
  163. white-space: nowrap;
  164. text-overflow: ellipsis;
  165. }
  166. .flow-chat__messages {
  167. font-size:12px;
  168. overflow-y:scroll;
  169. min-width:300px;
  170. flex:1;
  171. }
  172. .flow-chat__messages .message{
  173. padding:2px 2px 12px 2px;
  174. }
  175. .flow-chat__messages .handle {
  176. display:flex;
  177. flex-flow:row;
  178. justify-content: space-between;
  179. align-items: center;
  180. padding-top:2px;
  181. }
  182. .flow-chat__messages .handle .name {
  183. padding-bottom:4px;
  184. }
  185. .flow-chat__messages .handle .time{
  186. font-weight:normal;
  187. font-size:8px;
  188. }
  189. .flow-chat__messages .text {
  190. padding-top:0;
  191. padding-left:9px;
  192. }
  193. </style>