瀏覽代碼

no message

laosan2382995021@163.com 4 年之前
父節點
當前提交
d468935fe3
共有 100 個文件被更改,包括 2397 次插入298 次删除
  1. 7 2
      src/App.vue
  2. 0 1
      src/components/address/mixins/handle.ts
  3. 7 8
      src/components/flat-list/mixins/handle.ts
  4. 5 1
      src/components/flat-list/mixins/on.ts
  5. 26 25
      src/components/flat-list/src/main.vue
  6. 33 1
      src/components/scroll-view/mixins/on.ts
  7. 10 0
      src/components/svg-animate/props.ts
  8. 32 4
      src/components/svg-animate/src/main.vue
  9. 8 6
      src/components/swiper/src/main.vue
  10. 1 1
      src/components/upload/src/main.vue
  11. 2 2
      src/components/v-image/mixins/size.ts
  12. 4 0
      src/layout/layout-avatar/props.ts
  13. 1 1
      src/layout/layout-avatar/src/main.vue
  14. 21 5
      src/layout/layout-chat/mixins/handle.ts
  15. 19 0
      src/layout/layout-chat/props.ts
  16. 9 2
      src/layout/layout-chat/src/main.vue
  17. 18 2
      src/layout/layout-chat/style.scss
  18. 2 2
      src/layout/layout-dot/props.ts
  19. 2 2
      src/layout/layout-dot/src/main.vue
  20. 0 1
      src/layout/layout-play/mixins/handle.ts
  21. 6 1
      src/layout/layout-sex/props.ts
  22. 18 1
      src/layout/layout-sex/src/main.vue
  23. 1 0
      src/main.ts
  24. 16 0
      src/mixins/chat.ts
  25. 1 0
      src/mixins/queue.ts
  26. 94 0
      src/mixins/status/im.ts
  27. 0 2
      src/mixins/time.ts
  28. 12 1
      src/mixins/user.ts
  29. 3 0
      src/pages/home/mixins/index.ts
  30. 35 4
      src/pages/home/src/main.vue
  31. 1 1
      src/pages/talking/components/room-admission/src/main.vue
  32. 156 0
      src/pages/talking/components/room-gift/components/room-gift-item/mixins/giveGift.ts
  33. 2 1
      src/pages/talking/components/room-gift/components/room-gift-item/mixins/index.ts
  34. 44 2
      src/pages/talking/components/room-gift/components/room-gift-item/mixins/select.ts
  35. 22 0
      src/pages/talking/components/room-gift/components/room-gift-item/props.ts
  36. 20 20
      src/pages/talking/components/room-gift/components/room-gift-item/src/main.vue
  37. 34 2
      src/pages/talking/components/room-gift/components/room-gift-item/style.scss
  38. 6 6
      src/pages/talking/components/room-gift/data/tab.ts
  39. 22 0
      src/pages/talking/components/room-gift/props.ts
  40. 8 2
      src/pages/talking/components/room-gift/src/main.vue
  41. 1 0
      src/pages/talking/components/room-info/components/room-audience/data/type.ts
  42. 13 6
      src/pages/talking/components/room-info/components/room-audience/mixins/handle.ts
  43. 3 1
      src/pages/talking/components/room-info/components/room-audience/mixins/index.ts
  44. 36 0
      src/pages/talking/components/room-info/components/room-audience/mixins/people-online.ts
  45. 30 0
      src/pages/talking/components/room-info/components/room-audience/mixins/row-wheat.ts
  46. 4 2
      src/pages/talking/components/room-info/components/room-audience/src/main.vue
  47. 10 1
      src/pages/talking/components/room-info/mixins/handle.ts
  48. 5 3
      src/pages/talking/components/room-info/src/main.vue
  49. 3 0
      src/pages/talking/components/room-queue-gift/index.ts
  50. 137 0
      src/pages/talking/components/room-queue-gift/mixins/handle.ts
  51. 4 0
      src/pages/talking/components/room-queue-gift/mixins/index.ts
  52. 0 0
      src/pages/talking/components/room-queue-gift/props.ts
  53. 58 0
      src/pages/talking/components/room-queue-gift/src/main.vue
  54. 20 0
      src/pages/talking/components/room-queue-gift/style.scss
  55. 18 2
      src/pages/talking/components/room-ranking/components/room-chat/components/const.ts
  56. 7 1
      src/pages/talking/components/room-ranking/components/room-chat/components/index.ts
  57. 3 0
      src/pages/talking/components/room-ranking/components/room-chat/components/room-chat-entry/index.ts
  58. 10 0
      src/pages/talking/components/room-ranking/components/room-chat/components/room-chat-entry/props.ts
  59. 17 0
      src/pages/talking/components/room-ranking/components/room-chat/components/room-chat-entry/src/main.vue
  60. 13 0
      src/pages/talking/components/room-ranking/components/room-chat/components/room-chat-entry/style.scss
  61. 3 0
      src/pages/talking/components/room-ranking/components/room-chat/components/room-chat-message/index.ts
  62. 15 0
      src/pages/talking/components/room-ranking/components/room-chat/components/room-chat-message/props.ts
  63. 44 0
      src/pages/talking/components/room-ranking/components/room-chat/components/room-chat-message/src/main.vue
  64. 32 0
      src/pages/talking/components/room-ranking/components/room-chat/components/room-chat-message/style.scss
  65. 10 0
      src/pages/talking/components/room-ranking/components/room-chat/components/room-chat-system/props.ts
  66. 13 2
      src/pages/talking/components/room-ranking/components/room-chat/components/room-chat-system/src/main.vue
  67. 8 0
      src/pages/talking/components/room-ranking/components/room-chat/components/room-chat-system/style.scss
  68. 2 1
      src/pages/talking/components/room-ranking/components/room-chat/mixins/index.ts
  69. 71 1
      src/pages/talking/components/room-ranking/components/room-chat/mixins/message.ts
  70. 35 0
      src/pages/talking/components/room-ranking/components/room-chat/mixins/scroll.ts
  71. 9 3
      src/pages/talking/components/room-ranking/components/room-chat/src/main.vue
  72. 1 1
      src/pages/talking/components/room-ranking/components/room-chat/style.scss
  73. 6 3
      src/pages/talking/components/room-ranking/components/room-ranking-list/data/order.ts
  74. 5 5
      src/pages/talking/components/room-ranking/components/room-ranking-list/src/main.vue
  75. 3 3
      src/pages/talking/components/room-wheat/data/micro-control.ts
  76. 18 7
      src/pages/talking/components/room-wheat/src/main.vue
  77. 1 1
      src/pages/talking/components/room-wheat/style.scss
  78. 7 1
      src/pages/talking/mixins/agora.ts
  79. 33 0
      src/pages/talking/mixins/gift.ts
  80. 81 43
      src/pages/talking/mixins/handle.ts
  81. 7 1
      src/pages/talking/mixins/index.ts
  82. 92 10
      src/pages/talking/mixins/micro.ts
  83. 140 0
      src/pages/talking/mixins/socket.ts
  84. 35 3
      src/pages/talking/mixins/utils.ts
  85. 125 63
      src/pages/talking/mixins/wheat.ts
  86. 12 4
      src/pages/talking/src/main.vue
  87. 44 0
      src/popup/popup-chat/components/chat-content/components/chat-gift/mixins/handle.ts
  88. 3 0
      src/popup/popup-chat/components/chat-content/components/chat-gift/mixins/index.ts
  89. 10 0
      src/popup/popup-chat/components/chat-content/components/chat-gift/props.ts
  90. 56 8
      src/popup/popup-chat/components/chat-content/components/chat-gift/src/main.vue
  91. 8 0
      src/popup/popup-chat/components/chat-content/components/chat-gift/style.scss
  92. 22 6
      src/popup/popup-chat/components/chat-content/data/control.ts
  93. 8 1
      src/popup/popup-chat/components/chat-content/data/message-control.ts
  94. 22 3
      src/popup/popup-chat/components/chat-content/data/userContral.ts
  95. 二進制
      src/popup/popup-chat/components/chat-content/images/follow-active.png
  96. 二進制
      src/popup/popup-chat/components/chat-content/images/user-follow-active.png
  97. 81 0
      src/popup/popup-chat/components/chat-content/mixins/follow.ts
  98. 29 0
      src/popup/popup-chat/components/chat-content/mixins/gift.ts
  99. 198 2
      src/popup/popup-chat/components/chat-content/mixins/handle.ts
  100. 8 1
      src/popup/popup-chat/components/chat-content/mixins/index.ts

+ 7 - 2
src/App.vue

@@ -12,6 +12,8 @@
 <script>
 <script>
 import {layoutEntry} from '$layout';
 import {layoutEntry} from '$layout';
 import config from '$config/config';
 import config from '$config/config';
+import user from "$config/user";
+import socket from '$utils/socket/index';
 export default {
 export default {
 
 
   components:{
   components:{
@@ -19,11 +21,14 @@ export default {
   },
   },
 
 
   created() {
   created() {
-    return config.register(this);
+    config.register(this);
+    if (user.isLogin()) {
+      socket.install(user.user)
+    }
   }
   }
 
 
 }
 }
 </script>
 </script>
 <style lang="scss">
 <style lang="scss">
   @import "assets/scss/entry/index";
   @import "assets/scss/entry/index";
-</style>
+</style>

+ 0 - 1
src/components/address/mixins/handle.ts

@@ -195,7 +195,6 @@ export default {
     created(){
     created(){
         this.open();
         this.open();
 
 
-        console.log(this);
     }
     }
 
 
 }
 }

+ 7 - 8
src/components/flat-list/mixins/handle.ts

@@ -83,24 +83,23 @@ export default <LibMixins>{
 
 
             // 构建索引
             // 构建索引
             if (this.indexes) {
             if (this.indexes) {
+
+                if (this.dataIndexes === undefined) this.dataIndexes = [];
                 // 获取索引
                 // 获取索引
-                let keys = [];
                 let resultData = [];
                 let resultData = [];
                 for (let i=0,count=data.length;i<count;i++) {
                 for (let i=0,count=data.length;i<count;i++) {
-                    if (!replace && this.dataIndexes.indexOf(data[i][this.indexes]) < 0) {
+                    if (this.dataIndexes.indexOf(data[i][this.indexes]) < 0) {
                         this.dataIndexes.push(data[i][this.indexes]);
                         this.dataIndexes.push(data[i][this.indexes]);
                         resultData.push(data[i]);
                         resultData.push(data[i]);
-                    } else {
-                        keys.push(data[i][this.indexes]);
                     }
                     }
                 }
                 }
-                if (replace) {
-                    this.dataIndexes = keys;
-                } else if (!replace && resultData.length !== data.length) {
+                if (resultData.length !== data.length) {
                     data = resultData;
                     data = resultData;
                 }
                 }
             }
             }
 
 
+
+
             if (replace) {
             if (replace) {
                 this.data = data;
                 this.data = data;
             } else {
             } else {
@@ -181,4 +180,4 @@ export default <LibMixins>{
         this._status = this.constStatus.default;
         this._status = this.constStatus.default;
     }
     }
 
 
-}
+}

+ 5 - 1
src/components/flat-list/mixins/on.ts

@@ -8,6 +8,11 @@ export default <LibMixins>{
 
 
     methods:{
     methods:{
 
 
+        // 当前是否正在执行状态
+        flat_is_loading(){
+            return this._status === this.constStatus.loading;
+        },
+
         flat_clear_to_start(){
         flat_clear_to_start(){
           if (this.data.length > 0 || this.status!==this.constStatus.default) {
           if (this.data.length > 0 || this.status!==this.constStatus.default) {
               // 控制为 无状态
               // 控制为 无状态
@@ -43,7 +48,6 @@ export default <LibMixins>{
 
 
         flat_unshift(id:number | string,item:Record<string, any>){
         flat_unshift(id:number | string,item:Record<string, any>){
             if (id) {
             if (id) {
-
                 if (this.start) {
                 if (this.start) {
                     this.setStatus(Status.success,[item]);
                     this.setStatus(Status.success,[item]);
                 } else {
                 } else {

+ 26 - 25
src/components/flat-list/src/main.vue

@@ -17,36 +17,37 @@
       <empty-item v-else-if="status === constStatus.none" :empty-text="emptyText"></empty-item>
       <empty-item v-else-if="status === constStatus.none" :empty-text="emptyText"></empty-item>
 
 
     </aside>
     </aside>
-    <scroll-view
-      v-else-if="!start"
-      class="screen"
-      @scroll-lower="pagingLoading"
-      :lowerThreshold="lowerThreshold"
-      :security-size="securitySize"
-    >
-      <slot name="layout" :data="data">
+    <slot v-else-if="!start" name="page">
+      <scroll-view
+          class="screen"
+          @scroll-lower="pagingLoading"
+          :lowerThreshold="lowerThreshold"
+          :security-size="securitySize"
+      >
+        <slot name="layout" :data="data">
 
 
-        <div class="row wrap">
-          <slot
-            name="item"
-            v-for="(item,index) in data"
-            :item="item"
-            :index="index"
-          ></slot>
-        </div>
-      </slot>
-      <!--  底部加载  -->
-      <footer v-if="usePaging" class="center flat-list-footer overflow">
-         <svg v-if="status === constStatus.loading" class="flat-list-footer-loading" viewBox="0 0 100 100" enable-background="new 0 0 0 0" xml:space="preserve">
+          <div class="row wrap">
+            <slot
+                name="item"
+                v-for="(item,index) in data"
+                :item="item"
+                :index="index"
+            ></slot>
+          </div>
+        </slot>
+        <!--  底部加载  -->
+        <footer v-if="usePaging" class="center flat-list-footer overflow">
+          <svg v-if="status === constStatus.loading" class="flat-list-footer-loading" viewBox="0 0 100 100" enable-background="new 0 0 0 0" xml:space="preserve">
               <path fill="#fff" d="M73,50c0-12.7-10.3-23-23-23S27,37.3,27,50 M30.9,50c0-10.5,8.5-19.1,19.1-19.1S69.1,39.5,69.1,50">
               <path fill="#fff" d="M73,50c0-12.7-10.3-23-23-23S27,37.3,27,50 M30.9,50c0-10.5,8.5-19.1,19.1-19.1S69.1,39.5,69.1,50">
                 <animateTransform attributeName="transform" attributeType="XML" type="rotate" dur="1s" from="0 50 50" to="360 50 50" repeatCount="indefinite"></animateTransform>
                 <animateTransform attributeName="transform" attributeType="XML" type="rotate" dur="1s" from="0 50 50" to="360 50 50" repeatCount="indefinite"></animateTransform>
             </path>
             </path>
          </svg>
          </svg>
-         <div @click="reload()" class="screen flat-list-footer-fail center cursor-pointer" v-else-if="status === constStatus.fail">加载错误,点击重试</div>
-      </footer>
-      <!--  底部占位  -->
-      <div v-if="occupancySize" :style="{height:occupancySize}"></div>
-    </scroll-view>
+          <div @click="reload()" class="screen flat-list-footer-fail center cursor-pointer" v-else-if="status === constStatus.fail">加载错误,点击重试</div>
+        </footer>
+        <!--  底部占位  -->
+        <div v-if="occupancySize" :style="{height:occupancySize}"></div>
+      </scroll-view>
+    </slot>
 
 
   </section>
   </section>
 
 

+ 33 - 1
src/components/scroll-view/mixins/on.ts

@@ -4,6 +4,38 @@ import Unit from '@/utils/unit/unit';
 
 
 export default <LibMixins>{
 export default <LibMixins>{
     methods:<ScrollRefComponents & LibMixins>{
     methods:<ScrollRefComponents & LibMixins>{
+
+        /*
+        *  获取 当前移动距离
+        * */
+        getScrollDistance:function(direction:'x' | 'y' = 'y') {
+            if (this._scrollConfig[direction]) {
+                return this._scrollConfig[direction][direction];
+            } else {
+                return 0;
+            }
+        },
+
+        /*
+        *  获取距离底部的距离
+        * */
+        getScrollEndDistance:function(direction:'x' | 'y' = 'y') {
+            let nowDistance = this.getScrollDistance(direction);
+
+            // 获取 高度
+            this.setScrollConfig();
+
+            let config = this._scrollConfig[direction];
+
+            if (config) {
+                // 返回距离底部的高度
+                return config.maxScroll - nowDistance;
+            } else {
+                return  0;
+            }
+
+        },
+
         scrollTo(scrollParams: scrollParams) {
         scrollTo(scrollParams: scrollParams) {
 
 
             // 获取配置文件
             // 获取配置文件
@@ -23,7 +55,7 @@ export default <LibMixins>{
 
 
         },
         },
 
 
-        scrollToEnd(scrollParams: scrollAnimateParams={},all:boolean) {
+        scrollToEnd(scrollParams: scrollAnimateParams={},all:boolean=false) {
 
 
             // 获取配置文件
             // 获取配置文件
             this.setScrollConfig();
             this.setScrollConfig();

+ 10 - 0
src/components/svg-animate/props.ts

@@ -5,6 +5,11 @@ export default {
         default:''
         default:''
     },
     },
 
 
+    playStatus:{
+      type:Boolean,
+      default:true
+    },
+
     defaultSrc:{
     defaultSrc:{
       type:String,
       type:String,
       default:''
       default:''
@@ -23,6 +28,11 @@ export default {
     loops:{
     loops:{
         type:Number,
         type:Number,
         default:0
         default:0
+    },
+
+    mode:{
+        type:String,
+        default:'AspectFill'
     }
     }
 
 
 }
 }

+ 32 - 4
src/components/svg-animate/src/main.vue

@@ -1,7 +1,7 @@
 <template>
 <template>
   <div class="relative center" @mouseenter="enter" @mouseleave="leave">
   <div class="relative center" @mouseenter="enter" @mouseleave="leave">
     <div v-if="draw" v-show="status" class="screen" ref="svg"></div>
     <div v-if="draw" v-show="status" class="screen" ref="svg"></div>
-    <v-image v-show="!status" :style="{width:size,height:size}" v-if="defaultSrc" backgroundColor="transparent" :src="defaultSrc"></v-image>
+    <v-image v-show="!status" v-if="defaultSrc" :display="!status" :getSizeFailBody="false" :style="{width:size,height:size}" backgroundColor="transparent" :src="defaultSrc"></v-image>
   </div>
   </div>
 </template>
 </template>
 
 
@@ -26,6 +26,21 @@ export default {
     src:function (){
     src:function (){
 
 
       return this.play(this.loops);
       return this.play(this.loops);
+    },
+    playStatus:function (){
+      if (this.playStatus !== this.status) {
+
+        this.status = this.playStatus;
+        if (this.status) {
+
+          if (!this.draw) this.draw = true;
+
+          return nextTick(()=> this.play(this.loops));
+        } else {
+          this.pause();
+        }
+
+      }
     }
     }
   },
   },
 
 
@@ -37,6 +52,7 @@ export default {
 
 
       if (this.$attrs.onStop) {
       if (this.$attrs.onStop) {
         this.player.onFinished(()=> this.$emit('stop'));
         this.player.onFinished(()=> this.$emit('stop'));
+        // this.player.onError(()=> this.$emit('stop'));
       }
       }
     },
     },
 
 
@@ -65,10 +81,17 @@ export default {
           this.player.loops = count;  // 设置循环播放次数是1
           this.player.loops = count;  // 设置循环播放次数是1
           this.player.setVideoItem(videoItem);
           this.player.setVideoItem(videoItem);
 
 
-          this.player.setContentMode('AspectFill');
+          if (this.mode) {
+            this.player.setContentMode(this.mode);
+          }
+
 
 
           this.player.startAnimation();
           this.player.startAnimation();
 
 
+        },()=>{
+          if (this.$attrs.onStop) {
+            this.$emit('stop');
+          }
         });
         });
       } else if (this.src === this.play_src){
       } else if (this.src === this.play_src){
         this.player.startAnimation();
         this.player.startAnimation();
@@ -97,21 +120,26 @@ export default {
   beforeUnmount() {
   beforeUnmount() {
     if (this.player) {
     if (this.player) {
       this.player.clear();
       this.player.clear();
+      this.player && this.player.destroyed && this.player.destroyed();
+
       this.player = undefined;
       this.player = undefined;
       this.parser = undefined;
       this.parser = undefined;
     }
     }
   },
   },
 
 
   mounted() {
   mounted() {
-    if (!this.hover){
+    if (this.status){
       this.play(this.loops);
       this.play(this.loops);
     }
     }
 
 
   },
   },
 
 
   created() {
   created() {
-    this.draw = !this.hover;
     this.status = !this.hover;
     this.status = !this.hover;
+    if (this.status) {
+      this.status = this.playStatus;
+    }
+    this.draw = this.status;
   },
   },
 
 
   components:{
   components:{

+ 8 - 6
src/components/swiper/src/main.vue

@@ -59,12 +59,14 @@ export default {
       return this.swiper && this.swiper.slideTo(index,speed);
       return this.swiper && this.swiper.slideTo(index,speed);
     },
     },
     change(){
     change(){
-
-      let index = this.swiper.realIndex;
-      if (index !== this.value) {
-        this.swiper && this.$emit('update:value',index);
-        return this.swiper && this.$emit('change',index);
+      if (this.swiper) {
+        let index = this.swiper.realIndex;
+        if (index !== this.value) {
+          this.swiper && this.$emit('update:value',index);
+          return this.swiper && this.$emit('change',index);
+        }
       }
       }
+
     }
     }
   },
   },
   mounted() {
   mounted() {
@@ -76,4 +78,4 @@ export default {
 }
 }
 </script>
 </script>
 
 
-<style scoped lang="scss" src="../style.scss"></style>
+<style scoped lang="scss" src="../style.scss"></style>

+ 1 - 1
src/components/upload/src/main.vue

@@ -9,7 +9,7 @@
           <div class="upload-icon center">
           <div class="upload-icon center">
             <icon type="add"></icon>
             <icon type="add"></icon>
           </div>
           </div>
-          <div class="upload-title">{{uploadText}}</div>
+          <div v-if="uploadText" class="upload-title">{{uploadText}}</div>
         </aside>
         </aside>
       </slot>
       </slot>
     </section>
     </section>

+ 2 - 2
src/components/v-image/mixins/size.ts

@@ -40,7 +40,7 @@ export default <LibMixins> {
         },
         },
 
 
         useGetBodySize():Boolean{
         useGetBodySize():Boolean{
-            return this.getSizeFailBody && this.show === undefined;
+            return this.getSizeFailBody && this.display === undefined;
         }
         }
     },
     },
 
 
@@ -51,7 +51,7 @@ export default <LibMixins> {
         }
         }
       },
       },
      display(value:boolean){
      display(value:boolean){
-          if (value === true && this.container && this.containerSize && this.containerSize.width <= 0 && this.containerSize.height <= 0) {
+          if (value && this.container && this.containerSize && this.containerSize.width <= 0 && this.containerSize.height <= 0) {
               this.containerSize = this.getElementSize(this.container);
               this.containerSize = this.getElementSize(this.container);
 
 
               /* 如果图片加载成功 */
               /* 如果图片加载成功 */

+ 4 - 0
src/layout/layout-avatar/props.ts

@@ -6,6 +6,10 @@ export default {
         default:''
         default:''
     },
     },
 
 
+    backgroundColor:{
+      type:String
+    },
+
     // 装扮
     // 装扮
     dressSrc:{
     dressSrc:{
         type:String,
         type:String,

+ 1 - 1
src/layout/layout-avatar/src/main.vue

@@ -1,6 +1,6 @@
 <template>
 <template>
   <div class="layout-avatar relative">
   <div class="layout-avatar relative">
-    <v-image :src="src" class="screen" :radius="radius">
+    <v-image :src="src" class="screen" :radius="radius" :backgroundColor="backgroundColor">
       <svg-animate v-if="dressPlaySrc" :hover="true" size="100%" :default-src="dressSrc" :src="dressPlaySrc" class="absolute layout-avatar-dress"></svg-animate>
       <svg-animate v-if="dressPlaySrc" :hover="true" size="100%" :default-src="dressSrc" :src="dressPlaySrc" class="absolute layout-avatar-dress"></svg-animate>
       <div v-else-if="dressSrc" class="absolute layout-avatar-dress">
       <div v-else-if="dressSrc" class="absolute layout-avatar-dress">
         <v-image :src="dressSrc" mode="scaleToFill" backgroundColor="transparent" class="screen"></v-image>
         <v-image :src="dressSrc" mode="scaleToFill" backgroundColor="transparent" class="screen"></v-image>

+ 21 - 5
src/layout/layout-chat/mixins/handle.ts

@@ -1,17 +1,33 @@
 
 
+import MessageType from "$utils/socket/const/messageType";
+
 export default <LibMixins>{
 export default <LibMixins>{
 
 
+    data(){
+        return {
+            MessageType
+        }
+    },
+
     computed:{
     computed:{
 
 
+        user(){
+          return this.userInfo[this.item.uid] || {};
+        },
+
         reverse(){
         reverse(){
-            return true;
+            return this.item.uid == this.nowUid;
         },
         },
 
 
         message(){
         message(){
-            let message = '你好啊\n我是谁\n我也不知道';
-            return message.replace(/[\n\r]/g,function () {
-                return '<br />';
-            });
+            if (this.item.message) {
+                return this.item.message.replace(/[\n\r]/g,function () {
+                    return '<br />';
+                });
+            } else {
+                return  '';
+            }
+
         }
         }
 
 
     }
     }

+ 19 - 0
src/layout/layout-chat/props.ts

@@ -1,5 +1,24 @@
 export default {
 export default {
 
 
+    // 用户信息
+    userInfo:{
+        type:Object,
+        default:function () {
+            return {}
+        }
+    },
 
 
+    // 本人的id
+    nowUid:{
+        type:Number,
+        default:0
+    },
 
 
+    // 消息
+    item:{
+        type:Object,
+        default:function () {
+            return {}
+        }
+    }
 }
 }

+ 9 - 2
src/layout/layout-chat/src/main.vue

@@ -4,9 +4,16 @@
       'layout-chat-reverse':reverse
       'layout-chat-reverse':reverse
     }"
     }"
   >
   >
-    <v-image class="layout-chat-avatar" radius="50%"></v-image>
+    <v-image class="layout-chat-avatar" :src="user.head_pic" radius="50%"></v-image>
     <aside class="flex-1 layout-chat-content relative rowACenter">
     <aside class="flex-1 layout-chat-content relative rowACenter">
-      <div class="layout-chat-message relative" v-html="message"></div>
+      <div v-if="item.type === MessageType.gift && item.gift" class="layout-chat-message relative row aCenter">
+        <span>赠送</span>
+        <span class="layout-chat-gift-name">{{item.gift.gift_name}}</span>
+        <icon type="close" class="layout-chat-close-icon"></icon>
+        <span>{{item.number}}</span>
+        <v-image mode="center" :src="item.gift.base_image" backgroundColor="transparent" class="layout-chat-gift"></v-image>
+      </div>
+      <div v-else class="layout-chat-message relative" v-html="message"></div>
     </aside>
     </aside>
   </section>
   </section>
 </template>
 </template>

+ 18 - 2
src/layout/layout-chat/style.scss

@@ -1,7 +1,7 @@
 /* 外层模块 */
 /* 外层模块 */
 .layout-chat{
 .layout-chat{
   padding: 0 14px;
   padding: 0 14px;
-  margin-top: 24px;
+  margin-bottom: 24px;
 }
 }
 /* 外层模块 */
 /* 外层模块 */
 /* 用户头像 */
 /* 用户头像 */
@@ -68,4 +68,20 @@
   border-right: 4px solid transparent;
   border-right: 4px solid transparent;
   border-left: 6px solid rgba(255,255,255,0.1);
   border-left: 6px solid rgba(255,255,255,0.1);
 }
 }
-/* right 方向 */
+/* right 方向 */
+
+/* 礼物 */
+.layout-chat-close-icon{
+  font-size: 14px;
+  transform: scale(0.6) translateY(3px);
+}
+.layout-chat-gift-name{
+  color: #FF9D62;
+}
+.layout-chat-gift{
+  @include square(25px);
+}
+.layout-chat-gift-name,.layout-chat-gift{
+  margin-left: 5px;
+}
+/* 礼物 */

+ 2 - 2
src/layout/layout-dot/props.ts

@@ -2,7 +2,7 @@ export default {
 
 
     value:{
     value:{
         type:Number,
         type:Number,
-        default:17
+        default:0
     },
     },
 
 
     min:{
     min:{
@@ -20,4 +20,4 @@ export default {
         default:'+'
         default:'+'
     }
     }
 
 
-}
+}

+ 2 - 2
src/layout/layout-dot/src/main.vue

@@ -1,5 +1,5 @@
 <template>
 <template>
-  <div class="layout-dot center">{{numberFormat}}</div>
+  <div class="layout-dot center" v-show="value > 0">{{numberFormat}}</div>
 </template>
 </template>
 
 
 <script>
 <script>
@@ -22,4 +22,4 @@ export default {
 }
 }
 </script>
 </script>
 
 
-<style scoped lang="scss" src="../style.scss"></style>
+<style scoped lang="scss" src="../style.scss"></style>

+ 0 - 1
src/layout/layout-play/mixins/handle.ts

@@ -77,7 +77,6 @@ export default <LibMixins>{
 
 
         triggerDetail(){
         triggerDetail(){
 
 
-            console.log(this.item);
             return personalDetail.openDetail({
             return personalDetail.openDetail({
                 uid: this.item.uid,
                 uid: this.item.uid,
                 pid: this.item.pid
                 pid: this.item.pid

+ 6 - 1
src/layout/layout-sex/props.ts

@@ -10,7 +10,12 @@ export default {
     // 年龄
     // 年龄
     age:{
     age:{
         type:Number,
         type:Number,
-        default:18
+        default:0
+    },
+
+    birthday:{
+        type:String,
+        default:''
     }
     }
 
 
 }
 }

+ 18 - 1
src/layout/layout-sex/src/main.vue

@@ -2,7 +2,7 @@
   <div class="row">
   <div class="row">
     <div v-if="config" :style="{backgroundColor:config.color}" class="layout-sex rowACenter">
     <div v-if="config" :style="{backgroundColor:config.color}" class="layout-sex rowACenter">
       <icon :type="config.icon" class="layout-sex-icon"></icon>
       <icon :type="config.icon" class="layout-sex-icon"></icon>
-      <span>{{age}}</span>
+      <span>{{nowAge}}</span>
     </div>
     </div>
   </div>
   </div>
 </template>
 </template>
@@ -13,12 +13,29 @@ import {
 } from '$components';
 } from '$components';
 import config from '../data/config';
 import config from '../data/config';
 import props from '../props';
 import props from '../props';
+import {DateFormat} from "$utils/tool/date";
 export default {
 export default {
   name: "layout-sex",
   name: "layout-sex",
 
 
   computed:{
   computed:{
     config(){
     config(){
       return config[this.type];
       return config[this.type];
+    },
+
+    nowAge(){
+      if (this.age) {
+        return this.age;
+      } else if (this.birthday) {
+        let nowYear = new Date().getFullYear();
+
+        let usePeople = DateFormat.inverse(this.birthday,'YYYY-MM-DD');
+
+        let age = Math.ceil(nowYear - usePeople.year);
+
+        return  age < 0 ? 0 : age;
+      } else {
+        return  0;
+      }
     }
     }
   },
   },
 
 

+ 1 - 0
src/main.ts

@@ -8,5 +8,6 @@ import 'ant-design-vue/dist/antd.css';
 import popup from '$popup/popup-export/global';
 import popup from '$popup/popup-export/global';
 import request from "$utils/request";
 import request from "$utils/request";
 
 
+
 const app = createApp(App).use(store).use(router).use(popup).use(request).mount('#app')
 const app = createApp(App).use(store).use(router).use(popup).use(request).mount('#app')
 
 

+ 16 - 0
src/mixins/chat.ts

@@ -0,0 +1,16 @@
+export default {
+
+    computed:{
+        chatUserList:{
+            get(){
+                return this.$store.state.chat.chatUserList;
+            }
+        },
+        chatUserObject:{
+            get(){
+                return this.$store.state.chat.chatUserObject;
+            }
+        },
+    }
+
+}

+ 1 - 0
src/mixins/queue.ts

@@ -40,6 +40,7 @@ export default <LibMixins>{
           let item = this.queue.shift();
           let item = this.queue.shift();
           if (item){
           if (item){
               this.useQueueItem = item.data;
               this.useQueueItem = item.data;
+              this.triggerChangeQueue && this.triggerChangeQueue();
           } else {
           } else {
               this.triggerStatus = false;
               this.triggerStatus = false;
               clearTimeout(this.triggerTime);
               clearTimeout(this.triggerTime);

+ 94 - 0
src/mixins/status/im.ts

@@ -0,0 +1,94 @@
+import Status from './const/status';
+export default <LibMixins>{
+
+    data(){
+        return {
+            // 当前状态
+            status: Status.default,
+            // 是否使用唯一值
+            status_unique: true,
+            // 请求的名称
+            status_fetch_key:'getMessages',
+            // 常量
+            constStatus: Status,
+            // 最大数量
+            pageSize:20
+        }
+    },
+
+    methods:{
+
+        // 设置状态变更
+        setStatus(status,data?:any){
+
+            if (status !== this._status) {
+                clearTimeout(this._statusTime);
+                this._status = status;
+                if (this[this.status_async_key] && status === Status.loading) {
+                    this._statusTime = setTimeout(()=>{
+                        this.status = this._status;
+                    },this[this.status_async_key]);
+                } else {
+                    this.status = status;
+                }
+
+                this.triggerChangeStatus && this.triggerChangeStatus(status,data);
+            }
+        },
+
+        // 开启请求
+        statusFetch:function (must:boolean=false,data:any) {
+
+            // 如果当前状态为请求中就结束本次请求
+            if ((this._status === Status.loading || this._status === Status.none) && !must) return;
+
+            let unique = '';
+            if (this.status_unique) {
+                unique = new Date().getTime() + '-' + Math.floor(Math.random() * 10000);
+                this._statusUseUnique = unique;
+            }
+
+            this.setStatus(Status.loading);
+
+            return this[this.status_fetch_key] && this[this.status_fetch_key]({
+                success:(data?:any)=> {
+                    if (!this.status_unique || unique === this._statusUseUnique) {
+
+                        if (data && data.length < this.pageSize) {
+                            return this.setStatus(Status.none,data);
+                        } else {
+                            return this.setStatus(Status.success,data);
+                        }
+                    }
+                    // @ts-ignore
+                    unique = null;
+                },
+                fail:()=> {
+                    if (!this.status_unique || unique === this._statusUseUnique) {
+                        return this.setStatus(Status.fail);
+                    }
+                    // @ts-ignore
+                    unique = null;
+                },
+                none:()=>{
+                    if (!this.status_unique || unique === this._statusUseUnique) {
+                        return this.setStatus(Status.none);
+                    }
+                    // @ts-ignore
+                    unique = null;
+                },
+                unique,
+                data:{
+                    ...(data || {}),
+                    pageSize: this.pageSize
+                }
+            });
+
+        }
+
+    },
+    created(){
+        this._status = Status.default;
+    }
+
+}

+ 0 - 2
src/mixins/time.ts

@@ -34,8 +34,6 @@ export default <LibMixins>{
                 }
                 }
             }
             }
 
 
-            console.log(item,data);
-
             if (resultData) {
             if (resultData) {
                 resultData.key = 'mobile';
                 resultData.key = 'mobile';
                 verification.verificationPromise(resultData,true).then((data)=>{
                 verification.verificationPromise(resultData,true).then((data)=>{

+ 12 - 1
src/mixins/user.ts

@@ -1,4 +1,5 @@
 import user from '$config/user';
 import user from '$config/user';
+import popup, {PopupExportComponent} from "$utils/tool/popup";
 
 
 export default {
 export default {
 
 
@@ -35,6 +36,16 @@ export default {
                 }
                 }
             }
             }
         }
         }
+    },
+
+    methods:{
+
+        openLogin(){
+            if (!this.$store.getters.isLogin) {
+                return popup.$open(PopupExportComponent.login);
+            }
+        }
+
     }
     }
 
 
-}
+}

+ 3 - 0
src/pages/home/mixins/index.ts

@@ -0,0 +1,3 @@
+import params from '$mixins/params';
+
+export default [params];

+ 35 - 4
src/pages/home/src/main.vue

@@ -3,7 +3,7 @@
     <view-header></view-header>
     <view-header></view-header>
     <section class="flex-1 row container">
     <section class="flex-1 row container">
       <article class="flex-1 content-container">
       <article class="flex-1 content-container">
-        <tab :data="tabData">
+        <tab :data="tabData" v-model:value="value">
           <template
           <template
               v-for="(item,index) in tabData"
               v-for="(item,index) in tabData"
               v-slot:[item.slot]
               v-slot:[item.slot]
@@ -35,15 +35,45 @@ import {
   viewTalking
   viewTalking
 } from '$views';
 } from '$views';
 
 
+import mixins from '../mixins';
+
 import tabData from "../data/tabData";
 import tabData from "../data/tabData";
 
 
+import socket from '$utils/socket';
+import {NoticeType} from "../../../utils/socket/const";
+
 export default {
 export default {
   name: "home",
   name: "home",
   data(){
   data(){
     return {
     return {
-      tabData
+      tabData,
+      value:0
     }
     }
   },
   },
+
+
+  created() {
+    // // 针对不同的选择默认不同的选项
+    let select = this.$params.select === 1 ?1:0;
+    if (this.value !== this.$params.select) {
+      this.value = select;
+    }
+    //
+    socket.on('home',(data)=>{
+      if (data) {
+        let select = data.select === 1 ? 1:0;
+        if(select !== this.value) {
+          this.value = select;
+        }
+      }
+    },NoticeType.home)
+
+  },
+
+  beforeUnmount() {
+    socket.off('home',NoticeType.home)
+  },
+
   components:{
   components:{
     viewHeader,
     viewHeader,
     viewFooter,
     viewFooter,
@@ -51,8 +81,9 @@ export default {
     viewMenu,
     viewMenu,
     viewPlayWith,
     viewPlayWith,
     viewTalking
     viewTalking
-  }
+  },
+  mixins
 }
 }
 </script>
 </script>
 
 
-<style scoped lang="scss" src="../style.scss"></style>
+<style scoped lang="scss" src="../style.scss"></style>

+ 1 - 1
src/pages/talking/components/room-admission/src/main.vue

@@ -3,7 +3,7 @@
     <svg-animate
     <svg-animate
         class="room-admission-svg"
         class="room-admission-svg"
         v-if="useQueueItem"
         v-if="useQueueItem"
-        :src="useQueueItem.zq_play_image+'?id='+useQueueItem._id"
+        :src="useQueueItem.star_play_img+'?id='+useQueueItem._id"
         :loops="1"
         :loops="1"
         @stop="triggerQueueItem"
         @stop="triggerQueueItem"
     ></svg-animate>
     ></svg-animate>

+ 156 - 0
src/pages/talking/components/room-gift/components/room-gift-item/mixins/giveGift.ts

@@ -0,0 +1,156 @@
+import popup from "$utils/tool/popup";
+
+import userIntegral from '$utils/control/integral';
+
+import Throttle from '$utils/tool/throttle';
+import {InstructionsMessageType} from "$utils/request";
+
+export default {
+
+    data(){
+      return {
+          // 当前是否处于点击状态
+          pressStatus: false,
+          // 当前点击次数
+          pressNumber:0
+
+      }
+    },
+
+    inject:['getRoomInfo','sendGiveUserGift','sendGift'],
+
+    methods:{
+
+        giveUserGift(){
+
+            // 获取礼物
+            let gift = this.giftData[this.giftSelect];
+
+            if (!gift) return popup.$toast('请选择赠送礼物');
+
+            if (!this.giveUserValue) {
+                return popup.$confirm({
+                    title:'暂未选择赠送人,是否赠送全部麦序',
+                    confirm:()=>{
+                        this.giveUserValue = 'all';
+                    }
+                });
+            }
+
+
+            // 查看赠送用户
+            let giveUserId = this.giveUserValue;
+            // 如果为全部麦序触发
+            if (giveUserId === 'all') {
+                giveUserId = [];
+                this.userData.map((item)=>{
+                    giveUserId.push(item.uid);
+                });
+
+                if (giveUserId.length <=0) return  popup.$toast('未有人上麦');
+            }
+
+            if (!(giveUserId instanceof Array)) {
+                giveUserId = [giveUserId];
+            }
+
+            // 计算本次需要使用的积分
+            let integral = giveUserId.length * (parseFloat(gift.gift_price) || 0) * this.number;
+
+            // 查看用户余额是否足够
+            if (userIntegral.checkBalance(integral,true)) {
+                gift = JSON.parse(JSON.stringify(gift));
+                if (this.$refs.banner && this.$refs.banner.swiper) {
+                    gift.translate = this.$refs.banner.swiper.translate;
+                }
+
+                // 赠送礼物
+                this.sendGiveUserGift(gift,giveUserId,giveUserId.length * (parseFloat(gift.gift_price) || 0));
+                this.sendGift({
+                    gift,
+                    number:this.number,
+                    giveUserId,
+                    integral
+                });
+
+                // 减余额
+                userIntegral.reduceBalance(integral,false);
+
+                // 设置当前的标识符
+                let unique = new Date().getTime() + '-'+ Math.ceil(Math.random() * 10000);
+
+                this.requestUnique = unique;
+
+                // 赠送礼物
+                this.$request({
+                    url:'gift/send_gift',
+                    data:{
+                        to_uid_list: giveUserId.join(','),
+                        num: this.number,
+                        pack:1,
+                        rid: this.roomInfo.rid,
+                        gid: gift.gid
+                    },
+                    token:true,
+                    message:InstructionsMessageType.other,
+                    failMessage:true
+                }).then((data)=>{
+                    if (data.isSuccess) {
+                        this.checkUpdateUserIntegral(unique);
+                        this.sendGift({
+                            gift,
+                            number:this.number,
+                            giveUserId,
+                            integral
+                        },true);
+                    } else {
+                        this.plusBalance(integral,false);
+                        this.checkUpdateUserIntegral(unique);
+                    }
+
+                }).catch(()=>{
+                    this.plusBalance(integral,false);
+                    this.checkUpdateUserIntegral(unique);
+                });
+
+                /* 设置持续点击的动画 */
+                if (!this.pressStatus) {
+                    this.pressStatus = true;
+                }
+                this.pressNumber+=1;
+                return this.giveChangeNumber();
+            }
+
+        },
+
+        checkUpdateUserIntegral(unique){
+            if (this.requestUnique === unique) {
+                this.requestUnique = null;
+                // 向服务端同步
+                return userIntegral.updateUserMoney();
+            }
+        },
+
+        giveChangeNumber(){
+            this.pressStatus = false;
+            this.pressNumber = 0;
+        }
+
+    },
+
+    created(){
+        this.roomInfo = this.getRoomInfo();
+        this.giveChangeNumberThrottle = new Throttle({
+            call:this,
+            handle:this.giveChangeNumber,
+            first:false,
+            delay:1000
+        });
+        this.giveChangeNumber = this.giveChangeNumberThrottle.supper;
+    },
+
+    beforeUnmount() {
+        this.giveChangeNumberThrottle && this.giveChangeNumberThrottle.destroy();
+    }
+
+}

+ 2 - 1
src/pages/talking/components/room-gift/components/room-gift-item/mixins/index.ts

@@ -1,5 +1,6 @@
 import handle from './handle';
 import handle from './handle';
 import select from './select';
 import select from './select';
 import gift from './gift';
 import gift from './gift';
+import giveGift from "./giveGift";
 
 
-export default [handle,select,gift];
+export default [giveGift,handle,select,gift];

+ 44 - 2
src/pages/talking/components/room-gift/components/room-gift-item/mixins/select.ts

@@ -1,12 +1,54 @@
+import userAppendData from "../data/user";
+
 export default <LibMixins>{
 export default <LibMixins>{
 
 
+    inject:['triggerChangeGiveUserId'],
+
     data(){
     data(){
         return {
         return {
             // 选择的数量
             // 选择的数量
             number:1,
             number:1,
             // 赠送的用户
             // 赠送的用户
-            giveUser:undefined
+            giveUserValue:undefined
+        }
+    },
+
+    computed:{
+        giveUserNoHave(){
+            return this.giveUser && this.giveUser.uid && this.useUserIds.indexOf(this.giveUser.uid) < 0;
+        },
+
+        useUserIds(){
+          return this.useUserData.map((item)=> item.uid);
+        },
+        useUserData(){
+            return [...this.userData,...userAppendData];
+        },
+        giftData(){
+            return this.$store.state.gift.giftData;
+        }
+    },
+
+    watch:{
+        giveUserValue(){
+            this.changeGiveUserTop(this.giveUserValue);
+        },
+        giveUserId(){
+           return this.changeGiveUserValue(this.giveUserId);
+        }
+    },
+
+    methods:{
+        changeGiveUserValue(value){
+            if (this.giveUserValue !== value) {
+                this.giveUserValue = value;
+            }
+        },
+        changeGiveUserTop(value){
+            if (this.giveUser !== value) {
+                this.triggerChangeGiveUserId(value);
+            }
         }
         }
     }
     }
 
 
-}
+}

+ 22 - 0
src/pages/talking/components/room-gift/components/room-gift-item/props.ts

@@ -0,0 +1,22 @@
+export default {
+
+    userData:{
+        type:Array,
+        default:function () {
+            return [];
+        }
+    },
+
+    giveUserId:{
+        type:[Number,String],
+        default:0
+    },
+
+    giveUser:{
+        type:Object,
+        default:function (){
+            return {}
+        }
+    }
+
+}

+ 20 - 20
src/pages/talking/components/room-gift/components/room-gift-item/src/main.vue

@@ -28,6 +28,7 @@
             <div class="talking-gift-image-warp center">
             <div class="talking-gift-image-warp center">
               <v-image
               <v-image
                   class="talking-gift-image"
                   class="talking-gift-image"
+                  :id="index === giftSelect?'gift-active-'+item.gid:''"
                   :src="item.base_image"
                   :src="item.base_image"
                   backgroundColor="transparent"
                   backgroundColor="transparent"
               ></v-image>
               ></v-image>
@@ -65,11 +66,16 @@
         </div>
         </div>
       </div>
       </div>
       <div class="talking-gift-footer-margin">给</div>
       <div class="talking-gift-footer-margin">给</div>
-      <div class="relative">
+      <div class="relative"
+           :class="{
+            'talking-gift-not-user-select': giveUserNoHave
+           }"
+      >
         <a-select class="talking-gift-user talking-gift-select"
         <a-select class="talking-gift-user talking-gift-select"
                   dropdownClassName="talking-gift-dropdown"
                   dropdownClassName="talking-gift-dropdown"
+
                   placeholder="送给TA"
                   placeholder="送给TA"
-                  v-model:value="giveUser"
+                  v-model:value="giveUserValue"
         >
         >
           <a-select-option
           <a-select-option
               v-for="(item,index) in useUserData"
               v-for="(item,index) in useUserData"
@@ -90,9 +96,15 @@
         <div class="absolute talking-gift-select-modal jCenter aEnd">
         <div class="absolute talking-gift-select-modal jCenter aEnd">
           <icon type="down" class="talking-gift-select-icon"></icon>
           <icon type="down" class="talking-gift-select-icon"></icon>
         </div>
         </div>
+        <div class="talking-gift-no-user absolute jCenter" v-if="giveUserNoHave">
+          <div class="talking-select-label line-1">{{giveUser.nick_name}}</div>
+        </div>
+      </div>
+      <!--  赠送  -->
+      <div @click="giveUserGift" class="room-gift-give cursor-pointer center">
+        <span v-if="pressNumber<1">赠送</span>
+        <div v-else :key="'give-'+pressNumber" class="row room-gift-give-count"><span class="iconfont icon-close room-gift-give-close"></span>{{pressNumber}}</div>
       </div>
       </div>
-      <!--  赠送   -->
-      <div class="room-gift-give button">赠送</div>
 
 
     </footer>
     </footer>
 
 
@@ -110,7 +122,7 @@ import unit from "$utils/unit/unit";
 import mixins from '../mixins/index';
 import mixins from '../mixins/index';
 import {Select} from "ant-design-vue";
 import {Select} from "ant-design-vue";
 import numberData from '../data/number';
 import numberData from '../data/number';
-import userAppendData from '../data/user';
+import props from '../props';
 export default {
 export default {
   name: "room-gift-item",
   name: "room-gift-item",
 
 
@@ -122,22 +134,10 @@ export default {
         threshold:unit.unitPx(10)
         threshold:unit.unitPx(10)
       },
       },
 
 
-      numberData,
-      userData:[]
-    }
-  },
-
-  computed:{
-    useUserData(){
-      return [...this.userData,{
-        label: this.$store.state.user.user.nick_name,
-        icon: this.$store.state.user.user.head_pic
-      },...userAppendData];
-    },
-    giftData(){
-      return this.$store.state.gift.giftData;
+      numberData
     }
     }
   },
   },
+  props,
 
 
   mixins,
   mixins,
 
 
@@ -154,4 +154,4 @@ export default {
 
 
 <style scoped lang="scss" src="../style.scss"></style>
 <style scoped lang="scss" src="../style.scss"></style>
 
 
-<style lang="scss" src="../global.scss"></style>
+<style lang="scss" src="../global.scss"></style>

+ 34 - 2
src/pages/talking/components/room-gift/components/room-gift-item/style.scss

@@ -19,6 +19,9 @@
 .talking-gift-banner-margin{
 .talking-gift-banner-margin{
   margin: 0 25px;
   margin: 0 25px;
 }
 }
+.talking-gift-not-user-select::v-deep .ant-select-selection-item{
+  display: none;
+}
 .talking-gift-trigger-icon{
 .talking-gift-trigger-icon{
   @include square(20px);
   @include square(20px);
 }
 }
@@ -45,6 +48,14 @@
 .talking-gift-banner:last-of-type{
 .talking-gift-banner:last-of-type{
   margin-right: 0 !important;
   margin-right: 0 !important;
 }
 }
+.talking-gift-no-user{
+  top: 0;
+  left: 20px;
+  width: 83px;
+  bottom: 0;
+  pointer-events: none;
+  //background-color: ;
+}
 /* 礼物模块 */
 /* 礼物模块 */
 
 
 /* 底部模块 */
 /* 底部模块 */
@@ -155,12 +166,33 @@
 }
 }
 .room-gift-give{
 .room-gift-give{
   margin-left: 10px;
   margin-left: 10px;
-  width: 70px;
+  min-width: 70px;
   height: 32px;
   height: 32px;
   background: #FF6969;
   background: #FF6969;
   font-size: 14px;
   font-size: 14px;
   line-height: 18px;
   line-height: 18px;
   font-weight: 400;
   font-weight: 400;
   border-radius: 16px;
   border-radius: 16px;
+  padding: 0 15px;
+  transition: .3s;
 }
 }
-/* 底部模块 */
+.room-gift-give-count{
+  animation: giveCount .3s 1 forwards;
+  font-weight: bold;
+  font-size: 16px;
+}
+.room-gift-give-close{
+  font-size: 12px;
+  color: #fff;
+  transform: scale(0.7);
+  margin-left: -2px;
+}
+@keyframes giveCount {
+  0% {
+    transform: scale(1.3);
+  }
+  100%{
+    transform: scale(1);
+  }
+}
+/* 底部模块 */

+ 6 - 6
src/pages/talking/components/room-gift/data/tab.ts

@@ -3,9 +3,9 @@ export default [
         label:'热门',
         label:'热门',
         slot:'0'
         slot:'0'
     },
     },
-    {
-        label:'我的背包',
-        align:'right',
-        slot:'1'
-    }
-] as LibDataArray
+    // {
+    //     label:'我的背包',
+    //     align:'right',
+    //     slot:'1'
+    // }
+] as LibDataArray

+ 22 - 0
src/pages/talking/components/room-gift/props.ts

@@ -0,0 +1,22 @@
+export default {
+
+    userData:{
+        type:Array,
+        default:function () {
+            return [];
+        }
+    },
+
+    giveUserId:{
+        type:[Number,String],
+        default:0
+    },
+
+    giveUser:{
+        type:Object,
+        default:function (){
+            return {}
+        }
+    }
+
+}

+ 8 - 2
src/pages/talking/components/room-gift/src/main.vue

@@ -27,6 +27,9 @@
       >
       >
         <room-gift-item
         <room-gift-item
           :key="'room-gift-item-'+index"
           :key="'room-gift-item-'+index"
+          :user-data="userData"
+          :giveUserId="giveUserId"
+          :give-user="giveUser"
         ></room-gift-item>
         ></room-gift-item>
       </template>
       </template>
 
 
@@ -40,6 +43,7 @@ import {
   tab
   tab
 } from '$components';
 } from '$components';
 import roomGiftItem from '../components/room-gift-item';
 import roomGiftItem from '../components/room-gift-item';
+import props from '../props';
 export default {
 export default {
   name: "room-gift",
   name: "room-gift",
 
 
@@ -52,9 +56,11 @@ export default {
   components:{
   components:{
     tab,
     tab,
     roomGiftItem
     roomGiftItem
-  }
+  },
+
+  props
 
 
 }
 }
 </script>
 </script>
 
 
-<style scoped lang="scss" src="../style.scss"></style>
+<style scoped lang="scss" src="../style.scss"></style>

+ 1 - 0
src/pages/talking/components/room-info/components/room-audience/data/type.ts

@@ -7,6 +7,7 @@ export default {
 
 
     // 排麦
     // 排麦
     'rowWheat':{
     'rowWheat':{
+        wheat:true,
 
 
     }
     }
 
 

+ 13 - 6
src/pages/talking/components/room-info/components/room-audience/mixins/handle.ts

@@ -1,15 +1,22 @@
+import typeData from '../data/type';
+import user from "$config/user";
 export default <LibMixins>{
 export default <LibMixins>{
 
 
-    inject:['getRoomInfo','openUserInfo','allowForWheat'],
+    inject:['getRoomInfo','openUserInfo','allowForWheat','getAgoraRTMIM'],
+
+    computed:{
+      audienceItem(){
+          return typeData[this.type] || {};
+      }
+    },
 
 
     methods:{
     methods:{
 
 
         fetch(obj){
         fetch(obj){
-            return this.getWheatList(obj);
             if (this.type === 'audience') {
             if (this.type === 'audience') {
                 return this.getAudienceList(obj);
                 return this.getAudienceList(obj);
             } else {
             } else {
-
+                return this.getWheatList(obj);
             }
             }
         },
         },
 
 
@@ -23,10 +30,9 @@ export default <LibMixins>{
                 page:obj.data,
                 page:obj.data,
                 token:true
                 token:true
             }).then((data)=>{
             }).then((data)=>{
-
                 data = data.data || {};
                 data = data.data || {};
 
 
-                data = [...data.micro_user_list,...data.unmicro_user_list];
+                data = [...data.room_admin_list,...data.room_visitor_list,...data.micro_user_list,user.user];
 
 
                 return obj.success(data);
                 return obj.success(data);
 
 
@@ -57,6 +63,7 @@ export default <LibMixins>{
 
 
     created() {
     created() {
         this.roomInfo = this.getRoomInfo();
         this.roomInfo = this.getRoomInfo();
+        this.agoraRTMIM = this.getAgoraRTMIM();
     }
     }
 
 
-}
+}

+ 3 - 1
src/pages/talking/components/room-info/components/room-audience/mixins/index.ts

@@ -1,3 +1,5 @@
 import handle from './handle';
 import handle from './handle';
+import rowWheat from './row-wheat';
+import peopleOnline from './people-online';
 
 
-export default [handle];
+export default [handle,rowWheat,peopleOnline];

+ 36 - 0
src/pages/talking/components/room-info/components/room-audience/mixins/people-online.ts

@@ -0,0 +1,36 @@
+import {AgoraRTMessage} from "$utils/socket/agoraRTM/const/channel";
+import {FlatListReload} from "$components/flat-list/const";
+
+export default {
+
+    created(){
+        if (this.type === 'audience') {
+
+            this.agoraRTMIM.on(AgoraRTMessage.joinHome,({data})=>{
+
+                if (this.$refs.flat) {
+                    if (data.userInfo && data.userInfo.uid && !this.$refs.flat.flat_is_loading()) {
+                        this.$refs.flat.flat_push(data.userInfo.uid,data.userInfo);
+                    } else {
+                        this.$refs.flat.reload(FlatListReload.mustReload);
+                    }
+
+                }
+
+            });
+
+            this.agoraRTMIM.on(AgoraRTMessage.leave,(data)=>{
+                if (this.$refs.flat) {
+                    let uid = parseInt(data);
+                    if (uid) {
+                        this.$refs.flat.flat_delete(uid);
+                    } else {
+                        this.$refs.flat.reload(FlatListReload.mustReload);
+                    }
+                }
+            });
+
+        }
+    }
+
+}

+ 30 - 0
src/pages/talking/components/room-info/components/room-audience/mixins/row-wheat.ts

@@ -0,0 +1,30 @@
+import { AgoraRTMessage } from '$utils/socket/agoraRTM/const/channel';
+import {FlatListReload} from "$components/flat-list/const";
+export default {
+
+    created(){
+        if (this.type === 'rowWheat') {
+
+            this.agoraRTMIM.on(AgoraRTMessage.userRowWheat,({data})=>{
+
+                if (this.$refs.flat) {
+                    if (data.queueWheat && data.queueWheat.user && !this.$refs.flat.flat_is_loading()) {
+                        if (data.queueWheat.status) {
+                            this.$refs.flat.flat_unshift(data.queueWheat.user.uid,data.queueWheat.user);
+                        } else {
+                            this.$refs.flat.flat_delete(data.queueWheat.user.uid);
+                        }
+                    } else {
+                        this.$refs.flat.reload(FlatListReload.mustReload);
+                    }
+
+                }
+
+
+
+            });
+
+        }
+    }
+
+}

+ 4 - 2
src/pages/talking/components/room-info/components/room-audience/src/main.vue

@@ -3,6 +3,8 @@
     <flat-list
     <flat-list
       @fetch="fetch"
       @fetch="fetch"
       :security-size="10"
       :security-size="10"
+      ref="flat"
+      indexes="uid"
     >
     >
       <template v-slot:item="{item,index}">
       <template v-slot:item="{item,index}">
         <aside class="room-audience-item rowACenter" >
         <aside class="room-audience-item rowACenter" >
@@ -15,10 +17,10 @@
           <section class="flex-1 room-audience-content">
           <section class="flex-1 room-audience-content">
             <div class="line-1 room-audience-username">{{item.nick_name}}</div>
             <div class="line-1 room-audience-username">{{item.nick_name}}</div>
             <section class="row">
             <section class="row">
-              <layout-sex :type="item.sex"></layout-sex>
+              <layout-sex :type="item.sex" :birthday="item.birthday"></layout-sex>
             </section>
             </section>
           </section>
           </section>
-          <div v-if="admin" @click="triggerAllowForWheat(item)" class="center room-audience-wheat cursor-pointer">上麦</div>
+          <div v-if="admin && audienceItem.wheat" @click="triggerAllowForWheat(item)" class="center room-audience-wheat cursor-pointer">上麦</div>
         </aside>
         </aside>
       </template>
       </template>
     </flat-list>
     </flat-list>

+ 10 - 1
src/pages/talking/components/room-info/mixins/handle.ts

@@ -3,6 +3,7 @@ import user from "$config/user";
 
 
 import socket from '$utils/socket';
 import socket from '$utils/socket';
 import {NoticeType} from "$utils/socket/const";
 import {NoticeType} from "$utils/socket/const";
+import popup, {PopupExportComponent} from "$utils/tool/popup";
 
 
 export default <LibMixins>{
 export default <LibMixins>{
 
 
@@ -20,6 +21,14 @@ export default <LibMixins>{
 
 
     methods:{
     methods:{
 
 
+        // 举报
+        report(){
+            popup.$open(PopupExportComponent.report,{
+                rid: this.info.rid
+            });
+        },
+
+
         // 触发更改关注
         // 触发更改关注
         triggerFollow(){
         triggerFollow(){
             return this.setCollect(this.collect?0:1,true);
             return this.setCollect(this.collect?0:1,true);
@@ -78,4 +87,4 @@ export default <LibMixins>{
     }
     }
 
 
 
 
-}
+}

+ 5 - 3
src/pages/talking/components/room-info/src/main.vue

@@ -7,7 +7,7 @@
           <div class="flex-1">
           <div class="flex-1">
             <div class="room-info-name line-1">{{info.room_name}}</div>
             <div class="room-info-name line-1">{{info.room_name}}</div>
           </div>
           </div>
-          <div class="room-info-span cursor-pointer">举报</div>
+          <div @click="report" class="room-info-span cursor-pointer">举报</div>
         </div>
         </div>
         <div class="rowACenter room-info-id-container">
         <div class="rowACenter room-info-id-container">
           <div class="room-info-id">ID:{{info.room_number}}</div>
           <div class="room-info-id">ID:{{info.room_number}}</div>
@@ -57,7 +57,9 @@
                 'room-info-tab-item-active': index===select
                 'room-info-tab-item-active': index===select
               }"
               }"
                   @click="trigger(index)"
                   @click="trigger(index)"
-              >{{item.label}}<span v-if="item.key && info[item.key] >0">({{info[item.key]>=99?'99+':info[item.key]}})</span></aside>
+              >{{item.label}}
+<!--                <span v-if="item.key && info[item.key] >0">({{info[item.key]>=99?'99+':info[item.key]}})</span>-->
+              </aside>
               <div class="room-info-line absolute center"
               <div class="room-info-line absolute center"
                    :style="{width:avg+'%',left:avg * select +'%'}"
                    :style="{width:avg+'%',left:avg * select +'%'}"
               >
               >
@@ -158,4 +160,4 @@ export default {
 }
 }
 </script>
 </script>
 
 
-<style scoped lang="scss" src="../style.scss"></style>
+<style scoped lang="scss" src="../style.scss"></style>

+ 3 - 0
src/pages/talking/components/room-queue-gift/index.ts

@@ -0,0 +1,3 @@
+import main from './src/main.vue';
+
+export default main;

+ 137 - 0
src/pages/talking/components/room-queue-gift/mixins/handle.ts

@@ -0,0 +1,137 @@
+import {nextTick} from "vue";
+
+export default {
+
+    data(){
+        return {
+            queueTime:0
+        }
+    },
+
+    methods:{
+
+        // 播放礼物动画
+        pushGift(item,uid:Array<string | number> | string | number){
+
+            if (item.play_image){
+
+                let type = item.gift_type.toString();
+
+                if (type === '1') {
+
+                    let resultUid:Array<string | number> = [];
+                    if (!(uid instanceof Array)) {
+                        resultUid = [uid]
+                    } else {
+                        resultUid = uid;
+                    }
+
+                    let queueData = [];
+
+                    // 获取礼物布局信息
+                    let giftOffsets = this.getInfoOffset('gift-active-'+item.gid);
+
+                    if (giftOffsets) {
+                        if (item.translate) {
+                            giftOffsets.x = giftOffsets.x + item.translate;
+                        }
+                    }
+
+                    // 获取用户布局信息结果
+                    resultUid.map((item)=>{
+                        let result = this.getInfoOffset('user-'+item);
+
+                        if (result) {
+                            if (giftOffsets) {
+                                queueData.push({
+                                    offset:result,
+                                    giftOffsets,
+                                    ...giftOffsets
+                                });
+                            } else {
+                                queueData.push({
+                                    ...result,
+                                });
+                            }
+                        }
+
+                        return result;
+                    });
+
+                    if (queueData.length > 0) {
+                        this.pushQueue({
+                            type:type,
+                            data:queueData,
+                            item,
+                            play:!giftOffsets,
+                            draw:!giftOffsets
+                        });
+                    } else {
+                        this.pushQueue({
+                            type:'2',
+                            item
+                        });
+                    }
+                } else {
+                    this.pushQueue({
+                        type:type,
+                        item
+                    });
+                }
+            }
+
+        },
+
+        triggerChangeQueue(){
+            if (this.useQueueItem && this.useQueueItem.type === '1' && !this.useQueueItem.play) {
+                setTimeout(()=>{
+                    this.useQueueItem.data = this.useQueueItem.data.map((item)=>{
+                        return {
+                            ...item,
+                            ...item.offset,
+                        }
+                    });
+                    this.useQueueItem.draw = true;
+
+                    setTimeout(()=>{
+                        this.useQueueItem.play = true;
+                    },1500);
+
+                },10);
+            }
+
+        },
+
+        // 获取用户位置信息
+        getInfoOffset(id){
+
+            if (id) {
+                let el = document.getElementById(id);
+                if (el) {
+                    return {
+                        x: this.getOffset(el,'offsetLeft'),
+                        y: this.getOffset(el,'offsetTop'),
+                        width: el.offsetWidth,
+                        height: el.offsetHeight
+                    }
+                }
+            }
+
+            return null;
+
+        },
+
+        getOffset(el,offset='offsetLeft'){
+
+            let offsetValue = el[offset] || 0;
+            let target = el;
+            while (target.offsetParent) {
+                offsetValue += target.offsetParent[offset];
+                target = target.offsetParent;
+            }
+            return offsetValue;
+        }
+
+    }
+
+}

+ 4 - 0
src/pages/talking/components/room-queue-gift/mixins/index.ts

@@ -0,0 +1,4 @@
+import queue from '$mixins/queue';
+import handle from './handle';
+
+export default [queue,handle];

+ 0 - 0
src/pages/talking/components/room-queue-gift/props.ts


+ 58 - 0
src/pages/talking/components/room-queue-gift/src/main.vue

@@ -0,0 +1,58 @@
+<template>
+  <div v-show="triggerStatus" class="room-admission-container absolute">
+
+    <template v-if="useQueueItem">
+      <template v-if="useQueueItem.type === '1'" :key="useQueueItem._id">
+        <div
+            v-for="(item,index) in useQueueItem.data"
+            :style="{
+            'width': item.width +'px',
+            'height': item.height+'px',
+            'top': item.y+'px',
+            'left': item.x+'px'
+          }"
+            :key="'admission-'+useQueueItem._id+'-'+index"
+            class="room-admission-fixed center"
+        >
+          <svg-animate
+              :style="{
+            'width': item.width +'px',
+            'height': item.height+'px'
+          }"
+              v-if="useQueueItem.draw"
+              :playStatus="useQueueItem.play"
+              size="45%"
+              :src="useQueueItem.item.play_image+'?id='+useQueueItem._id+'-'+index"
+              :defaultSrc="useQueueItem.item.base_image"
+              @stop="triggerQueueItem"
+              :loops="1"
+          ></svg-animate>
+        </div>
+      </template>
+      <template v-else >
+        <svg-animate
+            class="room-admission-svg"
+            :key="useQueueItem._id"
+            :src="useQueueItem.item.play_image+'?id='+useQueueItem._id"
+            :loops="1"
+            mode="AspectFit"
+            @stop="triggerQueueItem"
+        ></svg-animate>
+      </template>
+    </template>
+  </div>
+</template>
+
+<script>
+import {
+  svgAnimate
+} from '$components';
+import mixins from '../mixins';
+export default {
+  name: "room-queue-gift",
+  components: {svgAnimate},
+  mixins
+}
+</script>
+
+<style scoped lang="scss" src="../style.scss"></style>

+ 20 - 0
src/pages/talking/components/room-queue-gift/style.scss

@@ -0,0 +1,20 @@
+/* 进场模块 */
+.room-admission-container{
+  z-index: 99;
+  height: 535px;
+  left: 0;
+  right: 0;
+  top: 0;
+  pointer-events: none;
+}
+.room-admission-svg{
+  @include square(100%);
+}
+.room-admission-fixed{
+  position: fixed;
+  transition: 1.5s linear;
+  z-index: 9999;
+  pointer-events: none;
+  transform: scale(1.5);
+}
+/* 进场模块 */

+ 18 - 2
src/pages/talking/components/room-ranking/components/room-chat/components/const.ts

@@ -1,7 +1,23 @@
+import { AgoraRTMIMStatus,AgoraRTMessage,AgoraRTPcMessage } from '$utils/socket/agoraRTM/agoraRTMIM';
+
 enum RoomMessageType{
 enum RoomMessageType{
-    system='room-chat-system'
+    // 系统消息
+    system='room-chat-system',
+    // 普通消息
+    message='room-chat-message',
+    // 进场消息
+    entry='room-chat-entry'
+}
+
+let RoomChatType = {
+    // 礼物或者普通消息
+    [AgoraRTMessage.gift]: RoomMessageType.message,
+    [AgoraRTMessage.chat]: RoomMessageType.message,
+    [AgoraRTMessage.system]: RoomMessageType.system,
+    [AgoraRTMessage.joinHome]: RoomMessageType.entry
 }
 }
 
 
 export {
 export {
-    RoomMessageType
+    RoomMessageType,
+    RoomChatType
 }
 }

+ 7 - 1
src/pages/talking/components/room-ranking/components/room-chat/components/index.ts

@@ -1,9 +1,15 @@
 // 系统消息组件
 // 系统消息组件
 import roomChatSystem from './room-chat-system';
 import roomChatSystem from './room-chat-system';
+// 用户组件
+import roomChatMessage from './room-chat-message';
+// 进场介绍
+import roomChatEntry from './room-chat-entry';
 
 
 
 
 export default {
 export default {
-    roomChatSystem
+    roomChatSystem,
+    roomChatMessage,
+    roomChatEntry
 }
 }
 
 
 // 导出常量
 // 导出常量

+ 3 - 0
src/pages/talking/components/room-ranking/components/room-chat/components/room-chat-entry/index.ts

@@ -0,0 +1,3 @@
+import main from './src/main.vue';
+
+export default main;

+ 10 - 0
src/pages/talking/components/room-ranking/components/room-chat/components/room-chat-entry/props.ts

@@ -0,0 +1,10 @@
+export default {
+
+    item:{
+        type:Object,
+        default:function (){
+            return {}
+        }
+    }
+
+}

+ 17 - 0
src/pages/talking/components/room-ranking/components/room-chat/components/room-chat-entry/src/main.vue

@@ -0,0 +1,17 @@
+<template>
+  <div class="row wrap room-chat-entry">
+    <div class="room-chat-name">{{item.nickName}}</div>
+    <div class="room-chat-introduce">{{item.message}}</div>
+  </div>
+</template>
+
+<script>
+import props from '../props';
+export default {
+  name: "room-chat-entry",
+
+  props
+}
+</script>
+
+<style scoped lang="scss" src="../style.scss"></style>

+ 13 - 0
src/pages/talking/components/room-ranking/components/room-chat/components/room-chat-entry/style.scss

@@ -0,0 +1,13 @@
+.room-chat-entry{
+  margin-bottom: 15px;
+  font-size: 14px;
+  line-height: 18px;
+}
+
+.room-chat-name{
+  color: #FF9D62;
+}
+
+.room-chat-introduce{
+  margin-left: 7px;
+}

+ 3 - 0
src/pages/talking/components/room-ranking/components/room-chat/components/room-chat-message/index.ts

@@ -0,0 +1,3 @@
+import main from './src/main.vue';
+
+export default main;

+ 15 - 0
src/pages/talking/components/room-ranking/components/room-chat/components/room-chat-message/props.ts

@@ -0,0 +1,15 @@
+export default {
+
+    item:{
+        type:Object,
+        default:function (){
+            return {}
+        }
+    },
+
+    type:{
+        type:String,
+        default:'0'
+    }
+
+}

+ 44 - 0
src/pages/talking/components/room-ranking/components/room-chat/components/room-chat-message/src/main.vue

@@ -0,0 +1,44 @@
+<template>
+  <section>
+    <header class="row aCenter room-chat-header">
+      <v-image class="room-chat-avatar" :src="item.headimgurl" radius="50%" :borderWidth="2" borderColor="#fff"></v-image>
+      <div class="flex-1 room-chat-nickname">
+        <div class="line-1">{{item.nickName}}</div>
+      </div>
+    </header>
+    <div class="room-chat-message row aCenter wrap" v-if="type=== AgoraRTMessage.gift">
+      赠送给
+      <div class="chat-gift-user-group"><span v-for="(cItem,cIndex) in item.userInfo" :key="cItem.uid">{{cIndex!==0?',':''}}{{cItem.nickname}}</span></div>
+      {{item.e_name}}
+      <icon type="close" class="room-chat-number"></icon>
+      {{item.giftNum}}
+      <v-image :src="item.show_img" mode="center" background-color="transparent" class="room-chat-icon"></v-image>
+    </div>
+    <div class="room-chat-message" v-else>{{item.message}}</div>
+  </section>
+
+</template>
+
+<script>
+import vImage from '$components/v-image';
+import props from '../props';
+import {AgoraRTMessage} from '$utils/socket/agoraRTM/const/channel';
+import {
+  icon
+} from '$components';
+export default {
+  name: "room-chat-message",
+  data(){
+    return {
+      AgoraRTMessage
+    }
+  },
+  components:{
+    vImage,
+    icon
+  },
+  props
+}
+</script>
+
+<style scoped lang="scss" src="../style.scss"></style>

+ 32 - 0
src/pages/talking/components/room-ranking/components/room-chat/components/room-chat-message/style.scss

@@ -0,0 +1,32 @@
+.room-chat-header{
+  margin-bottom: 10px;
+}
+.room-chat-avatar{
+  @include square(42px);
+}
+.room-chat-nickname{
+  padding-left: 15px;
+  font-size: 16px;
+  line-height: 20px;
+  font-weight: 400;
+}
+.room-chat-message{
+  font-size: 14px;
+  line-height: 20px;
+  padding: 10px 20px;
+  background-color: rgba(255,255,255,0.05);
+  border-radius: 5px;
+  margin-bottom: 15px;
+}
+.chat-gift-user-group{
+  color: #FF9D62;
+  margin: 0 5px;
+}
+.room-chat-number{
+  font-size: 12px;
+  transform: scale(0.7);
+}
+.room-chat-icon{
+  @include square(22px);
+  margin-left: 4px;
+}

+ 10 - 0
src/pages/talking/components/room-ranking/components/room-chat/components/room-chat-system/props.ts

@@ -0,0 +1,10 @@
+export default {
+
+    item:{
+        type:Object,
+        default:function (){
+            return {}
+        }
+    }
+
+}

+ 13 - 2
src/pages/talking/components/room-ranking/components/room-chat/components/room-chat-system/src/main.vue

@@ -1,10 +1,21 @@
 <template>
 <template>
-
+  <div class="room-chat-system" v-html="message"></div>
 </template>
 </template>
 
 
 <script>
 <script>
+import props from '../props';
 export default {
 export default {
-  name: "room-chat-system"
+  name: "room-chat-system",
+
+  computed:{
+    message(){
+      let message = this.item.message || '';
+
+      return message.replace(/\n|\r/,'<br />');
+    }
+  },
+
+  props
 }
 }
 </script>
 </script>
 
 

+ 8 - 0
src/pages/talking/components/room-ranking/components/room-chat/components/room-chat-system/style.scss

@@ -0,0 +1,8 @@
+.room-chat-system{
+  font-size: 14px;
+  line-height: 20px;
+  padding: 10px 20px;
+  background-color: rgba(255,255,255,0.05);
+  border-radius: 5px;
+  margin-bottom: 15px;
+}

+ 2 - 1
src/pages/talking/components/room-ranking/components/room-chat/mixins/index.ts

@@ -1,4 +1,5 @@
 import shield from './shield';
 import shield from './shield';
 import message from './message';
 import message from './message';
+import scroll from './scroll';
 
 
-export default [shield,message];
+export default [shield,message,scroll];

+ 71 - 1
src/pages/talking/components/room-ranking/components/room-chat/mixins/message.ts

@@ -1,18 +1,88 @@
+import { AgoraRTMessage } from '$utils/socket/agoraRTM/agoraRTMIM';
+import {RoomChatType} from '../components/const';
+import verification,{VerificationType} from '$utils/verification/index';
 export default <LibMixins>{
 export default <LibMixins>{
 
 
+    inject:['getAgoraRTMIM','installSocketItem'],
+
     data(){
     data(){
       return {
       return {
           // 消息存储对象
           // 消息存储对象
-          messageData:[]
+          messageData:[],
+          // 最大存储
+          messageLength:100,
+          // 消息
+          message:''
       }
       }
     },
     },
 
 
     methods:{
     methods:{
 
 
+        // 发送消息
         sendMessage(){
         sendMessage(){
 
 
+            if (verification.trigger[VerificationType.empty](this.message)) {
+
+                let resultData = this.agoraRTMIM.addUserInfo({});
+                // 消息内容
+                resultData.message = this.message;
+                // 清空消息
+                this.message = '';
+                // 执行视图消息
+                this.triggerPushMessage(AgoraRTMessage.chat,resultData);
+                // 发送消息
+                this.agoraRTMIM.send(resultData,AgoraRTMessage.chat);
+            }
+
+        },
+
+        // 添加消息
+        pushMessage(type,item,messageType){
+
+            if (this.messageData.length > this.messageLength) {
+                this.messageData.unshift();
+            }
+
+            this.messageData.push({
+                type,
+                item,
+                messageType
+            });
+
+            // 设置滚动条位置
+            this.sendMessageScroll();
+
+        },
+
+        // 执行发送消息
+        triggerPushMessage(type,item){
+            if (RoomChatType[type]) {
+                return this.pushMessage(RoomChatType[type],item,type);
+            }
         }
         }
 
 
+
+    },
+
+    mounted() {
+        // 聊天对象
+        this.agoraRTMIM = this.getAgoraRTMIM();
+
+        // 消息监听器
+        this.messageCallback = function ({type,data}) {
+            this.triggerPushMessage(type,data);
+        }.bind(this);
+
+        // 监听message
+        this.agoraRTMIM.on(AgoraRTMessage.message,this.messageCallback);
+
+        // 安装消息对象
+        this.installSocketItem(this);
+    },
+
+    beforeUnmount() {
+        this.agoraRTMIM.off(AgoraRTMessage.message,this.messageCallback);
+        delete this.messageCallback;
     }
     }
 
 
 }
 }

+ 35 - 0
src/pages/talking/components/room-ranking/components/room-chat/mixins/scroll.ts

@@ -1,9 +1,44 @@
+import Throttle from '$utils/tool/throttle';
+import {nextTick} from 'vue';
 export default <LibMixins>{
 export default <LibMixins>{
 
 
     methods:{
     methods:{
 
 
+        sendMessageScroll:function () {
 
 
+            // 获取判断
+            if (this.$refs.scroll && this.rangEndDistance >= this.$refs.scroll.getScrollEndDistance()) {
+                this.scrollToEnd();
+            }
 
 
+        },
+
+        scrollToEnd(){
+            nextTick(()=>{
+                return this.$refs.scroll.scrollToEnd();
+            });
+        }
+
+    },
+    created() {
+
+        // 当在底部多少范围内,收到消息直接跳转到最底部
+        this.rangEndDistance = 300;
+
+        this.throttle = new Throttle({
+            type:'queueWait',
+            delay: 300,
+            mustDelay:300,
+            handle: this.scrollToEnd,
+            call: this
+        });
+
+        this.scrollToEnd = this.throttle.supper;
+
+    },
+
+    beforeUnmount(){
+        this.throttle && this.throttle.destroy();
     }
     }
 
 
 }
 }

+ 9 - 3
src/pages/talking/components/room-ranking/components/room-chat/src/main.vue

@@ -7,7 +7,13 @@
        class="room-chat-padding"
        class="room-chat-padding"
        ref="scroll"
        ref="scroll"
       >
       >
-        <div>和大家打个招呼吧</div>
+        <component
+          v-for="(item,index) in messageData"
+          :key="'room-chat-'+index"
+          :is="item.type"
+          :item="item.item"
+          :type="item.messageType"
+        ></component>
       </scroll-view>
       </scroll-view>
     </div>
     </div>
 
 
@@ -55,9 +61,9 @@
 
 
       <footer class="row">
       <footer class="row">
         <div class="flex-1 room-chat-input">
         <div class="flex-1 room-chat-input">
-          <input type="text" placeholder="和大家打个招呼吧~" />
+          <input v-model="message" @keydown.enter="sendMessage" type="text" placeholder="和大家打个招呼吧~" />
         </div>
         </div>
-        <div class="room-chat-send button">发送</div>
+        <div class="room-chat-send button" @click.stop="sendMessage">发送</div>
       </footer>
       </footer>
     </section>
     </section>
 
 

+ 1 - 1
src/pages/talking/components/room-ranking/components/room-chat/style.scss

@@ -66,7 +66,7 @@
 .room-chat-send{
 .room-chat-send{
   margin-left: 10px;
   margin-left: 10px;
   width: 70px;
   width: 70px;
-  height: 100%;
+  height: 32px;
   background: #FF6969;
   background: #FF6969;
   font-size: 14px;
   font-size: 14px;
   line-height: 18px;
   line-height: 18px;

+ 6 - 3
src/pages/talking/components/room-ranking/components/room-ranking-list/data/order.ts

@@ -3,19 +3,22 @@ export default [
         label:2,
         label:2,
         color:'#F4F4F4',
         color:'#F4F4F4',
         icon: require('@/assets/images/ranking-2.png'),
         icon: require('@/assets/images/ranking-2.png'),
-        trophyIcon: require('../images/trophy-2.png')
+        trophyIcon: require('../images/trophy-2.png'),
+        index:1
     },
     },
     {
     {
         label: 1,
         label: 1,
         size:'big',
         size:'big',
         color:'#FFD041',
         color:'#FFD041',
         icon: require('@/assets/images/ranking-1.png'),
         icon: require('@/assets/images/ranking-1.png'),
-        trophyIcon: require('../images/trophy-1.png')
+        trophyIcon: require('../images/trophy-1.png'),
+        index:0
     },
     },
     {
     {
         label: 3,
         label: 3,
         color: '#F49A61',
         color: '#F49A61',
         icon: require('@/assets/images/ranking-3.png'),
         icon: require('@/assets/images/ranking-3.png'),
-        trophyIcon: require('../images/trophy-3.png')
+        trophyIcon: require('../images/trophy-3.png'),
+        index:2
     }
     }
 ]
 ]

+ 5 - 5
src/pages/talking/components/room-ranking/components/room-ranking-list/src/main.vue

@@ -19,9 +19,9 @@
                  radius="50%"
                  radius="50%"
                  :border-width="2"
                  :border-width="2"
                  :border-color="item.color"
                  :border-color="item.color"
-                 :class="{'cursor-pointer': loadingStatus?false:userRank[index]}"
-                 @click.stop="openUserInfo($event,userRank[index])"
-                 :src="loadingStatus ? '' : userRank[index] && userRank[index].head_pic"
+                 :class="{'cursor-pointer': loadingStatus?false:userRank[item.index]}"
+                 @click.stop="openUserInfo($event,userRank[item.index])"
+                 :src="loadingStatus ? '' : userRank[item.index] && userRank[item.index].head_pic"
         >
         >
           <img :src="item.icon" class="absolute user-ranking-crown" />
           <img :src="item.icon" class="absolute user-ranking-crown" />
         </v-image>
         </v-image>
@@ -29,8 +29,8 @@
           <img :src="item.trophyIcon" class="screen" />
           <img :src="item.trophyIcon" class="screen" />
           <div class="absolute user-ranking-trophy-number center">{{item.label}}</div>
           <div class="absolute user-ranking-trophy-number center">{{item.label}}</div>
         </div>
         </div>
-        <div class="line-1 user-ranking-title">{{loadingStatus ?'':userRank[index] ? userRank[index].nick_name:'虚位以待'}}</div>
-        <div class="line-1 user-ranking-number">{{loadingStatus ?'':userRank[index] && userRank[index].contribution_value || 0}}</div>
+        <div class="line-1 user-ranking-title">{{loadingStatus ?'':userRank[item.index] ? userRank[item.index].nick_name:'虚位以待'}}</div>
+        <div class="line-1 user-ranking-number">{{loadingStatus ?'':userRank[item.index] && userRank[item.index].contribution_value || 0}}</div>
       </aside>
       </aside>
     </section>
     </section>
 
 

+ 3 - 3
src/pages/talking/components/room-wheat/data/micro-control.ts

@@ -14,9 +14,9 @@ export default  {
             label:'上麦',
             label:'上麦',
             trigger:'applyForWheat'
             trigger:'applyForWheat'
         },
         },
-        {
-            label: '抱人上麦'
-        },
+        // {
+        //     label: '抱人上麦'
+        // },
         {
         {
             label: '锁麦',
             label: '锁麦',
             trigger: 'lockForWheat'
             trigger: 'lockForWheat'

+ 18 - 7
src/pages/talking/components/room-wheat/src/main.vue

@@ -12,7 +12,12 @@
           <div class="room-wheat-label center">主持</div>
           <div class="room-wheat-label center">主持</div>
         </aside>
         </aside>
         <aside v-else class="rowACenter room-wheat-host-user">
         <aside v-else class="rowACenter room-wheat-host-user">
-          <v-image @click.stop="openUserInfo($event,hostUser.mc_user_info)" backgroundColor="transparent" :src="hostUser.mc_user_info.head_pic" class="room-wheat-first-avatar cursor-pointer" radius="50%"></v-image>
+          <layout-avatar :id="'user-'+hostUser.mc_user_info.uid" @click.stop="openUserInfo($event,hostUser.mc_user_info)" backgroundColor="transparent" :src="hostUser.mc_user_info.head_pic"
+                         class="room-wheat-first-avatar cursor-pointer"
+                         :dress-src="hostUser.mc_user_info.avatar_base_image"
+                         :dress-play-src="hostUser.mc_user_info.avatar_play_image"
+                         radius="50%"
+          ></layout-avatar>
           <div class="flex-1 room-wheat-first-content">
           <div class="flex-1 room-wheat-first-content">
             <div class="rowACenter">
             <div class="rowACenter">
               <div>{{hostUser.mc_user_info.nick_name}}</div>
               <div>{{hostUser.mc_user_info.nick_name}}</div>
@@ -31,13 +36,12 @@
       </header>
       </header>
     </aside>
     </aside>
 
 
-
     <section class="room-position row wrap">
     <section class="room-position row wrap">
 
 
       <aside
       <aside
         v-for="(item,index) in 8"
         v-for="(item,index) in 8"
         :key="'room-position-'+item"
         :key="'room-position-'+item"
-        class="room-position-item aCenter overflow"
+        class="room-position-item aCenter"
       >
       >
         <section v-if="!microUsers[index] || !microUsers[index].mc_user_info.uid || microUsers[index].mc_status===1" class="center">
         <section v-if="!microUsers[index] || !microUsers[index].mc_user_info.uid || microUsers[index].mc_status===1" class="center">
           <div class="room-position-sofa overflow center"
           <div class="room-position-sofa overflow center"
@@ -53,9 +57,14 @@
           <div class="room-position-title line-1">{{sofaConfig[item] && sofaConfig[item].title || item+' 号麦'}}</div>
           <div class="room-position-title line-1">{{sofaConfig[item] && sofaConfig[item].title || item+' 号麦'}}</div>
         </section>
         </section>
 
 
-        <section v-else class="center overflow room-position-user" >
-          <div class="room-position-sofa-avatar overflow center">
-            <v-image @click.stop="openUserInfo($event,microUsers[index].mc_user_info)" backgroundColor="transparent" class="screen cursor-pointer" radius="50%" :src="microUsers[index].mc_user_info.head_pic"></v-image>
+        <section v-else class="center room-position-user" >
+          <div class="room-position-sofa-avatar center" :id="'user-'+microUsers[index].mc_user_info.uid">
+            <layout-avatar
+                @click.stop="openUserInfo($event,microUsers[index].mc_user_info)"
+                :dress-src="microUsers[index].mc_user_info.avatar_base_image"
+                :dress-play-src="microUsers[index].mc_user_info.avatar_play_image"
+                backgroundColor="transparent" class="screen cursor-pointer"
+                radius="50%" :src="microUsers[index].mc_user_info.head_pic"></layout-avatar>
           </div>
           </div>
           <div class="room-position-title line-1">{{item}} {{microUsers[index].mc_user_info.nick_name}}</div>
           <div class="room-position-title line-1">{{item}} {{microUsers[index].mc_user_info.nick_name}}</div>
           <div class="room-wheat-love rowACenter">
           <div class="room-wheat-love rowACenter">
@@ -82,13 +91,15 @@ import microControl from '../data/micro-control';
 import mixins from '../mixins';
 import mixins from '../mixins';
 import props from '../props';
 import props from '../props';
 import popup from "$utils/tool/popup";
 import popup from "$utils/tool/popup";
+import layoutAvatar from '$layout/layout-avatar';
 import {
 import {
   WheatUseStatus
   WheatUseStatus
 } from '../../../const/wheat';
 } from '../../../const/wheat';
 export default {
 export default {
   name: "room-wheat",
   name: "room-wheat",
   components:{
   components:{
-    vImage
+    vImage,
+    layoutAvatar
   },
   },
   mixins,
   mixins,
   props,
   props,

+ 1 - 1
src/pages/talking/components/room-wheat/style.scss

@@ -95,6 +95,6 @@
   line-height: 22px;
   line-height: 22px;
   height: 22px;
   height: 22px;
   text-align: center;
   text-align: center;
-  margin-top: 6px;
+  margin-top: 12px;
 }
 }
 /* 麦位 */
 /* 麦位 */

+ 7 - 1
src/pages/talking/mixins/agora.ts

@@ -3,6 +3,8 @@ import Agora, {
     AgoraStatus
     AgoraStatus
 } from "$utils/agora/agora";
 } from "$utils/agora/agora";
 
 
+import AgoraRTMIM from '$utils/socket/agoraRTM/agoraRTMIM';
+
 import user from '$config/user';
 import user from '$config/user';
 
 
 export default <LibMixins>{
 export default <LibMixins>{
@@ -17,6 +19,8 @@ export default <LibMixins>{
 
 
         this.useAgora = new Agora(this.$params.rid.toString(),user.uid() || null);
         this.useAgora = new Agora(this.$params.rid.toString(),user.uid() || null);
 
 
+        this.agoraRTMIM = new AgoraRTMIM();
+
         // 监听设置状态
         // 监听设置状态
         this.useAgora.on(AgoraEvent.status,(item)=>{
         this.useAgora.on(AgoraEvent.status,(item)=>{
             this.agoraStatus = item;
             this.agoraStatus = item;
@@ -27,6 +31,8 @@ export default <LibMixins>{
     beforeUnmount(){
     beforeUnmount(){
         // 释放
         // 释放
         this.useAgora && this.useAgora.destroy();
         this.useAgora && this.useAgora.destroy();
+        // 释放聊天
+        this.agoraRTMIM && this.agoraRTMIM.destroy();
     }
     }
 
 
-}
+}

+ 33 - 0
src/pages/talking/mixins/gift.ts

@@ -0,0 +1,33 @@
+export default {
+
+    provide(){
+        return {
+            triggerChangeGiveUserId:(uid,userInfo:Record<string, any>={})=> this.triggerChangeGiveUserId(uid,userInfo),
+        }
+    },
+
+    data(){
+        return {
+            // 赠送用户
+            giveUserId:undefined,
+            // 赠送用户信息
+            giveUser:{}
+        }
+    },
+
+    methods:{
+
+        triggerChangeGiveUserId(uid,userInfo:Record<string, any>={}){
+            if (this.giveUserId !== uid) {
+                this.giveUserId = uid;
+                if (userInfo && userInfo.uid && this.giveUser.uid !== userInfo.uid) {
+                    this.giveUser = userInfo;
+                } else {
+                    this.giveUser = {};
+                }
+            }
+        }
+
+    }
+
+}

+ 81 - 43
src/pages/talking/mixins/handle.ts

@@ -1,6 +1,8 @@
 import {InstructionsCacheType, InstructionsMessageType} from "$utils/request";
 import {InstructionsCacheType, InstructionsMessageType} from "$utils/request";
 import user from "$config/user";
 import user from "$config/user";
 import {RowWheat} from "@/pages/talking/const";
 import {RowWheat} from "@/pages/talking/const";
+import {AgoraRTMIMStatus} from "$utils/socket/agoraRTM/const/status";
+
 
 
 export default <LibMixins>{
 export default <LibMixins>{
 
 
@@ -35,42 +37,69 @@ export default <LibMixins>{
       },
       },
       // 自己是否在麦上
       // 自己是否在麦上
       inWheat(){
       inWheat(){
-          console.log(this.wheat_status);
           return this.wheat_status === RowWheat.wheat;
           return this.wheat_status === RowWheat.wheat;
       }
       }
     },
     },
 
 
     methods:{
     methods:{
+
+        // 获取房间信息
+        getRoomInfo(){
+            Promise.all([this.fetchRoomInfo(false),this.getUserAdmission()]).then(([roomInfo,data])=>{
+                this.setUserAddAdmission(data);
+            });
+        },
+
         // 房间信息
         // 房间信息
-        fetchRoomInfo(){
-            if (this.$params.infoData) {
-                return this.setRoomInfo(JSON.parse(this.$params.infoData));
-            } else {
-                return this.$request({
-                    url:'room/enter_room_info',
-                    data:{
-                        rid: this.$params.rid,
-                        password: this.$params.password
-                    },
-                    token:true,
-                    cache:{
-                        type: InstructionsCacheType.storage
-                    },
-                    failMessage:true,
-                    message:InstructionsMessageType.other
-                }).then((data)=>{
-                    if (data.isSuccess) {
-                        this.setRoomInfo(data.data);
-                    } else {
-                        return this.$router.back();
-                    }
-
-                });
-            }
+        fetchRoomInfo(updated:boolean=true){
+
+            return  new Promise((resolve, reject)=>{
+                if (this.$params.infoData) {
+                    this.setRoomInfo(JSON.parse(this.$params.infoData),resolve,reject);
+                    return resolve(this.$params.infoData);
+                } else {
+                    return this.$request({
+                        url:'room/enter_room_info',
+                        data:{
+                            rid: this.$params.rid,
+                            password: this.$params.password
+                        },
+                        token:true,
+                        cache:{
+                            type: InstructionsCacheType.storage,
+                            updated
+                        },
+                        failMessage:true,
+                        message:InstructionsMessageType.other
+                    }).then((data)=>{
+
+                        if (data.isCache) {
+                            this.getRoomMicroInfo(true);
+                        }
+
+                        if (data.isSuccess) {
+                            this.setRoomInfo(data.data,resolve,reject);
+                        } else {
+                            return this.$router.back();
+                        }
+
+                    }).catch(reject);
+                }
+            });
+
         },
         },
 
 
-        setRoomInfo(data){
+        setRoomInfo(data,resolve,reject){
             this.roomInfo = data;
             this.roomInfo = data;
+
+            if (this.agoraRTMIM.status !== AgoraRTMIMStatus.join) {
+                // 安装 socket
+                this.agoraRTMIM.install(this.$params.rid.toString()).then(()=>{
+                    this.sendSystem(data.room_welcome);
+                    resolve();
+                }).catch(reject);
+            }
+
         },
         },
 
 
         // 获取用户排麦状态
         // 获取用户排麦状态
@@ -97,29 +126,35 @@ export default <LibMixins>{
 
 
         // 获取用户进入房间特权信息
         // 获取用户进入房间特权信息
         getUserAdmission(){
         getUserAdmission(){
-          return this.$request({
-              url:'room/get_room_user_vip',
-              data:{
-                  rid: this.$params.rid
-              },
-              cache:{
-                  type: InstructionsCacheType.storage
-              },
-              token:true
-          }).then((data)=>{
-              return this.addAdmission(data.data);
-          })
+            return this.$request({
+                url:'room/get_room_user_vip',
+                data:{
+                    rid: this.$params.rid
+                },
+                cache:{
+                    type: InstructionsCacheType.storage
+                },
+                token:true
+            });
+        },
+
+        // 设置用户进入房间特权
+        setUserAddAdmission(data){
+            this.user = data.data;
+            return this.addAdmission(data.data);
         },
         },
 
 
         // 获取麦位详情
         // 获取麦位详情
         getRoomMicroInfo(updated:boolean=true){
         getRoomMicroInfo(updated:boolean=true){
 
 
+            if (this.roomMicroStatus) return ;
             return this.$request({
             return this.$request({
                 url:'room/get_room_micro_info',
                 url:'room/get_room_micro_info',
                 data:{
                 data:{
                     rid: this.$params.rid
                     rid: this.$params.rid
                 },
                 },
                 token:true,
                 token:true,
+                next:({status})=> this.roomMicroStatus = status,
                 failMessage:true,
                 failMessage:true,
                 cache:{
                 cache:{
                     type: InstructionsCacheType.storage,
                     type: InstructionsCacheType.storage,
@@ -136,6 +171,9 @@ export default <LibMixins>{
                 // 设置当前排麦状态
                 // 设置当前排麦状态
                 if (this.hasMicroInfo()) {
                 if (this.hasMicroInfo()) {
                     this.downMicro();
                     this.downMicro();
+                } else {
+                    // 否则移除订阅
+                    this.unPublish();
                 }
                 }
 
 
             })
             })
@@ -144,13 +182,13 @@ export default <LibMixins>{
         // 安装
         // 安装
         install(){
         install(){
             // 请求房间信息
             // 请求房间信息
-            this.fetchRoomInfo();
+            this.getRoomInfo();
             // 请求麦位信息
             // 请求麦位信息
             this.getRoomMicroInfo(false);
             this.getRoomMicroInfo(false);
             // 获取用户排麦信息
             // 获取用户排麦信息
             this.getUserRowWheat(false);
             this.getUserRowWheat(false);
-            // 获取用户入场特效
-            this.getUserAdmission();
+            // // 获取用户入场特效
+            // this.getUserAdmission();
         },
         },
     },
     },
 
 
@@ -162,4 +200,4 @@ export default <LibMixins>{
     }
     }
 
 
 
 
-}
+}

+ 7 - 1
src/pages/talking/mixins/index.ts

@@ -1,3 +1,5 @@
+// 用户信息
+import user from '$mixins/user';
 // 获取页面参数
 // 获取页面参数
 import params from '$mixins/params';
 import params from '$mixins/params';
 // 页面数据加载
 // 页面数据加载
@@ -10,5 +12,9 @@ import agora from "./agora";
 import micro from './micro';
 import micro from './micro';
 // 基础功能
 // 基础功能
 import utils from './utils';
 import utils from './utils';
+// 聊天im
+import socket from "./socket";
+// 礼物
+import gift from './gift';
 
 
-export default [params,handle,wheat,agora,micro,utils];
+export default [user,params,handle,wheat,agora,micro,utils,socket,gift];

+ 92 - 10
src/pages/talking/mixins/micro.ts

@@ -5,6 +5,29 @@ import {cache} from "$utils/request/cache";
 
 
 export default <LibMixins>{
 export default <LibMixins>{
 
 
+    computed:{
+        microUserInfo(){
+            if (this.microInfo) {
+                let data = [this.microInfo.host_info,...(this.microInfo.mc_list || [])];
+                let resultData = [];
+                // 循环处理
+                data.map((item)=>{
+                    if (item && item.mc_user_info && item.mc_user_info.uid) {
+                        resultData.push({
+                            label: item.mc_user_info.nick_name,
+                            icon: item.mc_user_info.head_pic,
+                            uid: item.mc_user_info.uid
+                        });
+                    }
+                });
+                return resultData;
+            } else {
+                return [];
+            }
+
+        }
+    },
+
     methods:{
     methods:{
 
 
         // 初始化麦位信息之后触发
         // 初始化麦位信息之后触发
@@ -25,17 +48,76 @@ export default <LibMixins>{
             this.updateMicroCache();
             this.updateMicroCache();
         },
         },
 
 
-        // 更新麦位缓存
-        updateMicroCache(){
-            let cacheSign =cache.getSign('get_room_micro_info-'+this.$params.rid);
+        // 执行对比麦位信息,如果不一致进行update 更新麦位不同点
+        contrastWheatInfo(microInfo){
 
 
-            let cacheData = cache.getCache(cacheSign);
+            if (microInfo) {
+                let data = [microInfo.host_info,...microInfo.mc_list];
+
+                let checkData = [this.microInfo.host_info,...this.microInfo.mc_list];
+                let resultData = {};
+                checkData.map((item,index)=>{
+                    let contrastItem = data[index];
+                    if (item.mc_user_info && !contrastItem.mc_user_info || item.mc_user_info.uid !== contrastItem.mc_user_info.uid) {
+                        item.mc_user_info = contrastItem.mc_user_info;
+                    }
+
+                    if (item.mc_status !== contrastItem.mc_status) {
+                        item.mc_status = contrastItem.mc_status;
+                    }
+
+                    if (item && item.mc_user_info && item.mc_user_info.uid) {
+                        resultData[item.mc_user_info.uid] = item;
+                    }
+                });
+
+                this.micro_info = resultData;
 
 
-            // 更新缓存
-            if (cacheData && cacheData.data.data) {
-                cacheData.data.data.data = this.microInfo;
-                cache.updateCache(cacheSign,cacheData.data);
             }
             }
+
+        },
+
+        // 更新某个用户的魅力值
+        updateUserIntegral(uid,integral){
+            let microInfo = this.getMicroUserInfo(uid);
+            if (microInfo) {
+                microInfo.charm_value = parseFloat(microInfo.charm_value) + parseFloat(integral);
+                this.updateMicroCache(false);
+            }
+        },
+
+        // 获取某一个用户信息
+        getMicroUserInfo(uid){
+            let info = this.micro_info[uid];
+            if (info && info.mc_user_info && info.mc_user_info.uid) {
+                return  info.mc_user_info;
+            } else {
+                return  null;
+            }
+        },
+
+
+        // 更新麦位缓存
+        updateMicroCache(message:boolean=true){
+
+            clearTimeout(this.cacheMicroTime);
+            this.cacheMicroTime = setTimeout(()=>{
+                let cacheSign =cache.getSign('get_room_micro_info-'+this.$params.rid);
+
+                let cacheData = cache.getCache(cacheSign);
+
+                // 更新缓存
+                if (cacheData && cacheData.data.data) {
+                    cacheData.data.data.data = this.microInfo;
+                    cache.updateCache(cacheSign,cacheData.data);
+                }
+
+                // 执行公布麦位消息
+                message && this.sendWheatInfo();
+
+            },10);
+
+
         },
         },
 
 
         // 查看当前麦位是否空缺
         // 查看当前麦位是否空缺
@@ -149,7 +231,7 @@ export default <LibMixins>{
             if (uid) {
             if (uid) {
                 let item = this.micro_info[uid];
                 let item = this.micro_info[uid];
                 if (item) {
                 if (item) {
-                    item.mc_status = WheatUseStatus.normal;
+                    // item.mc_status = WheatUseStatus.normal;
                     item.mc_user_info = {};
                     item.mc_user_info = {};
                     // 更新麦位信息
                     // 更新麦位信息
                     this.installMicroInfo();
                     this.installMicroInfo();
@@ -170,4 +252,4 @@ export default <LibMixins>{
         this.micro_info = {};
         this.micro_info = {};
     }
     }
 
 
-}
+}

+ 140 - 0
src/pages/talking/mixins/socket.ts

@@ -0,0 +1,140 @@
+import { AgoraRTMessage } from '$utils/socket/agoraRTM/agoraRTMIM';
+export default {
+
+    provide(){
+        return {
+            installSocketItem:(vm)=>{
+                this.socketItem = vm;
+            },
+            sendGift:(data,send:boolean=false)=> this.sendGift(data,send)
+        }
+    },
+
+    methods:{
+
+        // 发送系统消息
+        sendSystem(message){
+            if (message && this.socketItem) {
+
+                this.socketItem.triggerPushMessage(AgoraRTMessage.system,{
+                    message
+                });
+            }
+        },
+
+        // 发送加入房间消息
+        sendJoinRoom(message){
+            if (message && this.socketItem) {
+                let resultData = this.agoraRTMIM.addUserInfo({
+                    message
+                },true);
+                this.socketItem.triggerPushMessage(AgoraRTMessage.joinHome,resultData);
+                this.agoraRTMIM.send(resultData,AgoraRTMessage.joinHome);
+            }
+        },
+
+        // 发送礼物消息
+        sendGift(data,send:boolean=false){
+
+            if (data) {
+
+                let userInfo = [];
+                data.giveUserId.map((item)=>{
+                    let info = this.getMicroUserInfo(item);
+
+                    if (!info && this.giveUser && this.giveUser.uid && this.giveUser.uid === item) {
+                        info = this.giveUser;
+                    }
+
+                    if (info) {
+                        userInfo.push({
+                            uid:item,
+                            nickname:info.nick_name,
+                            toNick_color:'#000000'
+                        });
+                    }
+
+                });
+
+                let resultData = this.agoraRTMIM.addGiftInfo(this.agoraRTMIM.addUserInfo({}), {
+                    userInfo:userInfo,
+                    number: data.number,
+                    gift: data.gift
+                });
+
+                if (send) {
+                    this.agoraRTMIM.send(resultData,AgoraRTMessage.gift);
+                } else {
+                    this.socketItem.triggerPushMessage(AgoraRTMessage.gift,resultData);
+                }
+            }
+
+        },
+
+        // 向大家公布麦位信息
+        sendWheatInfo(){
+            // 提醒大家麦位信息得到了更新
+            this.agoraRTMIM.send({
+                wheatData: this.microInfo
+            },AgoraRTMessage.wheat);
+        },
+
+        // 向大家公布申请排麦状态
+        sendWheatQueueInfo(user,status:boolean=true){
+            let resultData = this.agoraRTMIM.addQueueWheat({},user,status);
+
+            // 向其他人广播
+            this.agoraRTMIM.send(resultData,AgoraRTMessage.userRowWheat);
+
+            // 执行通知自己
+            this.agoraRTMIM.triggerMessage(resultData);
+
+        }
+
+    },
+    mounted(){
+        // 监听加入房间
+        this.agoraRTMIM.on(AgoraRTMessage.joinHome,({data})=> this.addAdmission(data,false));
+
+        // 监听收到礼物
+        this.agoraRTMIM.on(AgoraRTMessage.gift,({data})=> {
+
+            // 获取礼物信息
+            let gift = this.$store.state.gift && this.$store.state.gift.giftObjectData && this.$store.state.gift.giftObjectData[data.giftId];
+            if (!gift) {
+                gift = {
+                    gid: data.giftId,
+                    gift_name: data.e_name,
+                    gift_type: data.type,
+                    play_image: data.show_gift_img,
+                    pcplay_image: data.show_gift_pc_img,
+                    base_image: data.show_img,
+                    gift_price: data.gift_price || 0
+                }
+            }
+            // 获取赠送的用户id
+            let uid = (data.userInfo || []).map((item)=> item.uid);
+
+            this.sendGiveUserGift(gift,uid, gift.gift_price * data.giftNum || 0);
+        });
+
+        // 监听麦位信息
+        this.agoraRTMIM.on(AgoraRTMessage.wheat,({data})=>{
+
+            if (data.wheatData) {
+                this.contrastWheatInfo(data.wheatData);
+                // 设置当前排麦状态
+                if (this.hasMicroInfo()) {
+                    this.downMicro();
+                } else {
+                    // 否则移除订阅
+                    this.unPublish();
+                }
+            } else {
+                this.getRoomMicroInfo(true);
+            }
+
+        });
+    }
+
+}

+ 35 - 3
src/pages/talking/mixins/utils.ts

@@ -3,19 +3,51 @@ import {Shield, UserConfigType} from "$utils/control/user/const";
 
 
 export default <LibMixins>{
 export default <LibMixins>{
 
 
+    provide(){
+      return {
+          sendGiveUserGift:(item:Record<string, any>,uid:Array<string | number>,integral:number)=> this.sendGiveUserGift(item,uid,integral),
+      }
+    },
+
     methods:{
     methods:{
 
 
         // 入场
         // 入场
-        addAdmission(item){
+        addAdmission(item,isMy:boolean=true){
+
+            if (isMy) {
+                item = this.agoraRTMIM.addUserInfo({...item},true);
+                item.message = item.zq_title || '进入房间';
+                // 提示别人加入了房间
+                this.sendJoinRoom(item.message);
+            }
+
+            item.star_play_img = item.star_play_img || item.vip_tx;
 
 
             // 检查权限是否屏蔽了进场特效
             // 检查权限是否屏蔽了进场特效
-            if (!user.getDataItem(UserConfigType.shield,Shield.approach) && item.zq_play_image) {
+            if (!user.getDataItem(UserConfigType.shield,Shield.approach) && item.star_play_img) {
                 // 添加入场动画
                 // 添加入场动画
                 this.$refs.admission && this.$refs.admission.pushQueue(item);
                 this.$refs.admission && this.$refs.admission.pushQueue(item);
             }
             }
 
 
+        },
+
+        // 赠送礼物
+        sendGiveUserGift(item:Record<string, any>,uid:Array<string | number>,integral:number){
+
+            // 执行增加魅力值
+            if (integral) {
+                uid.map((item)=>{
+                    this.updateUserIntegral(item,integral);
+                });
+            }
+
+            // 检查权限是否屏蔽了进场特效
+            if (!user.getDataItem(UserConfigType.shield,Shield.gift) && item.play_image) {
+                // 添加入场动画
+                this.$refs.queueGift && this.$refs.queueGift.pushGift(item,uid);
+            }
         }
         }
 
 
     }
     }
 
 
-}
+}

+ 125 - 63
src/pages/talking/mixins/wheat.ts

@@ -4,7 +4,7 @@ import {PopupExportComponent} from "$popup/popup-export/const";
 import user from '$config/user';
 import user from '$config/user';
 
 
 import {RowWheat} from '../const';
 import {RowWheat} from '../const';
-import {InstructionsMessageType} from "$utils/request";
+import {InstructionsCacheType, InstructionsMessageType} from "$utils/request";
 import {WheatUseStatus} from "@/pages/talking/const/wheat";
 import {WheatUseStatus} from "@/pages/talking/const/wheat";
 
 
 export default <LibMixins>{
 export default <LibMixins>{
@@ -30,6 +30,8 @@ export default <LibMixins>{
             getRoomInfo: ()=> this.roomInfo,
             getRoomInfo: ()=> this.roomInfo,
             // 获取通话对象
             // 获取通话对象
             getUseAgora:()=> this.useAgora || {},
             getUseAgora:()=> this.useAgora || {},
+            // 获取聊天对象
+            getAgoraRTMIM:()=> this.agoraRTMIM || {},
             // 锁定麦位
             // 锁定麦位
             lockForWheat:(index)=>this.lockForWheat(index),
             lockForWheat:(index)=>this.lockForWheat(index),
             // 解锁麦位
             // 解锁麦位
@@ -44,11 +46,33 @@ export default <LibMixins>{
         // 打开用户信息
         // 打开用户信息
         openUserInfo(event,userInfo){
         openUserInfo(event,userInfo){
             if (userInfo && userInfo.uid) {
             if (userInfo && userInfo.uid) {
-                popup.$popup.open(PopupExportComponent.user,{
-                    el:event,
-                    value:true,
-                    item:userInfo
-                });
+                if (this.openUserStatus) return;
+                this.$request({
+                    url:'room/get_room_user_info',
+                    data:{
+                        rid: this.$params.rid,
+                        uid: userInfo.uid
+                    },
+                    token:true,
+                    cache:{
+                        type: InstructionsCacheType.memory
+                    },
+                    next:({status})=> this.openUserStatus = status,
+                    loading:'加载中'
+                }).then((data)=>{
+                    popup.$popup.open(PopupExportComponent.user,{
+                        el:event,
+                        value:true,
+                        item:data.data,
+                        giveGift:(user)=>{
+                            popup.$popup.open(PopupExportComponent.user);
+                            if (user.uid) {
+                                this.triggerChangeGiveUserId(user.uid,user);
+                            }
+                        }
+                    });
+                })
+
             }
             }
 
 
         },
         },
@@ -68,31 +92,38 @@ export default <LibMixins>{
                         successAsyncText:'操作成功',
                         successAsyncText:'操作成功',
                         confirm:()=>{
                         confirm:()=>{
                             return new Promise( (c_resolve, c_reject) =>{
                             return new Promise( (c_resolve, c_reject) =>{
-                                this.$request({
-                                    url:'room/room_owner_up_micro',
-                                    data:{
-                                        micro_id:index,
-                                        uid:user.uid,
-                                        rid: this.$params.rid
-                                    },
-                                    token:true,
-                                    failMessage:true,
-                                    next:({status})=> this.allowForWheatStatus = status,
-                                    message: InstructionsMessageType.other
-                                }).then((data)=>{
-                                    if (data.isSuccess) {
-                                        this.updateMicro(index,user);
-                                        resolve(data);
-                                        c_resolve(true);
-                                    } else {
+
+                                this.getUserWheatInfo(user.uid).then((wheatInfo)=>{
+
+                                    this.$request({
+                                        url:'room/room_owner_up_micro',
+                                        data:{
+                                            micro_id:index,
+                                            uid:user.uid,
+                                            rid: this.$params.rid
+                                        },
+                                        token:true,
+                                        failMessage:true,
+                                        next:({status})=> this.allowForWheatStatus = status,
+                                        message: InstructionsMessageType.other
+                                    }).then((data)=>{
+                                        if (data.isSuccess) {
+                                            this.updateMicro(index,wheatInfo);
+                                            this.sendWheatQueueInfo(wheatInfo,false);
+                                            resolve(data);
+                                            c_resolve(true);
+                                        } else {
+                                            reject();
+                                            return c_resolve(false);
+                                        }
+
+                                    }).catch(()=>{
+                                        c_reject();
                                         reject();
                                         reject();
-                                        return c_resolve(false);
-                                    }
+                                    });
+                                }).catch(c_reject);
+
 
 
-                                }).catch(()=>{
-                                    c_reject();
-                                    reject();
-                                });
                             })
                             })
                         },
                         },
                         cancel:function () {
                         cancel:function () {
@@ -126,34 +157,34 @@ export default <LibMixins>{
 
 
                             if (index != null) {
                             if (index != null) {
                                 return new Promise<boolean>( (resolve, reject)=> {
                                 return new Promise<boolean>( (resolve, reject)=> {
-                                    return this.$request({
-                                        url:host ? 'room/host_up_micro' : 'room/user_up_micro',
-                                        data:{
-                                            rid: this.$params.rid,
-                                            micro_id:typeof index === 'number'?index:''
-                                        },
-                                        token:true,
-                                        failMessage:true,
-                                        next:({status})=> this.applyForWheatStatus = status,
-                                        message: InstructionsMessageType.other
-                                    }).then((data)=>{
-                                        if (data.isSuccess) {
-                                            resolve(true);
-
-                                            if (host) {
-                                                this.updateHostMicro(user.user);
+                                    this.getUserWheatInfo(user.uid()).then((wheatInfo)=>{
+                                        return this.$request({
+                                            url:host ? 'room/host_up_micro' : 'room/user_up_micro',
+                                            data:{
+                                                rid: this.$params.rid,
+                                                micro_id:typeof index === 'number'?index:''
+                                            },
+                                            token:true,
+                                            failMessage:true,
+                                            next:({status})=> this.applyForWheatStatus = status,
+                                            message: InstructionsMessageType.other
+                                        }).then((data)=>{
+                                            if (data.isSuccess) {
+                                                resolve(true);
+                                                if (host) {
+                                                    this.updateHostMicro(wheatInfo);
+                                                } else {
+                                                    this.downMicro({
+                                                        index,
+                                                        user:wheatInfo
+                                                    });
+                                                }
                                             } else {
                                             } else {
-                                                this.downMicro({
-                                                    index,
-                                                    user:user.user
-                                                });
+                                                resolve(false);
                                             }
                                             }
-
-
-                                        } else {
-                                            resolve(false);
-                                        }
+                                        }).catch(reject);
                                     }).catch(reject);
                                     }).catch(reject);
+
                                 });
                                 });
                             } else {
                             } else {
                                 return  popup.$toast('暂无可用麦位');
                                 return  popup.$toast('暂无可用麦位');
@@ -181,6 +212,8 @@ export default <LibMixins>{
                                         if (data.isSuccess) {
                                         if (data.isSuccess) {
                                             // 设置状态为排麦中
                                             // 设置状态为排麦中
                                             this.setMicroStatus(RowWheat.queuing);
                                             this.setMicroStatus(RowWheat.queuing);
+                                            // 向其他人广播 目前个人处于排麦中
+                                            this.sendWheatQueueInfo(user.user,true);
                                             resolve(true);
                                             resolve(true);
                                         } else {
                                         } else {
                                             resolve(false);
                                             resolve(false);
@@ -197,6 +230,38 @@ export default <LibMixins>{
             }
             }
         },
         },
 
 
+        // 获取用户上麦信息
+        getUserWheatInfo(uid){
+            return new Promise((resolve, reject)=>{
+                return this.$request({
+                    url:'hxuser/get_base_user_info',
+                    data:{
+                        uid
+                    },
+                    token:true,
+                    failMessage:true,
+                    message: InstructionsMessageType.other
+                }).then((data)=>{
+                    if (data.isSuccess) {
+                        data = data.data;
+                        resolve({
+                            avatar_base_image: data.avatar_base_image,
+                            avatar_play_image: data.avatar_play_image,
+                            charm_value: data.charm_level_info.now_value,
+                            uid: data.uid,
+                            nick_name:data.nick_name,
+                            sex: data.sex,
+                            head_pic: data.head_pic
+                        });
+                    } else {
+                        reject();
+                    }
+
+                }).catch(reject);
+            });
+
+        },
+
         // 下麦
         // 下麦
         exitForWheat(){
         exitForWheat(){
             if (this.hasMicroInfo(user.uid())) {
             if (this.hasMicroInfo(user.uid())) {
@@ -216,14 +281,10 @@ export default <LibMixins>{
                                     next:({status})=> this.exitForWheatStatus = status,
                                     next:({status})=> this.exitForWheatStatus = status,
                                     message: InstructionsMessageType.other
                                     message: InstructionsMessageType.other
                                 }).then((data)=>{
                                 }).then((data)=>{
-                                    if (data.isSuccess) {
-                                        resolve(true);
-                                        this.upMicro({
-                                            uid:user.uid()
-                                        });
-                                    } else {
-                                        resolve(false);
-                                    }
+                                    this.upMicro({
+                                        uid:user.uid()
+                                    });
+                                    resolve(true);
                                 }).catch(reject);
                                 }).catch(reject);
                             })
                             })
                         }
                         }
@@ -252,6 +313,7 @@ export default <LibMixins>{
                             }).then((data)=>{
                             }).then((data)=>{
                                 if (data.isSuccess) {
                                 if (data.isSuccess) {
                                     this.setMicroStatus(RowWheat.none);
                                     this.setMicroStatus(RowWheat.none);
+                                    this.sendWheatQueueInfo(user.user,false);
                                     resolve(true);
                                     resolve(true);
                                 } else {
                                 } else {
                                     resolve(false);
                                     resolve(false);
@@ -341,4 +403,4 @@ export default <LibMixins>{
 
 
 
 
 
 
-}
+}

+ 12 - 4
src/pages/talking/src/main.vue

@@ -8,14 +8,19 @@
         <section class="row flex-1 talking-content-container">
         <section class="row flex-1 talking-content-container">
 
 
           <room-info :info="roomInfo" :admin="isAdmin" :status="wheat_status"></room-info>
           <room-info :info="roomInfo" :admin="isAdmin" :status="wheat_status"></room-info>
-          <section class="talking-center flex">
+          <section class="talking-center flex relative">
+            <!--  礼物特效  -->
+            <room-queue-gift ref="queueGift"></room-queue-gift>
             <room-wheat
             <room-wheat
               :info="roomInfo"
               :info="roomInfo"
               :microInfo="microInfo"
               :microInfo="microInfo"
               :admin="isAdmin"
               :admin="isAdmin"
             ></room-wheat>
             ></room-wheat>
             <div class="flex-1"></div>
             <div class="flex-1"></div>
-            <room-gift></room-gift>
+            <room-gift :user-data="microUserInfo"
+              :give-user-id="giveUserId"
+              :give-user="giveUser"
+            ></room-gift>
           </section>
           </section>
           <room-ranking></room-ranking>
           <room-ranking></room-ranking>
         </section>
         </section>
@@ -43,6 +48,8 @@ import roomRanking from '../components/room-ranking';
 
 
 import roomAdmission from '../components/room-admission';
 import roomAdmission from '../components/room-admission';
 
 
+import roomQueueGift from '../components/room-queue-gift';
+
 import mixins from '../mixins';
 import mixins from '../mixins';
 
 
 export default {
 export default {
@@ -59,10 +66,11 @@ export default {
     roomWheat,
     roomWheat,
     roomGift,
     roomGift,
     roomRanking,
     roomRanking,
-    roomAdmission
+    roomAdmission,
+    roomQueueGift
   },
   },
   mixins
   mixins
 }
 }
 </script>
 </script>
 
 
-<style scoped lang="scss" src="../style.scss"></style>
+<style scoped lang="scss" src="../style.scss"></style>

+ 44 - 0
src/popup/popup-chat/components/chat-content/components/chat-gift/mixins/handle.ts

@@ -0,0 +1,44 @@
+import popup, {PopupExportComponent} from "$utils/tool/popup";
+import giveGift from "$utils/control/giveGift";
+
+export default <LibMixins>{
+
+    data(){
+        return {
+            number:1,
+            giftSelect:0
+        }
+    },
+
+    methods:{
+
+        setNumber(item){
+            if (this.number !== item) {
+                this.number = item;
+            }
+        },
+
+        // 充值
+        recharge(){
+            return popup.$open(PopupExportComponent.recharge);
+        },
+
+        // 赠送礼物
+        changeGiftSelect(index){
+            if (this.giftSelect !== index) {
+                this.giftSelect = index;
+            }
+        },
+
+        // 点击赠送触发
+        giveGift(){
+            let gift = this.giftData[this.giftSelect];
+
+            if (gift) {
+                giveGift.giveGift(gift,this.number,this.userInfo);
+            }
+        }
+
+    }
+
+}

+ 3 - 0
src/popup/popup-chat/components/chat-content/components/chat-gift/mixins/index.ts

@@ -0,0 +1,3 @@
+import handle from './handle';
+
+export default [handle];

+ 10 - 0
src/popup/popup-chat/components/chat-content/components/chat-gift/props.ts

@@ -5,6 +5,16 @@ export default {
         default:function () {
         default:function () {
             return {};
             return {};
         }
         }
+    },
+
+    value:{
+        type:Boolean,
+        default:false
+    },
+
+    userInfo:{
+        type:[Number,String],
+        default:0
     }
     }
 
 
 }
 }

+ 56 - 8
src/popup/popup-chat/components/chat-content/components/chat-gift/src/main.vue

@@ -1,5 +1,5 @@
 <template>
 <template>
-  <section class="chat-gift flex absolute overflow">
+  <section class="chat-gift flex absolute overflow" @click.stop v-if="draw" v-show="vValue">
     <section class="flex-1 chat-gift-content">
     <section class="flex-1 chat-gift-content">
       <swiper :swiper-option="swiperOption" v-if="giftData && giftData.length > 0"
       <swiper :swiper-option="swiperOption" v-if="giftData && giftData.length > 0"
               class="chat-gift-swiper screen"
               class="chat-gift-swiper screen"
@@ -8,7 +8,12 @@
         <swiper-item
         <swiper-item
             v-for="(item,index) in giftData"
             v-for="(item,index) in giftData"
             :key="'gift-item-'+index"
             :key="'gift-item-'+index"
-            class="chat-gift-item"
+            class="chat-gift-item "
+            :class="{
+              'chat-gift-item-active':giftSelect === index,
+              'cursor-pointer': giftSelect !== index
+            }"
+            @click="changeGiftSelect(index)"
         >
         >
           <div class="center screen relative">
           <div class="center screen relative">
             <v-image :src="item.base_image" backgroundColor="transparent" radius="0.05rem" class="chat-gift-image"></v-image>
             <v-image :src="item.base_image" backgroundColor="transparent" radius="0.05rem" class="chat-gift-image"></v-image>
@@ -32,14 +37,19 @@
           <aside
           <aside
             v-for="(item,index) in numberData"
             v-for="(item,index) in numberData"
             :key="'chat-gift-number-'+index"
             :key="'chat-gift-number-'+index"
-            class="chat-gift-number-item center cursor-pointer"
+            class="chat-gift-number-item center"
+            :class="{
+              'chat-gift-number-active': item === number,
+              'cursor-pointer': item !== number
+            }"
+            @click="setNumber(item)"
           >{{item}}</aside>
           >{{item}}</aside>
         </article>
         </article>
         <div class="rowACenter">
         <div class="rowACenter">
           <img src="@/assets/images/currency.png" class="chat-my-gift-currency" />
           <img src="@/assets/images/currency.png" class="chat-my-gift-currency" />
           <div class="chat-my-gift-price">{{$store.getters.integral}}</div>
           <div class="chat-my-gift-price">{{$store.getters.integral}}</div>
           <div class="chat-my-gift-line"></div>
           <div class="chat-my-gift-line"></div>
-          <div class="chat-my-gift-recharge rowACenter cursor-pointer">
+          <div @click="recharge" class="chat-my-gift-recharge rowACenter cursor-pointer">
             <span>充值</span>
             <span>充值</span>
             <icon type="more" class="chat-gift-recharge-icon"></icon>
             <icon type="more" class="chat-gift-recharge-icon"></icon>
           </div>
           </div>
@@ -47,9 +57,9 @@
       </section>
       </section>
       <div class="chat-gift-exchange rowACenter">
       <div class="chat-gift-exchange rowACenter">
         <div class="chat-gift-stepper">
         <div class="chat-gift-stepper">
-          <stepper class="chat-gift-stepper-target" type="pure"></stepper>
+          <stepper v-model:value="number" :max="9999" class="chat-gift-stepper-target" type="pure"></stepper>
         </div>
         </div>
-        <div class="flex-1 center cursor-pointer chat-gift-reward">打赏</div>
+        <div @click="giveGift" class="flex-1 center cursor-pointer chat-gift-reward">打赏</div>
       </div>
       </div>
     </footer>
     </footer>
   </section>
   </section>
@@ -66,6 +76,8 @@ import {
 import unit from "$utils/unit/unit";
 import unit from "$utils/unit/unit";
 import {mapState} from "vuex";
 import {mapState} from "vuex";
 import numberData from '../data/number';
 import numberData from '../data/number';
+import mixins from '../mixins';
+import props from '../props';
 export default {
 export default {
   name: "chat-gift",
   name: "chat-gift",
   data(){
   data(){
@@ -77,9 +89,38 @@ export default {
         slidesPerColumn:2,
         slidesPerColumn:2,
         slidesPerColumnFill:'row'
         slidesPerColumnFill:'row'
       },
       },
-      numberData
+      draw:false,
+      numberData,
+      vValue:false
     }
     }
   },
   },
+
+  watch:{
+    value:{
+      handler(){
+
+        return this.changeValue(this.value);
+      },
+      immediate:true
+    }
+  },
+
+  methods:{
+    changeValue(value){
+      if (value !== this.vValue) {
+        this.vValue = value;
+
+        if (value && !this.draw) {
+          this.draw = true;
+        }
+
+        if (this.value !== value) {
+          return this.$emit('input',value);
+        }
+      }
+    }
+  },
+
   components:{
   components:{
     swiper,
     swiper,
     swiperItem,
     swiperItem,
@@ -89,8 +130,15 @@ export default {
   },
   },
   computed:mapState({
   computed:mapState({
     // @ts-ignore
     // @ts-ignore
-    giftData:(state)=> state.gift.giftData
+    giftData:(state)=> state.gift.giftUserData
   }),
   }),
+
+  created() {
+    this.$store.dispatch('initializationUserGiftPromise');
+  },
+
+  props,
+  mixins
 }
 }
 </script>
 </script>
 
 

+ 8 - 0
src/popup/popup-chat/components/chat-content/components/chat-gift/style.scss

@@ -19,6 +19,10 @@
   height: 120px;
   height: 120px;
   background-color: rgba(255,255,255,0.1);
   background-color: rgba(255,255,255,0.1);
   border-radius: 10px;
   border-radius: 10px;
+  border:1px solid rgba(255,255,255,0.1);
+}
+.chat-gift-item-active {
+  border-color: #FF56C5;
 }
 }
 .chat-gift-swiper{
 .chat-gift-swiper{
   padding-bottom: 25px;
   padding-bottom: 25px;
@@ -70,6 +74,10 @@
   border-radius: 10.5px;
   border-radius: 10.5px;
   margin-right: 6px;
   margin-right: 6px;
 }
 }
+.chat-gift-number-active{
+  background-color:#FF56C5;
+  border-color: #ff56C5;
+}
 .chat-my-gift-currency{
 .chat-my-gift-currency{
   @include square(12px);
   @include square(12px);
 }
 }

+ 22 - 6
src/popup/popup-chat/components/chat-content/data/control.ts

@@ -1,11 +1,27 @@
+import {FunctionTrigger} from "$mixins/trigger/class";
+import popup, {PopupExportComponent} from "$utils/tool/popup";
+
 export default [
 export default [
     {
     {
-        icon:require('../images/follow.png')
+        icon:require('../images/follow.png'),
+        activeIcon:require('../images/follow-active.png'),
+        key:'follow',
+        trigger: new FunctionTrigger(function (){
+            this.toggleFollow();
+        })
     },
     },
     {
     {
-        icon:require('../images/report.png')
+        icon:require('../images/report.png'),
+        trigger: new FunctionTrigger(function (){
+            if (this.userInfo.uid) {
+                popup.$open(PopupExportComponent.report,{
+                    uid: this.userInfo.uid
+                });
+            }
+
+        })
     },
     },
-    {
-        icon:require('../images/blacklist.png')
-    }
-]
+    // {
+    //     icon:require('../images/blacklist.png')
+    // }
+]

+ 8 - 1
src/popup/popup-chat/components/chat-content/data/message-control.ts

@@ -1,8 +1,15 @@
+import {FunctionTrigger} from "$mixins/trigger/class";
+
 export default [
 export default [
     {
     {
         icon:require('../images/expression.png')
         icon:require('../images/expression.png')
     },
     },
     {
     {
-        icon:require('../images/gift.png')
+        icon:require('../images/gift.png'),
+        trigger: new FunctionTrigger(function () {
+
+            return this.toggleGift();
+
+        })
     }
     }
 ]
 ]

+ 22 - 3
src/popup/popup-chat/components/chat-content/data/userContral.ts

@@ -1,14 +1,33 @@
+import { FunctionTrigger } from '$mixins/trigger/class/index';
+
+import personalDetail from '$utils/control/personal-detail/index';
+
 export default [
 export default [
     {
     {
         label:'下单',
         label:'下单',
-        icon:require('../images/order.png')
+        icon:require('../images/order.png'),
+        where:'is_player',
+        trigger:new FunctionTrigger(function (){
+            return  this.placeOrder();
+        })
     },
     },
     {
     {
         label: '资料',
         label: '资料',
-        icon:require('../images/user-data.png')
+        icon:require('../images/user-data.png'),
+        where:'is_player',
+        trigger:new FunctionTrigger(function (){
+            if (this.userInfo && this.userInfo.uid && this.userInfo.pid) {
+                personalDetail.openDetail(this.userInfo);
+            }
+        })
     },
     },
     {
     {
         label: '关注',
         label: '关注',
-        icon:require('../images/user-follow.png')
+        icon:require('../images/user-follow.png'),
+        activeIcon: require('../images/user-follow-active.png'),
+        key:'follow',
+        trigger: new FunctionTrigger(function (){
+            this.toggleFollow();
+        })
     }
     }
 ]
 ]

二進制
src/popup/popup-chat/components/chat-content/images/follow-active.png


二進制
src/popup/popup-chat/components/chat-content/images/user-follow-active.png


+ 81 - 0
src/popup/popup-chat/components/chat-content/mixins/follow.ts

@@ -0,0 +1,81 @@
+import Throttle from '$utils/tool/throttle';
+import personalDetail from "$utils/control/personal-detail";
+import socket from "$utils/socket";
+import {NoticeType} from "$utils/socket/const";
+export default {
+
+    data(){
+      return {
+          control:{
+              follow:false
+          }
+      }
+    },
+
+    methods:{
+
+        setFollow(user){
+            this.control.follow = !!user.is_follow;
+            this._followStatus = this.control.follow;
+        },
+
+        toggleFollow(){
+            this.control.follow = !this.control.follow;
+            personalDetail.updateCache({
+                uid: this.uid,
+                status: this.control.follow ? 1 : 0
+            });
+
+            socket.triggerNotice(NoticeType.follow, {
+                uid: this.uid,
+                status: this.control.follow ? 1 : 0,
+                followUserInfo:this.userInfo
+            });
+
+            // 设置是否关注
+            return this.triggerFollow();
+        },
+
+        triggerFollow(){
+            if(this.control.follow !== this._followStatus) {
+                this._followStatus = this.control.follow;
+                return this.$request({
+                    url:this._followStatus ? 'user/follow_user' : '/user/unfollow_user',
+                    data:{
+                        follow_uid: this.uid
+                    },
+                    token:true
+                });
+            }
+        }
+
+    },
+
+    created() {
+        this.Throttle = new Throttle({
+            delay:1000,
+            first:false,
+            call:this,
+            handle: this.triggerFollow
+        });
+
+        socket.on('popup-chat-content',(params)=>{
+
+            if (params.uid) {
+                let status = !!params.status;
+                if (this.control.follow !== status) {
+                    this.control.follow = status;
+                }
+            }
+
+        },NoticeType.follow);
+
+        this.triggerFollow = this.Throttle.supper;
+    },
+
+    beforeUnmount() {
+        this.Throttle && this.Throttle.destroy();
+        socket.off('popup-chat-content');
+    }
+
+}

+ 29 - 0
src/popup/popup-chat/components/chat-content/mixins/gift.ts

@@ -0,0 +1,29 @@
+import globalEvent from "$utils/tool/globalEvent";
+
+export default {
+
+    data(){
+        return {
+            giftModal:false
+        }
+    },
+
+    methods:{
+        toggleGift(){
+
+            // if (this.giftModal) {
+            //      globalEvent.off('chat-content');
+            // } else {
+            //     console.log('点击1');
+            //     globalEvent.on('chat-content',()=>{
+            //         console.log('点击');
+            //         this.giftModal = false;
+            //     });
+            // }
+
+            this.giftModal = !this.giftModal;
+
+        }
+    }
+
+}

+ 198 - 2
src/popup/popup-chat/components/chat-content/mixins/handle.ts

@@ -1,14 +1,210 @@
 import controlData from '../data/control';
 import controlData from '../data/control';
 import userControlData from '../data/userContral';
 import userControlData from '../data/userContral';
 import messageControlData from '../data/message-control';
 import messageControlData from '../data/message-control';
+import {FlatListReload} from "$components/flat-list/const";
+import verification, {VerificationType} from '$utils/verification/index';
+import socket from "$utils/socket/index";
+import MessageType from "$utils/socket/const/messageType";
+import user from '$config/user';
+import {NoticeType} from "$utils/socket/const";
+import giveGift from "$utils/control/giveGift";
 export default <LibMixins>{
 export default <LibMixins>{
 
 
     data(){
     data(){
         return {
         return {
             controlData,
             controlData,
             userControlData,
             userControlData,
-            messageControlData
+            messageControlData,
+            userInfo:{},
+            message:'',
+            messageData:[],
+            loadingStatus:true,
+            opacity:1
         }
         }
+    },
+
+    watch:{
+      uid:{
+          handler(){
+            if (this.uid && this._uid !== this.uid) {
+
+                socket.off('chat-content',NoticeType.message,{
+                    userId: (this._uid || '').toString()
+                });
+
+                this._uid = this.uid;
+
+                this.userInfo = {};
+
+                this.opacity = 0;
+
+                socket.on('chat-content',(item)=> this.watchMessage(item),NoticeType.message,{
+                    userId: this.uid.toString()
+                });
+
+                return  this.fetch();
+            }
+          },
+          immediate:true
+      }
+
+    },
+
+    computed:{
+        nowUserInfo(){
+            if (this.userInfo.uid) {
+                return this.userInfo;
+            } else {
+                return this.useUserInfo || {};
+            }
+        },
+        allUserInfo(){
+          let users = [this.user,this.userInfo];
+          let usersObject = {};
+          users.map((item)=>{
+              usersObject[item.uid] = item;
+          });
+
+          return usersObject;
+      },
+      nowUid(){
+         return this.user.uid;
+      }
+    },
+
+    methods:{
+
+        watchMessage(item){
+            // 清楚未读消息
+            this.socketUser && this.socketUser.read();
+            this.messageData.push(this.getMessageItem(item));
+            return this.sendMessageScroll();
+        },
+
+        fetch() {
+
+            this.giftModal = false;
+
+            this.loadingStatus = true;
+
+            this.socketUser = socket.getConversation(this.uid);
+
+            let requestUnique = +new Date() + '-'+Math.ceil(Math.random() * 10000);
+
+            this.requestUnique = requestUnique;
+
+            this.messageData = [];
+
+            // 加载历史记录
+            this.statusFetch(true,{
+                unique:requestUnique
+            });
+
+            return this.getUserInfo(requestUnique);
+
+        },
+
+        // 获取历史消息
+        getMessages(obj){
+
+            this.socketUser.getMessages({
+                timestamp: this.lastTime,
+                count:obj.data.pageSize
+            }).then((data)=>{
+                if (obj.data.unique === this.requestUnique) {
+                    data.list = data.list || [];
+
+                    // 最后的时间
+                    this.lastTime = data.list[data.list.length - 1] &&  data.list[data.list.length - 1].receivedTime;
+
+                    data.list = data.list.map((item)=>{
+                        return this.getMessageItem(item);
+                    });
+
+                    this.messageData.unshift(...data.list);
+
+                    this.scrollToEnd();
+                }
+
+
+            }).catch(()=>{
+                obj.fail();
+                this.opacity = 1;
+            });
+        },
+
+        // 设置消息
+        getMessageItem(item){
+
+            let uid = item.senderUserId == user.uid() ? user.uid() : this.nowUserInfo.uid;
+            let toUserId = item.senderUserId == user.uid() ? this.nowUserInfo.uid : user.uid();
+
+            return {
+                ...item.content,
+                type:item.messageType,
+                toUserId: toUserId.toString(),
+                uid: uid.toString(),
+            }
+        },
+
+        sendGift(gift,number,userInfo){
+
+            if (gift && number && userInfo && userInfo.uid === this.nowUserInfo.uid) {
+                this.messageData.push({
+                    gift,
+                    number,
+                    type:MessageType.gift,
+                    uid:user.uid(),
+                    toUserId: userInfo.uid
+                });
+                this.sendMessageScroll();
+            }
+
+        },
+
+        sendMessage(){
+
+            if (this.message && verification.trigger[VerificationType.empty](this.message)) {
+
+                this.messageData.push({
+                    message:this.message,
+                    type:MessageType.text,
+                    uid:user.uid(),
+                    toUserId: this.nowUserInfo.uid
+                });
+
+                this.sendMessageScroll();
+                this.sendText(this.message);
+
+                this.message = '';
+
+
+            }
+
+        },
+
+        sendText(message){
+            if (this.socketUser) {
+                this.socketUser.send({
+                    messageType: MessageType.text, // 'RC:TxtMsg'
+                    content:socket.addUser({
+                        message:message,
+                    },this.nowUserInfo)
+                });
+            }
+        }
+    },
+
+    created(){
+        this.lastTime = +new Date();
+        giveGift.content = this;
+    },
+
+    beforeUnmount() {
+        socket.off('chat-content',NoticeType.message,{
+            userId: (this._uid || '').toString()
+        });
+        giveGift.content = undefined;
     }
     }
+}
 
 
-}

+ 8 - 1
src/popup/popup-chat/components/chat-content/mixins/index.ts

@@ -1,3 +1,10 @@
 import handle from './handle';
 import handle from './handle';
+import imStatus from '$mixins/status/im';
+import user from '$mixins/user';
+import scroll from './scroll';
+import userInfo from './userInfo';
+import trigger from '$mixins/trigger';
+import gift from './gift';
+import follow from './follow';
 
 
-export default [handle];
+export default [handle,gift,imStatus,user,scroll,userInfo,trigger,follow];

部分文件因文件數量過多而無法顯示