message.vue 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. <template>
  2. <view>
  3. <view :class="{item:true,'item-reverse':m.sender.id==userInfo.id}">
  4. <view class="avatar">
  5. <image :src="m.sender?m.sender.avatar:m.receiver?m.receiver.avatar:''" mode=""></image>
  6. </view>
  7. <view v-if="m.message.type == 'text'" :class="{'text': true,'reverse blueBg':m.sender.id==userInfo.id}">
  8. {{m.message.content}}
  9. </view>
  10. <view v-if="m.message.type == 'image'" :class="{'text': true,'reverse blueBg':m.sender.id==userInfo.id}">
  11. <image :src="m.message.content" mode="widthFix" style="max-width: 300upx;" @click="showImages"></image>
  12. </view>
  13. <view v-if="m.message.type == 'redpack'" :class="{'redpack': true,'reverse':m.sender.id==userInfo.id,'redpack-open':m.message.content.hasget||hasget}" @click="grab">
  14. <view class="redpack-body">
  15. <view class="redpack-body-image"></view>
  16. <view class="redpack-body-content">
  17. <view>{{m.message.content.money}}</view>
  18. <view class="description">{{m.message.content.note||'恭喜发财,大吉大利!'}}</view>
  19. </view>
  20. </view>
  21. <view class="redpack-footer">
  22. 红包
  23. </view>
  24. </view>
  25. <view v-if="m.message.type == 'voice'" :class="{'voice': true,reverse:m.sender.id==userInfo.id,'voice-play':msgId == $store.state.currentVoiceId}" @click="showVoice">
  26. <view :class="{'box': true,'mybox':m.sender.id==userInfo.id}">
  27. <view class="wifi-symbol">
  28. <view class="wifi-circle first"></view>
  29. <view class="wifi-circle second"></view>
  30. <view class="wifi-circle third"></view>
  31. </view>
  32. </view>
  33. <view :class="{'voice-text': true,'voice-text-right':m.sender.id==userInfo.id}">
  34. {{m.message.content.time}}''
  35. </view>
  36. </view>
  37. <view v-if="m.message.type == 'face'" :class="{'text': true,'reverse blueBg':m.sender.id==userInfo.id}">
  38. <image :src="m.message.content" :style="{width:(faceSize.width/2) + 'px', height: (faceSize.height/2) + 'px'}" @load="setEmoji"></image>
  39. </view>
  40. </view>
  41. </view>
  42. </template>
  43. <script>
  44. import api from "../library/index.js"
  45. const innerAudioContext = uni.createInnerAudioContext();
  46. export default {
  47. data(){
  48. return{
  49. userInfo: uni.getStorageSync('userInfo'),
  50. hasget:false,
  51. onVoice:false,
  52. faceSize: {width:'',height:''}
  53. }
  54. },
  55. props: {
  56. m: {
  57. type: Object,
  58. require: true
  59. },
  60. msgId: {
  61. type: [Number, String],
  62. require: true
  63. }
  64. },
  65. methods:{
  66. setEmoji(e){
  67. this.faceSize = e.detail
  68. },
  69. grab(){
  70. if(this.m.group_id>0){
  71. let group = uni.getStorageSync('group_'+this.m.group_id)
  72. let index = this.m.message.content.id
  73. for(let i in group){
  74. if(group[i].message.content.id==index){
  75. group[i].message.content.hasget=true
  76. }
  77. }
  78. uni.setStorageSync('group_'+this.m.group_id,group)
  79. this.hasget = true
  80. api.grab({id:this.m.message.content.id}).then(res=>{
  81. this.$emit('getPick',{content:this.m.message.content,data:res,sender: this.m.sender})
  82. }).catch(data=>{
  83. this.$emit('getPick',{content:this.m.message.content,data:data,sender: this.m.sender})
  84. })
  85. }else{
  86. let chat = uni.getStorageSync('chat_'+this.m.receiver.id);
  87. console.log(JSON.stringify(chat));
  88. let index = this.m.message.content.id
  89. for(let i in chat){
  90. if(chat[i].message.content.id==index){
  91. chat[i].message.content.hasget=true
  92. }
  93. }
  94. uni.setStorageSync('chat_'+this.m.receiver.id,chat)
  95. this.hasget = true
  96. api.grab({id:this.m.message.content.id}).then(res=>{
  97. this.$emit('getPick',{content:this.m.message.content,data:res,sender: this.m.sender})
  98. }).catch(data=>{
  99. this.$emit('getPick',{content:this.m.message.content,data:data,sender: this.m.sender})
  100. })
  101. }
  102. },
  103. showVoice(){
  104. if(innerAudioContext.paused) {
  105. this.$store.state.currentVoiceId = this.msgId;
  106. innerAudioContext.play()
  107. } else {
  108. this.$store.state.currentVoiceId = -1;
  109. innerAudioContext.stop()
  110. }
  111. },
  112. showImages(){
  113. uni.previewImage({
  114. urls:[this.m.message.content]
  115. })
  116. }
  117. },
  118. created() {
  119. innerAudioContext.src = this.m.message.content.url
  120. innerAudioContext.onCanplay(function(){
  121. innerAudioContext.pause();
  122. })
  123. innerAudioContext.onEnded(()=>{
  124. this.$store.state.currentVoiceId = -1;
  125. })
  126. }
  127. }
  128. </script>
  129. <style lang="scss" scoped>
  130. .item {
  131. display: flex;
  132. font-size: 28upx;
  133. padding: 20upx;
  134. &-reverse{
  135. flex-direction: row-reverse;
  136. }
  137. .avatar {
  138. width: 90upx;
  139. height: 90upx;
  140. border-radius: 12upx;
  141. background: #fff;
  142. overflow: hidden;
  143. image {
  144. width: 90upx;
  145. height: 90upx;
  146. }
  147. }
  148. .text,
  149. .redpack,
  150. .voice {
  151. margin: 0 20upx;
  152. border-radius: 12upx;
  153. max-width: 70%;
  154. position: relative;
  155. &:before {
  156. display: block;
  157. content: "";
  158. position: absolute;
  159. left: -12upx;
  160. top: 39upx;
  161. width: 0;
  162. height: 0;
  163. border-style: solid;
  164. border-width: 12upx 12upx 12upx 0;
  165. }
  166. &.reverse:after {
  167. display: block;
  168. content: "";
  169. position: absolute;
  170. right: -12upx;
  171. top: 39upx;
  172. width: 0;
  173. height: 0;
  174. border-style: solid;
  175. border-width: 12upx 0upx 12upx 12upx;
  176. }
  177. &.reverse:before{
  178. display: none;
  179. }
  180. }
  181. .text {
  182. line-height: 35upx;
  183. padding: 30upx 20upx;
  184. background: #fff;
  185. color: #000;
  186. word-wrap: break-word;
  187. &:before{
  188. border-color: transparent #fff transparent transparent;
  189. }
  190. &.reverse:after{
  191. border-color: transparent transparent transparent #007aff;
  192. }
  193. }
  194. .redpack {
  195. background: #EF9638;
  196. color: #fff;
  197. &:before{
  198. border-color: transparent #EF9638 transparent transparent;
  199. }
  200. &.reverse:after{
  201. border-color: transparent transparent transparent #EF9638;
  202. }
  203. &-open{
  204. background: #FDE1C3;
  205. .redpack-body-image{
  206. background: #FB998A;
  207. }
  208. .redpack-body-image::before{
  209. background: #FFF3E7;
  210. top: -110upx;
  211. }
  212. &:after{
  213. border-color: transparent transparent transparent #FDE1C3 !important;
  214. }
  215. }
  216. &-body {
  217. padding: 20upx;
  218. display: flex;
  219. justify-content: space-between;
  220. align-items: center;
  221. &-image {
  222. background: #CD3D35;
  223. width: 70upx;
  224. height: 90upx;
  225. overflow: hidden;
  226. position: relative;
  227. border-radius: 6upx;
  228. &:before {
  229. content: "";
  230. display: block;
  231. width: 140upx;
  232. height: 140upx;
  233. border-radius: 50%;
  234. position: absolute;
  235. top: -90upx;
  236. left: 50%;
  237. transform: translateX(-50%);
  238. background: #FA5151;
  239. }
  240. &:after {
  241. position: relative;
  242. display: block;
  243. content: '¥';
  244. width: 28upx;
  245. height: 28upx;
  246. background-color: #f2d252;
  247. color: #E08B34;
  248. border-radius: 28upx;
  249. line-height: 32upx;
  250. font-size: 24upx;
  251. transform: scale(.8);
  252. margin: 36upx auto;
  253. text-align: center;
  254. }
  255. }
  256. &-content {
  257. padding-left: 20upx;
  258. }
  259. }
  260. &-footer {
  261. font-size: 24upx;
  262. padding: 10upx 20upx;
  263. background: #fff;
  264. color: #999;
  265. border-bottom-left-radius: 12upx;
  266. border-bottom-right-radius: 12upx;
  267. }
  268. }
  269. .voice {
  270. width: 30%;
  271. position: relative;
  272. background: #007aff;
  273. color: #fff;
  274. &:before{
  275. border-color: transparent #007aff transparent transparent;
  276. }
  277. &.reverse:after{
  278. border-color: transparent transparent transparent #007aff;
  279. }
  280. &-text{
  281. margin-left: 60upx;
  282. line-height: 90upx;
  283. margin-right: 60upx;
  284. }
  285. &-text-right{
  286. text-align: right;
  287. }
  288. &-play{
  289. .second {
  290. animation: fadeInOut 1s infinite 0.2s;
  291. }
  292. .third {
  293. animation: fadeInOut 1s infinite 0.4s;
  294. }
  295. }
  296. }
  297. }
  298. .box {
  299. position: absolute;
  300. top: 50%;
  301. transform: translate(30upx,-50%);
  302. }
  303. .mybox{
  304. transform: rotateY(180deg);
  305. top: 25%;
  306. right: 15%;
  307. }
  308. .wifi-symbol {
  309. border: 1px solid red;
  310. width: 25px;
  311. height: 25px;
  312. box-sizing: border-box;
  313. overflow: hidden;
  314. transform: rotate(135deg);
  315. position: relative;
  316. }
  317. .wifi-circle {
  318. border: 2px solid #fff;
  319. border-radius: 50%;
  320. position: absolute;
  321. }
  322. .first {
  323. width: 2px;
  324. height: 2px;
  325. background: #fff;
  326. top: 22px;
  327. left: 22px;
  328. }
  329. .second {
  330. width: 12px;
  331. height: 12px;
  332. top: 17px;
  333. left: 17px;
  334. }
  335. .third {
  336. width: 20px;
  337. height: 20px;
  338. top: 12px;
  339. left: 12px;
  340. }
  341. @keyframes fadeInOut {
  342. 0% {
  343. opacity: 0;
  344. }
  345. 100% {
  346. opacity: 1;
  347. }
  348. }
  349. .blueBg{
  350. background: #007aff!important;
  351. color: #fff!important;
  352. }
  353. .description{
  354. min-width: 250upx;
  355. text-overflow: ellipsis;
  356. white-space: nowrap;
  357. overflow: hidden;
  358. }
  359. </style>