jwyu 2 years ago
parent
commit
386cf461b7
49 changed files with 2887 additions and 360 deletions
  1. 10 0
      api/common.js
  2. 8 4
      api/question.js
  3. 19 0
      api/report.js
  4. 30 0
      api/user.js
  5. 12 0
      api/video.js
  6. 16 1
      components/audioBox/audioBox.vue
  7. 72 0
      components/collectBox/collectBox.vue
  8. 9 3
      components/sharePoster/sharePoster.vue
  9. 521 0
      components/videoBox/videoBox.vue
  10. 364 0
      components/videoComment/comment.vue
  11. 6 6
      custom-tab-bar/index.wxml
  12. 4 2
      mixin/index.js
  13. 1 0
      mixin/questionMixin.js
  14. 11 3
      pages-report/classify.vue
  15. 366 0
      pages-report/reportForVariety/list.vue
  16. 51 52
      pages-report/reportList.vue
  17. BIN
      pages-report/static/a-pause.png
  18. BIN
      pages-report/static/a-play.png
  19. 79 45
      pages-roadShow/video/list.vue
  20. 81 46
      pages-roadShow/video/search.vue
  21. 3 11
      pages-sandTable/sandTable.vue
  22. 315 0
      pages-user/myCollect.vue
  23. 1 0
      pages-voice/myVoice.vue
  24. 19 1
      pages-voice/voiceDetail.vue
  25. 34 12
      pages.json
  26. 1 1
      pages/login.vue
  27. 15 2
      pages/pc.vue
  28. 4 3
      pages/question/question.vue
  29. 2 2
      pages/report/report.vue
  30. 99 0
      pages/roadShow/video/components/noAuth.vue
  31. 495 0
      pages/roadShow/video/list.vue
  32. 13 6
      pages/user/user.vue
  33. 76 45
      pages/video/videoList.vue
  34. 78 45
      pages/video/videoSearch.vue
  35. 59 64
      pages/voice/voice.vue
  36. BIN
      static/collect-s.png
  37. BIN
      static/collect-user-icon.png
  38. BIN
      static/collect.png
  39. BIN
      static/danmu-close-btn-2.png
  40. BIN
      static/danmu-close-btn.png
  41. BIN
      static/danmu-show-btn-2.png
  42. BIN
      static/danmu-show-btn.png
  43. BIN
      static/headphones-icon.png
  44. BIN
      static/tabbar/roadShow-s.png
  45. BIN
      static/tabbar/roadShow.png
  46. BIN
      static/voice/creat-poster-icon.png
  47. 7 0
      store/modules/audio.js
  48. 5 5
      utils/config.js
  49. 1 1
      utils/request.js

+ 10 - 0
api/common.js

@@ -67,4 +67,14 @@ export const apiGetTagTree = params=>{
  */
 export const apiUserBindPermission=()=>{
     return httpGet('/company/permission/bind',{})
+}
+
+/**
+ * 更新媒体播放记录时长
+ * @param id 日志ID
+ * @param stop_seconds 访问时长
+ * @param source 来源:1-问答社区; 2-语音播报; 3-视频社区; 4-路演视频
+ */
+export const apiViewLogUpdate=params=>{
+    return httpPost('/public/view_log/update',params)
 }

+ 8 - 4
api/question.js

@@ -77,10 +77,11 @@ export const apiCountAudioClick = params=>{
 
 /**
  * 点赞/吐槽
- *  "community_question_id": 35,
+ *  "community_question_id": 35, 问答ID/视频ID
     "op_type": 1, 1-点赞 2-吐槽
     "enable": 1, 0取消 1-有效数据
     "source_agent": 1, 1:小程序,2:小程序 pc 3:弘则研究公众号,4:web pc
+    source:来源:1-问答社区(默认, 传0也是); 2-视频社区
  */
 export const apiSetLike = params => {
    return httpPost('/community/set_like_or_tease',{ source_agent:1,...params })
@@ -89,10 +90,11 @@ export const apiSetLike = params => {
 /**
  * 发布评论
  * @param {*} params 
- * "community_question_id": 35,
+ * "community_question_id": 35, 问答ID/视频ID
     "content": "这里是roc的测试评论",
     "is_show_name": 0,
     "source_agent": 1,
+      source 来源:1-问答社区(默认, 传0也是); 2-视频社区
  */
 export const apiPublishComment = params => {
    return httpPost('/community/comment',{ source_agent:1,...params })
@@ -125,9 +127,10 @@ export const apiDelComment = params => {
 /**
  * 精选留言列表
  * @param {*} params
- * community_question_id 
+ * community_question_id 问答ID/视频ID
  * curr_page
  * page_size
+ * source 来源:1-问答社区(默认, 传0也是); 2-视频社区
  */
 export const apiHotComment = params => {
    return httpGet('/community/comment/hot',params)
@@ -136,9 +139,10 @@ export const apiHotComment = params => {
 /**
  * 我的留言列表
  * @param {*} params
- * community_question_id 
+ * community_question_id 问答ID/视频ID
  * curr_page
  * page_size
+ * source 来源:1-问答社区(默认, 传0也是); 2-视频社区
  */
 export const apiMyComment = params => {
    return httpGet('/community/comment/my',params)

+ 19 - 0
api/report.js

@@ -107,4 +107,23 @@ export const apiChapterTickerValue=params=>{
  */
 export const apiReportPPtImgs=params=>{
     return httpGet('/report/ppt_img',params)
+}
+
+/**
+ * 品种类型报告中品种筛选项
+ * @param classify_id 分类id
+ */
+export const apiGoodsPermissionList=params=>{
+    return httpGet('/company/permission/commodities',params)
+}
+
+/**
+ * 按品种查询报告列表
+ * @param chart_permission_id 品种id
+ * @param classify_id 分类id
+ * @param current_index
+ * @param page_size
+ */
+export const apiReportListForVariety=params=>{
+    return httpGet('/report/variety/list',params)
 }

+ 30 - 0
api/user.js

@@ -69,4 +69,34 @@ export const apiLastApplyRecord=(params)=>{
  */
 export const apiSetMyinfo = params => {
 	return httpPost('/user/set',params)
+}
+
+/**
+ * 收藏
+ * @param collection_type 收藏类型:1-研报; 2-视频社区; 3-微路演视频
+ * @param primary_id //收藏类型主ID(如报告id,视频id)
+ * @param extend_id //扩展ID-如研报章节ID
+ * @param source_agent //操作来源:1-小程序 2-小程序 PC 3-弘则研究公众号 4-Web PC
+ */
+export const apiSetCollect=params=>{
+	return httpPost('/collection/collect',{source_agent:1,...params})
+}
+
+/**
+ * 取消收藏
+ * @param collection_id 收藏ID
+ */
+export const apiCancelCollect=params=>{
+	return httpPost('/collection/cancel',params)
+}
+
+/**
+ * 我的收藏列表
+ * @param curr_page
+ * @param page_size
+ * @param keywords
+ * @param from_type 来源类型:0-全部; 1-研报; 2-线上路演; 3-视频社区
+ */
+export const apiMyCollectList=params=>{
+	return httpGet('/collection/list',params)
 }

+ 12 - 0
api/video.js

@@ -21,4 +21,16 @@ export const apiVideoList=params=>{
  */
 export const apiVideoPlayLog=params=>{
     return httpPost('/community/video/play_log',{...params,source_agent:1})
+}
+
+/**
+ * 视频弹幕
+ * @param content
+ * @param seconds
+ * @param primary_id 视频id
+ * @param source 来源:1-视频社区 2-路演视频
+ * @param source_agent 来源平台:1:小程序、2:小程序(pc)、3:公众号、4:官网web(pc)
+ */
+export const apiVideoDanmuSend=params=>{
+    return httpPost('/bullet_chat/add',{source_agent:1,...params})
 }

+ 16 - 1
components/audioBox/audioBox.vue

@@ -54,6 +54,7 @@
 </template>
 
 <script>
+import {apiViewLogUpdate} from '@/api/common'
 export default {
     filters:{
         formatVoiceTime(e){
@@ -120,6 +121,7 @@ export default {
             const curAudio=this.$store.state.audio.list[this.$store.state.audio.index]
             setTimeout(() => {
                 if(this.globalBgMusic.src!=curAudio.url){
+                    this.handleUpdateAudioPlayTime()
                     this.globalBgMusic.src=curAudio.url 
                     this.globalBgMusic.title=curAudio.title
                 }
@@ -141,16 +143,18 @@ export default {
             })
             this.globalBgMusic.onPause(()=>{
                 console.log('音频暂停');
+                this.handleUpdateAudioPlayTime()
                 this.play=false
                 this.$store.commit('audio/updateAudioPause',true)
             })
             this.globalBgMusic.onStop(()=>{
                 console.log('音频停止');
+                this.handleUpdateAudioPlayTime()
                 this.$store.commit('audio/removeAudio')
             })
             this.globalBgMusic.onEnded(()=>{
                 console.log('音频onEnded');
-
+                this.handleUpdateAudioPlayTime()
                 const index=this.$store.state.audio.index 
                 if(index==this.$store.state.audio.list.length-1){
                     this.$store.commit('audio/removeAudio')
@@ -212,6 +216,17 @@ export default {
             }
         },
 
+        // 记录音频播放 时长
+        handleUpdateAudioPlayTime(){
+            if(!this.$store.state.audio.recordId||this.$store.state.audio.curTime==0) return
+            apiViewLogUpdate({
+                id:this.$store.state.audio.recordId,
+                stop_seconds:parseInt(this.$store.state.audio.curTime),
+                source:this.$store.state.audio.lastType
+            }).then(res=>{
+                console.log('音频播放时间记录成功');
+            })
+        }
     },
 }
 </script>

+ 72 - 0
components/collectBox/collectBox.vue

@@ -0,0 +1,72 @@
+<template>
+    <view class="collect-box" @click.stop.prevent="handleClick">
+        <image class="icon" :src="cid>0?require('@/static/collect-s.png'):require('@/static/collect.png')" mode="aspectFill" />
+    </view>
+</template>
+
+<script>
+import {apiSetCollect,apiCancelCollect} from '@/api/user'
+export default {
+    props:{
+        type:{//收藏类型:1-研报; 2-视频社区; 3-微路演视频
+            type:Number,
+            default:0
+        },
+        primaryId:{// 藏类型主ID(如报告id,视频id)
+            default:0
+        },
+        extendId:{//扩展ID-如研报章节ID
+            default:0
+        },
+        collectId:{//收藏的id 大于0说明收藏了
+            default:0,
+        }
+    },
+    data() {
+        return {
+            cid:this.collectId
+        }
+    },
+    methods: {
+        handleClick(){
+            if(this.cid>0){
+                apiCancelCollect({
+                    collection_id:Number(this.cid)
+                }).then(res=>{
+                    if(res.code===200){
+                        uni.showToast({
+                            title:'取消收藏!',
+                            icon:'none'
+                        })
+                        this.cid=0
+                    }
+                })
+            }else{
+                apiSetCollect({
+                    collection_type:this.type,
+                    primary_id:Number(this.primaryId),
+                    extend_id:Number(this.extendId)
+                }).then(res=>{
+                    if(res.code===200){
+                        uni.showToast({
+                            title:'收藏成功!',
+                            icon:'none'
+                        })
+                        this.cid=res.data
+                    }
+                })
+            }
+        }
+    },
+
+}
+</script>
+
+<style lang="scss" scoped>
+.collect-box{
+    .icon{
+        width: 34rpx;
+        height: 34rpx;
+    }
+}
+</style>

+ 9 - 3
components/sharePoster/sharePoster.vue

@@ -1,8 +1,11 @@
 <template>
     <view class="share-poster-wrap" :catchtouchmove="false">
-        <image @click="handleCreatePoster" :style="style" class="share-icon" src="@/static/share-poster-icon.png" mode="aspectFill"/>
+        <div v-if="showSlot" @click.stop="handleCreatePoster">
+            <slot></slot>
+        </div>
+        <image @click.stop="handleCreatePoster" :style="style" class="share-icon" src="@/static/share-poster-icon.png" mode="aspectFill" v-else/>
 
-        <view class="poster-mask" v-if="show||showPoster" @click="showPoster=false"></view>
+        <view class="poster-mask" v-if="show||showPoster" @click.stop="showPoster=false"></view>
         <view class="loading-box" v-if="show">
             <image class="load-img" src="../../static/loading.png" mode="aspectFill" />
             <view>海报生成中...</view>
@@ -16,10 +19,13 @@ import {apiGetPoster} from '@/api/common'
 export default {
     // shareData.type 分享页面: 
     //activity_detail(活动详情) activity_list(活动列表) special_column_list(专栏列表) special_column_detail(专栏详情) 
-    //report_list(报告列表) report_detail(报告详情) chart_list(图库列表) chart_detail(图库详情)
+    //report_list(报告列表) report_detail(报告详情) chart_list(图库列表) chart_detail(图库详情) voice_detail(语音详情)
     props:{
         style:null,
         shareData:null,
+        showSlot:{//是否用插槽显示
+            default:false
+        }
     },
     data () {
         return {

+ 521 - 0
components/videoBox/videoBox.vue

@@ -0,0 +1,521 @@
+<template>
+    <view class="video-wrap" @click="handleClickWrap">
+        <video
+            autoplay
+            object-fit="contain"
+            show-mute-btn
+            enable-play-gesture
+            :poster="videoInfo.cover_img_url"
+            :src="videoInfo.video_url"
+            :id="videoInfo.id"
+            @ended="handleVideoEnd"
+            @play="handleVideoPlay"
+            @pause="handleVideoPause"
+            @timeupdate="handleTimeUpdate"
+            @fullscreenchange="handleFullscreenchange"
+            @controlstoggle="handleControlstoggle"
+            v-if="videoInfo.id==curVideoId"
+        >
+
+            <!-- 弹幕滚动模块 -->
+            <view class="danmu-scroll-box" v-show="!closeDM">
+                <view 
+                    :class="[
+                        'danmu-item',
+                        play?'animat-run':'animat-pause',
+                        item.user_id==selfUserid?'danmu-item-self':''
+                    ]"
+                    v-for="item in danmuList"
+                    :key="item.id"
+                    :style="{color:item.color,top:item.top,animationDuration:isFullScreen?item.speed+7+'s':item.speed+'s'}"
+                >{{item.content}}</view>
+            </view>
+
+            <view class="video-inner-right-box" v-if="isShowControls">
+                <!-- 切换音频播放按钮 -->
+                <view :class="['change-music-icon',isFullScreen&&'isFullScreen']" @click.stop="handleChangeMusic"></view>
+                <!-- 弹幕控制按钮 -->
+                <view :class="['video-danmu-control-box',isFullScreen&&'isFullScreen']">
+                    <view class="show-btn" v-if="!closeDM" @click.stop="closeDM=true"></view>
+                    <view class="close-btn" v-else @click.stop="closeDM=false"></view>
+                    <!-- <view class="send-btn" v-if="!closeDM" @click.stop="showInput=true">发弹幕</view> -->
+                </view>
+                  
+                <!-- 倍速控制按钮 -->
+                <view class="video-speed-btn" @click.stop="showSpeedOpt=true">倍速</view>
+            </view>
+            
+            <!-- 倍速选项模块 -->
+            <view class="speed-opt-box" v-if="showSpeedOpt">
+                <view 
+                    class="item"
+                    :style="{color:item==curSpeed?'#F3A52F':''}" 
+                    v-for="item in speedOpts" 
+                    :key="item" 
+                    @click.stop="handleVideoSpeedChange(item)"
+                >{{item}}X</view>
+            </view>
+            
+        </video>
+        <image @click="handelClickPlay" v-else class="poster" :src="videoInfo.cover_img_url" mode="aspectFill" lazy-load/>
+
+        <!-- 外面弹幕按钮 -->
+        <view class="danmu-btn-box" v-if="showDanmu">
+            <view class="big-box" v-if="!closeDM">
+                <view class="left" @click.stop="showInput=true"></view>
+                <view class="right" @click.stop="closeDM=true"></view>
+            </view>
+            <view class="small-box" v-else @click.stop="handleShowDM"></view>
+        </view>
+        
+        <!-- 弹幕输入弹窗 -->
+        <view class="flex danmu-input-box" :style="{bottom:keyboardheight+'px',paddingLeft:isFullScreen?safeAreaTop+17+'px':'34rpx'}" v-if="showInput">
+            <view class="flex input-box">
+                <input 
+                    type="text" 
+                    v-model="danmuText" 
+                    placeholder="发个友善的弹幕见证当下~" 
+                    cursor-spacing="20" 
+                    maxlength="50" 
+                    focus 
+                    confirm-type="send"
+                    :adjust-position="false"
+                    @confirm="handleSendDanmu"
+                    @focus="handleDanmuInputFocus"
+                    @blur="handleDanmuInputBlur"
+                />
+                <text>{{danmuText.length}}/50</text>
+            </view>
+            <view class="btn" @click="handleSendDanmu">发送</view>
+        </view>
+          
+    </view>
+</template>
+
+<script>
+import {apiVideoDanmuSend} from '@/api/video'
+import { debounce } from '@/utils/common.js';
+export default {
+    props:{
+        showDanmu:{
+            type:Boolean,
+            default:false
+        },//是否显示弹幕
+        videoInfo:{},//{source:2-视频社区\3-路演视频,id:视频社区id\路演视频id,...其他数据}
+        curVideoId:0,//当前正在播放的id
+    },
+    watch: {
+        curVideoId(){
+            this.curSpeed='1.0'
+            if(this.videoInfo.id==this.curVideoId){//显示弹幕
+                this.closeDM=false
+            }else{
+                this.closeDM=true
+                this.curVideoIns=null
+                this.play=false
+                this.danmuList=[]
+                this.temdanmuList.forEach(item=>{
+                    item.done=false
+                })
+            }
+        },
+        showInput(n){
+            //写弹幕时暂停视频
+            if(n){
+                this.curVideoIns.pause()
+            }else{
+                this.curVideoIns.play()
+            }
+        },
+        closeDM(){
+            if(this.closeDM){
+                this.danmuList=[]//如果关闭了弹幕显示 则清空一次 弹幕列表 防止 切换回来又会重新播放一次已有的弹幕
+            }
+        }
+    },
+    computed:{
+        selfUserid(){ 
+            return this.$store.state.user.userInfo.user_id;
+        }
+    },
+    data() {
+        return {
+            curVideoIns:null,
+            play:false,//视频播放状态
+            curVideoTime:0,
+
+            showInput:false,//显示悬浮输入弹幕弹窗
+            closeDM:true,//是否关闭弹幕
+            danmuText:'',
+
+            showSpeedOpt:false,
+            speedOpts:['0.5','0.8','1.0','1.25','1.5','2.0'],
+            curSpeed:'1.0',
+
+            keyboardheight:0,//键盘高度
+            isBlur:false,//是否弹幕输入框失焦了
+            isFullScreen:false,//是否为全屏
+            isShowControls:false,//是否显示视频的控制栏
+
+            safeAreaTop:0,
+
+            temdanmuList:this.videoInfo.bullet_chat_list||[],
+            danmuList:[],
+        }
+    },
+    created(){
+        uni.getSystemInfo({
+            success:(res)=>{
+                this.safeAreaTop=res.safeArea.top
+            }
+        })
+    },
+    methods: {
+        //点击最外层盒子
+        handleClickWrap(){
+            this.showSpeedOpt=false
+        },
+
+        // 点击播放
+        handelClickPlay(){
+            this.$emit('videoPlay', this.videoInfo)
+            setTimeout(() => {
+                this.curVideoIns=uni.createVideoContext(this.curVideoId.toString(),this)//由于是在自定义组件内 所有this不可少
+            }, 300);
+        },
+        handleVideoPlay(){
+            this.play=true
+        },
+        handleVideoEnd(){
+            // 此处因为如果不调用退出全屏方法 安卓和ios页面均会表现异常,安卓横屏不恢复竖屏,ios底部tabbar渲染异常
+            this.curVideoIns.exitFullScreen()
+            this.curVideoIns=null
+            this.play=false
+            this.danmuList=[]
+            this.temdanmuList.forEach(item=>{
+                item.done=false
+            })
+            this.$emit('ended')
+        },
+        handleVideoPause(){
+            this.play=false
+            this.$emit('pause')
+        },
+        handleTimeUpdate(e){
+            this.addDanmu(e.detail.currentTime)
+            this.curVideoTime=e.detail.currentTime
+            this.$emit('timeupdate',e)
+        },
+        handleFullscreenchange(e){
+            this.isFullScreen=e.detail.fullScreen
+        },
+        handleControlstoggle(e){
+            this.isShowControls=e.detail.show
+        },
+        handleDanmuInputFocus(e){
+            console.log(e.detail.height);
+            this.keyboardheight=e.detail.height
+        },
+        handleDanmuInputBlur:debounce(function(){
+            if(this.showInput){
+                this.showInput=false
+            }
+        },60),
+
+        //切换为背景音频播放
+        handleChangeMusic(){
+            console.log('切换背景音频播放');
+            this.curVideoIns.requestBackgroundPlayback()
+        },
+
+        // 倍速切换
+        handleVideoSpeedChange(item){
+            const num=Number(item)
+            this.curVideoIns.playbackRate(num)
+            this.curSpeed=item
+            this.showSpeedOpt=false
+        },
+
+        //点击视频区域外面的 显示弹幕按钮 进行判断如果当前视频没有播放 则不改变状态
+        handleShowDM(){
+            if(this.videoInfo.id==this.curVideoId){
+                this.closeDM=false
+            }
+        },
+        
+        //发送弹幕
+        handleSendDanmu(){
+            if(!this.danmuText) return
+            apiVideoDanmuSend({
+                content:this.danmuText,
+                seconds:parseInt(this.curVideoTime),
+                primary_id:this.videoInfo.id,
+                source:this.videoInfo.source
+            }).then(res=>{
+                this.danmuText=''
+                if(res.code===200){
+                    this.temdanmuList.push({...res.data,seconds:Number(res.data.seconds)+3})
+                }
+            })
+        },
+
+        //添加弹幕到视频上去
+        addDanmu(ctime){
+            this.temdanmuList.forEach(item => {
+                if(item.seconds>ctime-1&&item.seconds<ctime+1){// 前后误差一秒
+                    if(!item.done){
+                        item.done=true
+                        this.danmuList.push({
+                            ...item,
+                            top:this.getTopPosition(),
+                            speed:Math.floor(Math.random()*(16-8+1))+8//8~16 之间的随机数
+                        })
+                    }
+                }else{
+                    // 如果播放过了 手贱又把进度条拖回去了 则重置done
+                    if(ctime-1<item.seconds){
+                        item.done=false
+                    }
+                    if(ctime+1>item.seconds){
+                        item.done=true
+                    }
+                }
+            });
+        },
+
+        //设置弹幕位置
+        getTopPosition(){
+            const length=this.danmuList.length
+            let num=0
+            if(length%3===1){
+                num=10
+            }else if(length%3===2){
+                num=30
+            }else{
+                num=50
+            }
+            return num+'px'
+        }
+
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+.video-wrap{
+    width: 100%;
+    height: 100%;
+    position: relative;
+    video,.poster{
+        width: 100%;
+        height: 100%;
+        border-radius: 20rpx;
+        position: relative;
+    }
+    .poster{
+        position: relative;
+        &::after{
+            content:'';
+            display: block;
+            position: absolute;
+            width: 120rpx;
+            height: 120rpx;
+            top: 50%;
+            left: 50%;
+            transform: translate(-50%,-50%);
+            background-image: url('@/static/video-play-btn.png');
+            background-size: cover;
+        }
+    }
+
+    .danmu-btn-box{
+        position: absolute;
+        bottom: -70rpx;
+        right: 6rpx;
+        .big-box{
+            width: 248rpx;
+            height: 50rpx; 
+            background-image: url('@/static/danmu-show-btn.png');  
+            background-size: cover; 
+            display: flex;
+            .left{
+                width: 67%;
+                height: 100%;
+                flex-shrink: 0;
+            }
+            .right{
+                flex: 1;
+                height: 100%;
+            }
+        }
+        .small-box{
+            width: 80rpx;
+            height: 50rpx; 
+            background-image: url('@/static/danmu-close-btn.png');  
+            background-size: cover; 
+        }
+    }
+
+    .danmu-input-box{
+        position: fixed;
+        left: 0;
+        right: 0;
+        bottom: 0;
+        z-index: 999999999;
+        background-color: #ffffff;
+        padding: 10rpx 34rpx;
+        border-top: 1px solid #E5E5E5;
+        align-content: center;
+        .input-box{
+            flex:1;
+            border-radius: 40rpx;
+            padding: 6rpx 10rpx;
+            background: #EFEFEF;
+            border: 2rpx solid #E5E5E5;
+            align-items: center;
+            font-size: 12px;
+            input{
+                flex:1;
+            }
+            text{
+                color: #999;
+            }
+        }
+        .btn{
+            width: 100rpx;
+            flex-shrink: 0;
+            color: #F3A52F;
+            font-size: 12px;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+        }
+    }
+
+
+    .video-inner-right-box{
+        position: absolute;
+        bottom: 30%;
+        right: 5%;
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+    }
+    .change-music-icon{
+        width: 40rpx;
+        height: 40rpx;
+        background-image: url('@/static/headphones-icon.png');
+        background-size: cover;
+        margin-bottom: 20rpx;
+        &.isFullScreen{
+            margin-bottom: 30rpx;
+        }
+    }
+
+    .video-speed-btn{
+        width: 80rpx;
+        height: 44rpx;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        background: rgba(0, 0, 0, 0.4);
+        border-radius: 22rpx;
+        color: #fff;
+        font-size: 12px;
+    }
+    .speed-opt-box{
+        position: absolute;
+        right: 0;
+        top: 0;
+        bottom: 0;
+        width: 20%;
+        background: rgba(0, 0, 0, 0.8);
+        display: flex;
+        flex-direction: column;
+        justify-content: space-around;
+        padding-top: 55rpx;
+        .item{
+            color: #fff;
+            font-size: 26rpx;
+            flex: 1;
+            width: 100%;
+            text-align: center;
+        }
+    }
+
+    .video-danmu-control-box{
+        margin-bottom: 10rpx;
+        &.isFullScreen{
+            margin-bottom: 30rpx;
+            .send-btn{
+                margin-top: 30rpx;
+            }
+        }
+        view{
+            margin-left: auto;
+            margin-right: auto;
+        }
+        .show-btn{
+            width: 80rpx;
+            height: 50rpx;
+            background-image: url('@/static/danmu-show-btn-2.png');
+            background-size: cover;
+        }
+        .close-btn{
+            width: 80rpx;
+            height: 50rpx;
+            background-image: url('@/static/danmu-close-btn-2.png');
+            background-size: cover;
+        }
+        .send-btn{
+            width: 100rpx;
+            height: 44rpx;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            background: rgba(0, 0, 0, 0.4);
+            border-radius: 22rpx;
+            color: #fff;
+            font-size: 12px;
+            margin-top: 20rpx;
+        }
+    }
+
+    .danmu-scroll-box{
+        .danmu-item{
+            color: #fff;
+            animation: move 6s linear;
+            position: absolute;
+            top: 0;
+            display: block;
+            left: 150%;
+            position: absolute;
+            font-size: 12px;
+            height: 18px;
+            white-space: nowrap;
+            background: rgba(48, 48, 48, 0.5);
+            padding-left: 10rpx;
+            padding-right: 10rpx;
+            border-radius: 18px;
+            padding-top: 9px;
+        }
+        .animat-pause{
+            animation-play-state: paused;
+        }
+        .animat-run{
+            animation-play-state: running;
+        }
+        .danmu-item-self{
+            color: #F9AC3A !important;
+        }
+        @keyframes move {
+            0%{
+                left: 150%;
+            }
+            100%{
+                left: -200%;
+            }
+        }
+    }
+}
+</style>

+ 364 - 0
components/videoComment/comment.vue

@@ -0,0 +1,364 @@
+<template>
+    <view class="video-comment-wrap">
+        <view :class="['flex action-wrap',showDanmu?'showDanmu':'']">
+            <view class="item" @click="handleSetLike(1)">
+                <image :src="info.op_type===1?like_act_img:like_img" mode="aspectFill"/>
+                <text>{{info.like_total>0?info.like_total:''}}</text>
+            </view>
+            <view class="item" @click="handleSetLike(2)" style="text-align:center">
+                <image :src="info.op_type===2?tease_act_img:tease_img" mode="aspectFill"/>
+                <text>{{info.tease_total>0?info.tease_total:''}}</text>
+            </view>
+            <view class="item" @click="showComment" style="text-align:right">
+                <image :src="comment_img" mode="aspectFill"/>
+                <text>{{info.comment_total>0?info.comment_total:''}}</text>
+            </view>
+        </view>
+        <view class="list-commnet-box" v-if="info.comment_list.length>0">
+            <template class="item" v-for="(item,index) in info.comment_list" >
+                <image class="avatar" :src="item.qa_avatar_url" mode="aspectFill" lazy-load="false" :key="index"/>
+				<text :key="index">{{item.comment}}</text>
+            </template>
+              
+        </view>
+          
+        <!-- 评论弹窗 -->
+        <van-action-sheet 
+			:show="isShowComment" 
+			title="视频评论"
+			@close="closeCommentHandle"
+			@clickOverlay="isShowComment=false"
+            z-index="99999"
+		>
+			<view class="comment-cont" @touchmove.stop>
+			   <view class="commment-top">
+				   <text class="title">{{comment_obj.title}} {{comment_obj.total}}</text>
+				   <view class="comment-top-right">
+					   <text :class="select_comment_type === 1 && 'act'" @click="changeCommentTypeHandle(1)">全部</text>
+					   <text :class="select_comment_type === 2 && 'act'" @click="changeCommentTypeHandle(2)">我的</text>
+				   </view>
+			   </view>
+				<scroll-view class="comment-list-cont" v-if="comment_obj.total" scroll-y>
+                    <view class="comment-list-item" v-for="(item,index) in commentList" :key="item.community_question_comment_id">
+                        <view class="flex comment">
+                            <image class="avatar" :src="item.qa_avatar_url" mode="aspectFill" lazy-load="true"/>
+                            <view style="display:flex;align-items:center">{{item.content}}</view>
+                        </view>
+                        <view class="del" v-if="select_comment_type === 2"  @click="delCommentHandle(item,index)">删除该评论</view>
+                    </view>
+				</scroll-view>
+                <view class="nodata" v-else>
+                    <image src="@/static/nodata.png"></image>
+                    <view>暂无评论</view>
+                </view>
+				<view class="write-wrap" :style="{bottom: writeBottom+'px'}">
+                    <textarea 
+                        v-model="comment_cont" 
+                        placeholder="发布一条友善的评论" 
+                        auto-height
+                        :adjust-position="false"
+                        :show-confirm-bar="false"
+                        :cursor-spacing="20"
+                        class="write-ipt"
+                        @blur="setWritePosition(0)"
+                        @focus="checkNickHandle"
+                    />
+				    <view class="confirm-btn" @click="publishMessageHandle">发布</view>
+				</view>
+			</view>
+		</van-action-sheet>
+    </view>
+</template>
+
+<script>
+import {apiSetLike,apiHotComment,apiMyComment,apiPublishComment,apiDelComment} from '@/api/question'
+export default {
+    props:{
+        showDanmu:{
+            type:Boolean,
+            default:false
+        },
+        videoInfo:null,//{source:2-视频社区\3-路演视频,id:视频社区id\路演视频id,...其他数据}
+    },
+    data() {
+        return {
+            info:this.videoInfo,
+            tease_img: require('@/static/question/tease.png'),
+			tease_act_img: require('@/static/question/tease_act.png'),
+			like_img: require('@/static/question/like.png'),
+			like_act_img: require('@/static/question/like_act.png'),
+			comment_img: require('@/static/question/comment.png'),
+
+            isShowComment: false,
+			comment_cont: '',
+			writeBottom: 0,
+			select_comment_type:1,//默认全部
+			comment_obj: {
+				title: '全部评论',
+				total: 0
+			},
+			comment_total: 0,
+			commentList: []
+        }
+    },
+    methods: {
+        /* 关闭评论弹窗 */
+        closeCommentHandle() {
+            this.isShowComment = false;
+            this.comment_cont = '';
+            this.select_comment_type = 1;//默认全部
+        },
+
+        /* 切换评论类型*/
+        changeCommentTypeHandle(type) {
+            if(type === this.select_comment_type) return
+            this.commentList = [];
+            this.select_comment_type = type;
+            this.getComment();
+        },
+
+        showComment(){
+            this.getComment()
+            this.isShowComment=true
+        },
+
+        // 获取评论
+        async getComment(flag){
+            const params={
+                community_question_id:this.info.id,
+                curr_page: 1,
+                page_size: 10000,
+                source:this.info.source
+            }
+            const { code,data } = this.select_comment_type===1 ? await apiHotComment(params) : await apiMyComment(params);
+            if(code !== 200) return
+            this.commentList = data.list || [];
+            this.comment_obj = {
+                title: this.select_comment_type === 1 ? '全部评论' : '我的评论',
+                total: data.paging.totals
+            }
+
+            // 如果flag='refresh' 则获取一次全部留言 更新到列表上面去
+            if(flag==='refresh'){
+                const res=await apiHotComment(params)
+                const arr=res.data.list||[]
+                this.info.comment_list=arr.map(item=>{
+                    return {
+                        comment:item.content,
+                        qa_avatar_url:item.qa_avatar_url
+                    }
+                })
+                this.info.comment_total=arr.length
+            }
+        },
+
+        //删除我的评论
+        delCommentHandle({community_question_comment_id},index){
+            wx.showModal({
+                title: "",
+                content: "评论删除后不可恢复,确认删除吗?",
+                confirmColor: "#EE3636",
+                cancelColor: '#333',
+                success:  async(res) => {
+                    if( res.cancel) return
+                    const { code } = await apiDelComment({ community_question_comment_id });
+                    if( code !== 200 ) return
+                    
+                    this.commentList.splice(index,1)
+                    this.comment_obj.total--
+                                
+                    wx.showToast({title: '删除成功'});
+                    this.getComment('refresh')
+                }
+            })
+        },
+
+        setWritePosition(val=50) {
+            console.log(val)
+            this.writeBottom = val < 50 ? 0 : val-8;
+        },
+
+        checkNickHandle(e){
+            this.setWritePosition(e.detail.height);
+        },
+
+        //发布留言
+        async publishMessageHandle(){
+            if(!this.comment_cont) return wx.showToast({title: '请输入留言内容',icon: 'none'})
+            const { code } = await apiPublishComment({
+                content: this.comment_cont,
+                community_question_id: this.info.id,
+                source:this.info.source,
+            })
+            if(code===200){
+                wx.showToast({title: '发布成功'});
+                this.comment_cont = '';
+                this.getComment('refresh')
+            }
+        },
+
+        //吐槽/点赞
+        async handleSetLike(type){
+            const res=await apiSetLike({
+                community_question_id:this.info.id,
+                op_type: type,
+                enable: type === 1 ? Number(this.info.op_type!==1) : Number(this.info.op_type!==2),
+                source:this.info.source
+            })
+            if(res.code===200){
+                const { enabled,op_type,like_total,tease_total } = res.data;
+                this.info.tease_total = tease_total;
+                this.info.like_total = like_total;
+                this.info.op_type = enabled === 0 ? 0 : op_type ;
+                uni.showToast({
+                    title: enabled === 0 ? '取消成功' : op_type=== 1 ? '点赞成功' : '吐槽成功'
+                })
+            }
+        },
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+.video-comment-wrap{
+    .action-wrap{
+        justify-content: space-between;
+        padding: 0 56rpx;
+        .item{
+            min-width: 80rpx;
+            image{
+                width: 48rpx;
+                height: 48rpx;
+                vertical-align: middle;
+            }
+            text{
+                font-size: 28rpx;
+                color: #999;
+                vertical-align: middle;
+            }
+        }
+    }
+    .showDanmu{
+        width: 50%;
+        padding: 0;
+    }
+}
+.list-commnet-box{
+    margin-top: 34rpx;
+    background-color: #F9F9F9;
+    padding: 20rpx;
+    // .item{
+        color: #666;
+		font-size: 28rpx;
+        .avatar{
+			width: 56rpx;
+			height: 56rpx;
+			border-radius: 50%;
+			margin-right: 14rpx;
+			vertical-align: middle;
+		}
+		text{
+			vertical-align: middle;
+			line-height: 56rpx;
+			margin-right: 20rpx;
+		}
+    // }
+}
+.comment-cont {
+	height: calc(100vh - 250rpx);
+	border-top: 4rpx solid #F4F4F4;
+    position: relative;
+    padding: 24rpx 0;
+    overflow: hidden;
+   .commment-top {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      padding: 0 24rpx;
+      .title {
+         font-weight: bold;
+         font-size: 30rpx;
+         color: #000;
+      }
+      .comment-top-right {
+         display: flex;
+         align-items: center;
+         background-color: #F6F6F6;
+         border: 1px solid #F6F6F6;
+         color: #666;
+         border-radius: 48rpx;
+         text {
+            padding: 0 12rpx;
+            height: 48rpx;
+            line-height: 48rpx;
+            &.act {
+               background-color: #FFFFFF;
+               color: #000;
+               border-radius: 48rpx;
+            }
+         }
+      }
+   }
+   .comment-list-cont {
+      height: calc(100vh - 550rpx);
+      overflow-y: auto;
+      position: relative;
+      padding: 30rpx 0;
+      .comment-list-item {
+			margin-bottom: 30rpx;
+			padding: 0 24rpx;
+			.comment { 
+				color: #666; 
+				.avatar{
+					width: 56rpx;
+					height: 56rpx;
+					border-radius: 50%;
+					flex-shrink: 0;
+					margin-right: 20rpx;
+				}
+				view{
+					flex: 1;
+				}
+			}
+			.del { 
+				color: #D80000;
+				margin-top: 10rpx;
+				margin-left: 76rpx;
+				width: 200rpx; 
+			}
+      }
+   }
+   .write-wrap {
+      padding: 0 24rpx;
+      border-top: 4rpx solid #F4F4F4;
+      position: absolute;
+      // bottom: 50px;
+      left: 0;
+      right: 0;
+      display: flex;
+      align-items: center;
+      z-index: 99;
+      background-color: #fff;
+      padding-bottom: calc(5px + constant(safe-area-inset-bottom));
+      padding-bottom: calc(5px + env(safe-area-inset-bottom));
+      ::-webkit-scrollbar {
+         display: none;
+      }
+      .write-ipt {
+         padding: 30rpx 0;
+         flex: 1;
+      }
+      .confirm-btn {
+         width: 100rpx;
+         margin-left: 20rpx;
+         text-align: center;
+         padding: 20rpx 0;
+         color: #E3B377;
+      }
+   }
+}
+.nodata {
+   text-align: center;
+   color: #999;
+}
+</style>

+ 6 - 6
custom-tab-bar/index.wxml

@@ -1,6 +1,6 @@
-<cover-view class="tab-bar">
-  <cover-view wx:for="{{list}}" wx:key="index" class="tab-bar-item" data-path="{{item.pagePath}}" data-text="{{item.text}}" bindtap="switchTab">
-    <cover-image class="icon" src="{{selected === item.pagePath ? item.selectedIconPath : item.iconPath}}"></cover-image>
-    <cover-view class="text" style="color: {{selected === item.pagePath ? selectedColor : color}}">{{item.text}}</cover-view>
-  </cover-view>
-</cover-view>
+<view class="tab-bar">
+  <view wx:for="{{list}}" wx:key="index" class="tab-bar-item" data-path="{{item.pagePath}}" data-text="{{item.text}}" bindtap="switchTab">
+    <image class="icon" src="{{selected === item.pagePath ? item.selectedIconPath : item.iconPath}}"></image>
+    <view class="text" style="color: {{selected === item.pagePath ? selectedColor : color}}">{{item.text}}</view>
+  </view>
+</view>

+ 4 - 2
mixin/index.js

@@ -4,8 +4,10 @@ dayjs.locale('zh-cn')
 // 引入全局配置的图片资源地址 
 import {globalImgUrls} from "../utils/config"
 import store from '@/store'
+import {defaultTabBarListConfig} from '@/utils/config.js'
 
-const tabbarPathList=['pages/voice/voice','pages/pricedriven/pricedriven','pages/video/videoList','pages/report/report','pages/question/question']
+// const tabbarPathList=['pages/voice/voice','pages/roadShow/video/list','pages/video/videoList','pages/report/report','pages/question/question']
+const tabbarPathList=defaultTabBarListConfig.map(item=>item.pagePath)
 
 module.exports = {
   watch: {
@@ -50,7 +52,7 @@ module.exports = {
      * 报告时间格式化
      */
     formatReportTime(e){
-      return dayjs(e).format('YYYY.MM.DD')
+      return dayjs(e).format('YYYY-MM-DD')
     }
 
   },

+ 1 - 0
mixin/questionMixin.js

@@ -405,6 +405,7 @@ export default {
                 }).then((res)=>{
                     if(res.code===200){
                       console.log('音频id为'+audioItem.community_question_audio_id+'点击次数+1')  
+                      this.$store.commit('audio/addAudioRecordId',{recordId:res.data,source:1})
                     }
                 })
             }

+ 11 - 3
pages-report/classify.vue

@@ -2,7 +2,7 @@
   <view class="classify-page">
     <swiper class="swiper" autoplay interval>
       <swiper-item>
-        <image @click="goFiccService" :src="globalImgUrls.ficcServiceImg" mode="aspectFill"/>
+        <image @click="goFiccService" :src="globalImgUrls.ficcServiceImg+'?t='+new Date().getDay()" mode="aspectFill"/>
       </swiper-item>
     </swiper>
     <view class="list">
@@ -45,7 +45,7 @@ export default {
     },
 
     goDetail(item){
-      //redirect_type : 跳转页面类型:1,专栏列表,2报告列表,3专栏详情
+      //redirect_type : 跳转页面类型:1,专栏列表,2报告列表,3专栏详情,4品种类型列表
       if(item.redirect_type==1){
         uni.navigateTo({ url: `/pages-report/specialColumn/list?classifyId=${item.classify_id_first}&classifyName=${item.classify_name_first}` })
       }
@@ -55,6 +55,9 @@ export default {
       if(item.redirect_type==3){
         uni.navigateTo({url:'/pages-report/specialColumn/detail?columnId='+item.classify_id_second})
       }
+      if(item.redirect_type==4){
+        uni.navigateTo({url:`/pages-report/reportForVariety/list?classifyId=${item.classify_id_first}&classifyName=${item.classify_name_first}`})
+      }
     },
 
     goFiccService(){
@@ -63,7 +66,12 @@ export default {
   }
 };
 </script>
-
+<style>
+page{
+    padding-bottom: constant(safe-area-inset-bottom);
+    padding-bottom: env(safe-area-inset-bottom);
+}
+</style>
 <style lang="scss" scoped>
 .classify-page {
   padding: 34rpx;

+ 366 - 0
pages-report/reportForVariety/list.vue

@@ -0,0 +1,366 @@
+<template>
+    <view class="varietyauth-report-list">
+        <view class="top-variety-box">
+            <view class="first-nav">
+                <text 
+                    :class="['first-nav-item',item.id===firstVarietyId?'active':'']" 
+                    v-for="item in varietyList" 
+                    :key="item.id"
+                    @click="handleSelectFirstVariety(item)"
+                >{{item.classify_name}}</text>
+            </view>
+            <view class="sub-nav">
+                <text 
+                    :class="['sub-nav-item',item.chart_permission_id===secVarietyId?'active':'']" 
+                    v-for="item in secVarietyList" 
+                    :key="item.chart_permission_id"
+                    @click="handleSelectSecVariety(item)"
+                >{{item.chart_permission_name}}</text>
+            </view>
+        </view>
+        <view class="report-empty-box" v-if="finished&&list.length==0">
+            <image :src="globalImgUrls.chartEmpty" mode="widthFix" />
+            <view>暂无报告</view>
+        </view>
+        <view class="report-list-wrap" v-else>
+            <view class="flex item" v-for="item in list" :key="item.report_id" @click="goReportDetail(item)">
+                <image class="img" :src="item.report_img_url" mode="aspectFill" lazy-load />
+                <view class="con">
+                    <view class="van-multi-ellipsis--l2 title">{{item.title}}</view>
+                    <view class="info">{{item.classify_name_second}} · {{item.stage}}期 | {{item.publish_time|formatReportTime}}</view>
+                </view>
+                <view class="audio-box" @click.stop="handleClickAudio(item)">
+                    <image src="../static/a-pause.png" mode="aspectFill"/>
+                </view>
+            </view>
+        </view>
+
+        <!-- 音频弹窗 -->
+        <audioBox v-if="showAudioPop"></audioBox>
+
+        <!-- 分享海报 -->
+        <sharePoster 
+        :style="{bottom:'190rpx'}" 
+        :shareData="{
+            type:'report_list',
+            code_page:'pages-report/reportForVariety/list',
+            code_scene:code_scene,
+            data:shareParams
+        }"></sharePoster>
+    </view>
+</template>
+
+<script>
+import {apiGetSceneToParams} from '@/api/common'
+import {apiGoodsPermissionList,apiReportListForVariety} from '@/api/report'
+import audioBox from '../components/audioBox.vue'
+const moment=require('@/utils/moment-with-locales.min')
+export default {
+    computed:{
+        showAudioPop(){//是否显示音频弹窗
+            return this.$store.state.report.audioData.show 
+        },
+        curAudioReportId(){//当前播放的音频所属报告
+            return this.$store.state.report.audioData.reportId
+        },
+        curAudioPaused(){//当前音频是否暂停状态
+            return this.$store.state.report.audioData.paused
+        },
+        shareParams(){
+            let obj={
+                list_title:this.classifyName,
+                img_1:'',
+                title_1:'',
+                abstract_1:'',
+                abstract_1_style:'',
+                time_1:'',
+                img_2:'',
+                title_2:'',
+                abstract_2:'',
+                abstract_2_style:'',
+                time_2:'',
+            }
+            if(this.list[0]){
+                obj.img_1=this.list[0].report_img_url
+                obj.title_1=this.list[0].title 
+                obj.abstract_1=this.list[0].classify_name_second
+                obj.time_1=`${this.list[0].stage}期 | ${moment(this.list[0].publish_time).format('YYYY.MM.DD')}`
+                obj.abstract_1_style=this.list[0].classify_name_second?'':'display:none'
+            }
+            if(this.list[1]){
+                obj.img_2=this.list[1].report_img_url
+                obj.title_2=this.list[1].title 
+                obj.abstract_2=this.list[1].classify_name_second
+                obj.time_2=`${this.list[1].stage}期 | ${moment(this.list[1].publish_time).format('YYYY.MM.DD')}`
+                obj.abstract_2_style=this.list[1].classify_name_second?'':'display:none'
+            }
+            return obj
+        },
+        code_scene(){
+            return JSON.stringify({classifyId:this.classifyId,classifyName:this.classifyName})
+        }
+    },
+    components: {
+        audioBox
+    },
+    data() {
+        return {
+            classifyId:0,
+            classifyName:'',
+            varietyList:[],
+            firstVarietyId:0,//选择的一级品种id
+            secVarietyList:[],//二级品种
+            secVarietyId:0,//选择的二级品种id
+
+            list:[],
+            finished:false,
+            page:1,
+            pageSize:20
+        }
+    },
+    onLoad(opt){
+        this.init(opt)
+    },
+    onPullDownRefresh() {
+        this.page=1
+        this.list=[]
+        this.finished=false
+        this.getPermissionList()
+        setTimeout(() => {
+            uni.stopPullDownRefresh()
+        }, 1500);
+    },
+    onReachBottom() {
+        if(this.finished) return
+        this.page++
+        this.getList()
+    },
+    onShareAppMessage() {
+        return {
+            title:`FICC【${this.classifyName}】`
+        }
+    },
+    methods: {
+        async init(opt){
+            let classifyId=opt.classifyId||0
+            let classifyName=opt.classifyName
+            if(opt.scene){
+                const res=await apiGetSceneToParams({scene_key:opt.scene})
+                if(res.code===200){
+                    const obj=JSON.parse(res.data)
+                    classifyId=obj.classifyId
+                    classifyName=obj.classifyName
+                }
+            }
+            this.classifyId=classifyId
+            this.classifyName=decodeURIComponent(classifyName)
+            uni.setNavigationBarTitle({ title: this.classifyName })
+            this.getPermissionList()
+        },
+
+        //获取用户已绑定品种
+        async getPermissionList(){
+            const res=await apiGoodsPermissionList({
+                classify_id:Number(this.classifyId),
+            })
+            if(res.code===200){
+                let arr=res.data.permission_list||[]
+                //如果一个权限都没有则返回到分类列表
+                if(arr.length===0){
+                    uni.showToast({
+                        title: '暂无权限',
+                        icon: 'none'
+                    })
+                    setTimeout(() => {
+                        uni.reLaunch({
+                            url: '/pages-report/classify',
+                        });
+                    }, 1500);
+                    
+                    return
+                }
+                this.varietyList=arr
+                this.handleSelectFirstVariety(this.varietyList[0])
+            }
+        },
+
+        //选择一级品种
+        handleSelectFirstVariety(item){
+            this.firstVarietyId=item.id
+            this.secVarietyList=item.list
+            this.handleSelectSecVariety(item.list[0])
+        },
+        //选择二级品种
+        handleSelectSecVariety(item){
+            this.secVarietyId=item.chart_permission_id
+            this.page=1
+            this.finished=false
+            this.list=[]
+            this.getList()
+        },
+
+        async getList(){
+            const res=await apiReportListForVariety({
+                chart_permission_id:Number(this.secVarietyId),
+                classify_id:Number(this.classifyId),
+                current_index:this.page,
+                page_size:this.pageSize
+            })
+            if(res.code===200){
+                const arr=res.data.list||[]
+                this.list=[...this.list,...arr]
+                this.finished=res.data.paging.is_end
+            }
+        },
+
+        // 跳转报告详情
+        goReportDetail(item){
+            if(['晨报','周报'].includes(item.classify_name_first)){
+                uni.navigateTo({url: `/pages-report/chapterDetail?chapterId=${item.report_chapter_id}`})
+            }else{
+                uni.navigateTo({url:'/pages-report/reportDetail?reportId='+item.report_id})
+            }
+        },
+
+        handleClickAudio(item){
+            if(!item.auth_ok) return
+            if(!item.video_list||item.video_list.length==0){
+                uni.showToast({
+                    title: '暂无音频',
+                    icon: 'none'
+                })
+                return
+            }
+            // 判断是否为同一个音频
+            if(this.$store.state.report.audioData.reportId==item.report_id){
+                if(this.globalBgMusic.paused){
+                    this.globalBgMusic.play()
+                    this.$store.commit('showPopAudio')
+                }else{
+                    this.globalBgMusic.pause()
+                }
+            }else{
+                this.$store.commit('addAudio', {list:item.video_list,reportId:item.report_id})
+            }
+        },
+    },
+}
+</script>
+
+<style>
+page{
+    padding-bottom: constant(safe-area-inset-bottom);
+    padding-bottom: env(safe-area-inset-bottom);
+}
+</style>
+
+<style lang="scss" scoped>
+.top-variety-box{
+    padding: 40rpx 34rpx 0 34rpx;
+    box-shadow: 0px 4rpx 4rpx rgba(198, 198, 198, 0.25);
+    background-color: #fff;
+    position: sticky;
+    left: 0;
+    right: 0;
+    top: 0;
+    z-index: 50;
+    .first-nav-item{
+        display: inline-block;
+        min-width: 140rpx;
+        line-height: 70rpx;
+        margin-right: 30rpx;
+        font-size: 32rpx;
+        color: #666;
+        text-align: center;
+        background: #F5F5F5;
+        border-radius: 4px;
+        box-sizing: border-box;
+        padding: 0 20rpx;
+        margin-bottom: 16rpx;
+        &.active{
+            color: #E3B377;
+            background: #FDF8F2;
+        }
+    }
+    .sub-nav{
+        overflow-x: auto;
+        white-space: nowrap;
+        padding: 16rpx 0;
+        &::-webkit-scrollbar{
+            width: 0;
+            height: 0;
+            display: none;
+        }
+        .sub-nav-item{
+            display: inline-block;
+            position: relative;
+            margin-right: 50rpx;
+            font-size: 28rpx;
+            color: #666;
+            position: relative;
+            &.active{
+                color: #E3B377;
+                &::after{
+                    content: '';
+                    display: block;
+                    width: 54rpx;
+                    height: 4rpx;
+                    background-color: #E3B377;
+                    position: absolute;
+                    bottom: -16rpx;
+                    left: 50%;
+                    transform: translateX(-50%);
+                }
+            }
+        }
+    }
+}
+.report-list-wrap{
+    padding: 34rpx;
+    .item{
+        margin-bottom: 30rpx;
+        position: relative;
+        .img{
+            width: 90rpx;
+            height: 120rpx;
+            background-color: #f5f5f5;
+            border-radius: 8rpx;
+            overflow: hidden;
+            margin-right: 19rpx;
+            flex-shrink: 0;
+        }
+        .con{
+            padding-right: 100rpx;
+            flex: 1;
+        }
+        .title{
+            font-size: 28rpx;
+            font-weight: bold;
+            margin-bottom: 10rpx;
+            min-height: 70rpx;
+        }
+        .info{
+            font-size: 24rpx;
+            color: #9C9791;
+        }
+        .audio-box{
+            position: absolute;
+            top: 50%;
+            transform: translateY(-50%);
+            width: 22px;
+            height: 20px;
+            background: linear-gradient(180deg, #F3A52F 0%, #E3B377 100%);
+            border-radius: 6px;
+            right: 20rpx;
+            text-align: center;
+            image{
+                width: 12px;
+                height: 12px;
+                position: relative;
+                top: 1px;
+            }
+        }
+
+    }
+}
+</style>

+ 51 - 52
pages-report/reportList.vue

@@ -24,11 +24,13 @@
         <image class="img" :src="item.report_img_url" mode="aspectFill" lazy-load />
         <view class="con">
           <view class="title" v-html="item.title"></view>
-          <view class="info" v-html="item.classify_name_second"></view>
-          <view class="time">{{item.stage}}期 | {{item.publish_time|formatReportTime}}</view>
-          <view :class="['audio-box',!item.auth_ok&&'grey-audio-box']" @click.stop="handleClickAudio(item)" v-if="item.auth_ok">
-            <image :src="curAudioReportId==item.report_id&&!curAudioPaused?'./static/audio-s.png':'./static/audio.png'" mode="aspectFill"/>
-            <text>{{curAudioReportId==item.report_id&&!curAudioPaused?'暂停':'播放'}}</text>
+          <view class="info">
+            <view v-html="item.classify_name_second" style="display:inline-block"></view>
+            <text v-if="item.classify_name_second" style="display:inline-block;margin:0 10rpx">&nbsp;·&nbsp;</text>
+            <text>{{item.stage}}期 | {{item.publish_time|formatReportTime}}</text>
+          </view>
+          <view class="audio-box" v-if="item.auth_ok" @click.stop="handleClickAudio(item)">
+            <image :src="curAudioReportId==item.report_id&&!curAudioPaused?'./static/a-play.png':'./static/a-pause.png'" mode="aspectFill"/>
           </view>
         </view>
       </view>
@@ -36,7 +38,7 @@
 
     <!-- 筛选 -->
     <van-popup :show="showFilter" position="bottom" :safe-area-inset-bottom="false" round @close="showFilter=false">
-        <view class="filter-wrap">
+        <view class="filter-wrap" @touchmove.stop>
             <view class="flex top">
                 <text style="color:#000">筛选</text>
                 <text style="color:#E3B377" @click="showFilter=false">取消</text>
@@ -93,10 +95,12 @@ export default {
         img_1:'',
         title_1:'',
         abstract_1:'',
+        abstract_1_style:'',
         time_1:'',
         img_2:'',
         title_2:'',
         abstract_2:'',
+        abstract_2_style:'',
         time_2:'',
       }
       if(this.list[0]){
@@ -104,12 +108,14 @@ export default {
         obj.title_1=this.list[0].title 
         obj.abstract_1=this.list[0].classify_name_second
         obj.time_1=`${this.list[0].stage}期 | ${dayjs(this.list[0].publish_time).format('YYYY.MM.DD')}`
+        obj.abstract_1_style=this.list[0].classify_name_second?'':'display:none'
       }
       if(this.list[1]){
         obj.img_2=this.list[1].report_img_url
         obj.title_2=this.list[1].title 
         obj.abstract_2=this.list[1].classify_name_second
         obj.time_2=`${this.list[1].stage}期 | ${dayjs(this.list[1].publish_time).format('YYYY.MM.DD')}`
+        obj.abstract_2_style=this.list[1].classify_name_second?'':'display:none'
       }
       return obj
     },
@@ -274,7 +280,8 @@ export default {
 
 <style>
 page{
-  padding-bottom: 0;
+  padding-bottom: constant(safe-area-inset-bottom);
+  padding-bottom: env(safe-area-inset-bottom);
 }
 </style>
 <style lang="scss" scoped>
@@ -298,58 +305,50 @@ page{
 }
 .report-list-wrap {
   padding: 0 34rpx;
-  .item {
-    padding-bottom: 30rpx;
+  .item{
     margin-bottom: 30rpx;
-    border-bottom: 1px solid #EDEDED;
-    .img {
-      width: 120rpx;
-      height: 180rpx;
+    position: relative;
+    .img{
+      width: 90rpx;
+      height: 120rpx;
       background-color: #f5f5f5;
+      border-radius: 8rpx;
+      overflow: hidden;
+      margin-right: 19rpx;
       flex-shrink: 0;
-      margin-right: 20rpx;
-      border-radius: 16rpx;
     }
-    .con {
+    .con{
+      padding-right: 100rpx;
       flex: 1;
-      position: relative;
-      overflow: hidden;
-      .title {
-        font-size: 32rpx;
-        font-weight: bold;
-        margin-bottom: 8rpx;
-      }
-      
-      .time {
-        position: absolute;
-        color: #666666;
-        bottom: 0;
-        left: 0;
-        font-size: 28rpx;
-      }
-      .audio-box {
-        position: absolute;
-        bottom: 0;
-        right: 0;
-        width: 99rpx;
-        height: 39rpx;
-        background: #E3B377;
-        border-radius: 20rpx;
-        color: #fff;
-        font-size: 24rpx;
-        display: flex;
-        justify-content: center;
-        align-items: center;
-        image{
-          width: 30rpx;
-          height: 30rpx;
-          margin-right: 4rpx;
-        }
-      }
-      .grey-audio-box {
-        background: linear-gradient(114deg, #b0b0b0 0%, #e5e2e2 100%);
+    }
+    .title{
+      font-size: 28rpx;
+      font-weight: bold;
+      margin-bottom: 10rpx;
+      min-height: 70rpx;
+    }
+    .info{
+      font-size: 24rpx;
+      color: #9C9791;
+    }
+    .audio-box{
+      position: absolute;
+      top: 50%;
+      transform: translateY(-50%);
+      width: 22px;
+      height: 20px;
+      background: linear-gradient(180deg, #F3A52F 0%, #E3B377 100%);
+      border-radius: 6px;
+      right: 20rpx;
+      text-align: center;
+      image{
+        width: 12px;
+        height: 12px;
+        position: relative;
+        top: 1px;
       }
     }
+
   }
 }
 .filter-wrap{

BIN
pages-report/static/a-pause.png


BIN
pages-report/static/a-play.png


+ 79 - 45
pages-roadShow/video/list.vue

@@ -36,26 +36,34 @@
                     <text class="tag">{{item.chart_permission_name}}</text>
                     <text class="title">{{item.title}}</text>
                 </view>
+                <collectBox
+                    :type="3"
+                    :primaryId="item.road_video_id"
+                    :collectId="item.collection_id"
+                    class="share-btn collect-btn"
+                />
                 <button 
                     class="share-btn" 
                     open-type="share" 
                     :data-item="item">
                     <image class="share-img" src="@/static/share-icon.png" mode="aspectFill"/>
                 </button>
-                <video
-                    autoplay
-                    object-fit="contain"
-                    show-mute-btn
-                    :poster="item.cover_img_url"
-                    :src="item.video_url"
-                    enable-play-gesture
-                    :id="item.road_video_id"
-                    @ended="handleVideoEnd"
-                    v-if="item.road_video_id==curVideoId"
-                ></video>
-                <image @click="handelClickPlay(item)" v-else class="poster" :src="item.cover_img_url" mode="aspectFill" lazy-load/>
-                <view class="time">发布时间:{{item.publish_time}}</view>
-                <view class="user-name">{{item.admin_real_name}}</view>
+                <view style="padding-top:20rpx">
+                    <view class="time">发布时间:{{item.publish_time}}</view>
+                    <view class="user-name">{{item.admin_real_name}}</view>
+                </view>
+                <view class="video-content">
+                    <videoBox 
+                        :videoInfo="getDanmuData(item)"
+                        :curVideoId="curVideoId"
+                        :showDanmu="showDanmu"
+                        @videoPlay="handelClickPlay"
+                        @ended="handleVideoEnd"
+                        @pause="handleVideoPause"
+                        @timeupdate="handleTimeUpdate"
+                    />
+                </view>
+                <comment :showDanmu="showDanmu" :videoInfo="getCommentData(item)"></comment>
             </view>
         </view>
 
@@ -113,13 +121,19 @@
 </template>
 <script>
 import {apiRoadShowVideoList,apiRoadShowVideoPlayLog} from '@/api/roadShow'
-import {apiGetSceneToParams,apiUserBindPermission} from '@/api/common'
+import {apiGetSceneToParams,apiUserBindPermission,apiViewLogUpdate} from '@/api/common'
 import noAuth from './components/noAuth.vue'
 import dragButton from '@/components/dragButton/dragButton.vue'
+import comment from '@/components/videoComment/comment.vue'
+import collectBox from '@/components/collectBox/collectBox.vue'
+import videoBox from '@/components/videoBox/videoBox.vue'
 export default {
     components:{
         noAuth,
-        dragButton
+        dragButton,
+        comment,
+        collectBox,
+        videoBox
     },
     data() {
         return {
@@ -135,12 +149,15 @@ export default {
             list:[],
 
             curVideoId:0,
-            curVideoIns:null,
+            curVideoTime:0,
+            videoRecordId:0,
 
             isAuth:true,
             noAuthData:null,
 
             noShareData:false,//用户从分享进入没有该分享的视频的权限
+
+            showDanmu:true,//控制整个模块是否显示弹幕功能(没用了本来后台有个开关功能的 后来不要了 但是还是留着吧)
         }
     },
     onLoad(options){
@@ -191,6 +208,22 @@ export default {
         this.getList()
     },
     methods: {
+        // 处理弹幕模块需要的数据
+        getDanmuData(item){
+            return {
+                source:2,
+                id:item.road_video_id,
+                ...item
+            }
+        },
+        // 处理评论模块需要的数据
+        getCommentData(item){
+            return {
+                source:3,
+                id:item.road_video_id,
+                ...item
+            }
+        },
         async init(options){
             if(options.scene){
                 const resScene=await apiGetSceneToParams({scene_key:options.scene})
@@ -275,25 +308,43 @@ export default {
 
         handelClickPlay(item){
             this.curVideoId=item.road_video_id
-            setTimeout(() => {
-                this.curVideoIns=uni.createVideoContext(this.curVideoId.toString())
-            }, 300);
             // 记录播放
             apiRoadShowVideoPlayLog({video_id:Number(item.road_video_id)}).then(res=>{
                 if(res.code===200){
                     console.log('视频埋点成功');
+                    this.videoRecordId=res.data
                 }
             })
         },
 
         //视频播放结束
         handleVideoEnd(){
-            // 此处因为如果不调用退出全屏方法 安卓和ios页面均会表现异常,安卓横屏不恢复竖屏,ios底部tabbar渲染异常
-            this.curVideoIns.exitFullScreen()
             setTimeout(() => {
                 this.curVideoId=0
-                this.curVideoIns=null
             }, 200);
+        },
+
+        //时长变化
+        handleTimeUpdate(e){
+            // console.log(this.curVideoId,e.detail.currentTime);
+            this.curVideoTime=e.detail.currentTime
+        },
+
+        handleVideoPause(){
+            // console.log(`视频 pause---${this.videoRecordId}----${this.curVideoTime}`);
+            this.handleUpdateVideoPlayTime()
+        },
+
+        // 更新播放时长
+        handleUpdateVideoPlayTime(){
+            if(!this.videoRecordId) return
+            apiViewLogUpdate({
+                id:this.videoRecordId,
+                stop_seconds:parseInt(this.curVideoTime),
+                source:4
+            }).then(res=>{
+                console.log('更新播放时长成功');
+            })
         }
     },
 }
@@ -342,7 +393,7 @@ export default {
             padding: 30rpx 34rpx;
             position: relative;
             .title-box{
-                padding-right: 40rpx;
+                margin-right: 110rpx;
             }
             .share-btn{
                 position: absolute;
@@ -361,6 +412,9 @@ export default {
                 width: 32.5rpx;
                 height: 32rpx;
             }
+            .collect-btn{
+                right: 96rpx;
+            }
             .tag{
                 color: #E4B478;
                 background-color: #333;
@@ -380,30 +434,10 @@ export default {
                 color: #000;
                 vertical-align: middle;
             }
-            video{
-                width: 100%;
-                height: 400rpx;
-                margin: 30rpx 0 20rpx 0;
-                border-radius: 20rpx;
-            }
-            .poster{
+            .video-content{
                 width: 100%;
                 height: 400rpx;
                 margin: 30rpx 0 20rpx 0;
-                border-radius: 20rpx;
-                position: relative;
-                &::after{
-                    content:'';
-                    display: block;
-                    position: absolute;
-                    width: 120rpx;
-                    height: 120rpx;
-                    top: 50%;
-                    left: 50%;
-                    transform: translate(-50%,-50%);
-                    background-image: url('@/static/video-play-btn.png');
-                    background-size: cover;
-                }
             }
             .time{
                 font-size: 28rpx;

+ 81 - 46
pages-roadShow/video/search.vue

@@ -23,26 +23,34 @@
                     <text class="tag">{{item.chart_permission_name}}</text>
                     <text class="title">{{item.title}}</text>
                 </view>
+                <collectBox
+                    :type="3"
+                    :primaryId="item.road_video_id"
+                    :collectId="item.collection_id"
+                    class="share-btn collect-btn"
+                />
                 <button 
                     class="share-btn" 
                     open-type="share" 
                     :data-item="item">
                     <image class="share-img" src="@/static/share-icon.png" mode="aspectFill"/>
                 </button>
-                <video
-                    autoplay
-                    object-fit="contain"
-                    show-mute-btn
-                    :poster="item.cover_img_url"
-                    :src="item.video_url"
-                    enable-play-gesture
-                    :id="item.road_video_id"
-                    @ended="handleVideoEnd"
-                    v-if="item.road_video_id==curVideoId"
-                ></video>
-                <image @click="handelClickPlay(item)" v-else class="poster" :src="item.cover_img_url" mode="aspectFill" lazy-load/>
-                <view class="time">发布时间:{{item.publish_time}}</view>
-                <view class="user-name">{{item.admin_real_name}}</view>
+                <view style="padding-top:20rpx">
+                    <view class="time">发布时间:{{item.publish_time}}</view>
+                    <view class="user-name">{{item.admin_real_name}}</view>
+                </view>
+                <view class="video-content">
+                    <videoBox 
+                        :videoInfo="getDanmuData(item)"
+                        :curVideoId="curVideoId"
+                        :showDanmu="showDanmu"
+                        @videoPlay="handelClickPlay"
+                        @ended="handleVideoEnd"
+                        @pause="handleVideoPause"
+                        @timeupdate="handleTimeUpdate"
+                    />
+                </view>
+                <comment :showDanmu="showDanmu" :videoInfo="getCommentData(item)"></comment>
             </view>
         </view>
     </view>
@@ -51,9 +59,16 @@
 <script>
 import searchBox from '@/components/searchBox/searchBox.vue'
 import {apiRoadShowVideoList,apiRoadShowVideoPlayLog} from '@/api/roadShow'
+import comment from '@/components/videoComment/comment.vue'
+import {apiViewLogUpdate} from '@/api/common'
+import collectBox from '@/components/collectBox/collectBox.vue'
+import videoBox from '@/components/videoBox/videoBox.vue'
 export default {
     components: {
-        searchBox
+        searchBox,
+        collectBox,
+        comment,
+        videoBox
     },
     data() {
         return {
@@ -65,7 +80,10 @@ export default {
             pageSize:10,
 
             curVideoId:0,
-            curVideoIns:null
+            curVideoTime:0,
+            videoRecordId:0,
+
+            showDanmu:true,//控制整个模块是否显示弹幕功能(没用了本来后台有个开关功能的 后来不要了 但是还是留着吧)
         }
     },
     onReachBottom() {
@@ -75,12 +93,12 @@ export default {
     },
     onShareAppMessage({from,target}) {
         console.log(from,target);
-        let path='/pages-roadShow/video/list?videoId=0'
+        let path='/pages/roadShow/video/list?videoId=0'
         let title='FICC线上路演'
         let imageUrl=''
         if(from=='button'){
             title=target.dataset.item.title
-            path=`/pages-roadShow/video/list?videoId=${target.dataset.item.road_video_id}`
+            path=`/pages/roadShow/video/list?videoId=${target.dataset.item.road_video_id}`
             imageUrl=target.dataset.item.cover_img_url
         }
         return {
@@ -90,6 +108,22 @@ export default {
         }
     },
     methods: {
+        // 处理弹幕模块需要的数据
+        getDanmuData(item){
+            return {
+                source:2,
+                id:item.road_video_id,
+                ...item
+            }
+        },
+        // 处理评论模块需要的数据
+        getCommentData(item){
+            return {
+                source:3,
+                id:item.road_video_id,
+                ...item
+            }
+        },
         onChange(e){
             this.searchVal=e
         },
@@ -123,25 +157,43 @@ export default {
 
         handelClickPlay(item){
             this.curVideoId=item.road_video_id
-            setTimeout(() => {
-                this.curVideoIns=uni.createVideoContext(this.curVideoId.toString())
-            }, 300);
             // 记录播放
             apiRoadShowVideoPlayLog({video_id:Number(item.road_video_id)}).then(res=>{
                 if(res.code===200){
                     console.log('视频埋点成功');
+                    this.videoRecordId=res.data
                 }
             })
         },
 
         //视频播放结束
         handleVideoEnd(){
-            // 此处因为如果不调用退出全屏方法 安卓和ios页面均会表现异常,安卓横屏不恢复竖屏,ios底部tabbar渲染异常
-            this.curVideoIns.exitFullScreen()
             setTimeout(() => {
                 this.curVideoId=0
-                this.curVideoIns=null
             }, 200);
+        },
+
+        //时长变化
+        handleTimeUpdate(e){
+            // console.log(this.curVideoId,e.detail.currentTime);
+            this.curVideoTime=e.detail.currentTime
+        },
+
+        handleVideoPause(){
+            // console.log(`视频 pause---${this.videoRecordId}----${this.curVideoTime}`);
+            this.handleUpdateVideoPlayTime()
+        },
+
+        // 更新播放时长
+        handleUpdateVideoPlayTime(){
+            if(!this.videoRecordId) return
+            apiViewLogUpdate({
+                id:this.videoRecordId,
+                stop_seconds:parseInt(this.curVideoTime),
+                source:4
+            }).then(res=>{
+                console.log('更新播放时长成功');
+            })
         }
     },
 }
@@ -177,7 +229,7 @@ page{
             padding: 30rpx 34rpx;
             position: relative;
             .title-box{
-                padding-right: 40rpx;
+                margin-right: 110rpx;
             }
             .share-btn{
                 position: absolute;
@@ -196,6 +248,9 @@ page{
                 width: 32.5rpx;
                 height: 32rpx;
             }
+            .collect-btn{
+                right: 96rpx;
+            }
             .tag{
                 color: #E4B478;
                 background-color: #333;
@@ -215,30 +270,10 @@ page{
                 color: #000;
                 vertical-align: middle;
             }
-            video{
-                width: 100%;
-                height: 400rpx;
-                margin: 30rpx 0 20rpx 0;
-                border-radius: 20rpx;
-            }
-            .poster{
+            .video-content{
                 width: 100%;
                 height: 400rpx;
                 margin: 30rpx 0 20rpx 0;
-                border-radius: 20rpx;
-                position: relative;
-                &::after{
-                    content:'';
-                    display: block;
-                    position: absolute;
-                    width: 120rpx;
-                    height: 120rpx;
-                    top: 50%;
-                    left: 50%;
-                    transform: translate(-50%,-50%);
-                    background-image: url('@/static/video-play-btn.png');
-                    background-size: cover;
-                }
             }
             .time{
                 font-size: 28rpx;

+ 3 - 11
pages-sandTable/sandTable.vue

@@ -244,16 +244,7 @@
 		},
 		onReachBottom() {
 			if(this.isRequseting) return 
-			if(this.list.length>=this.total && this.total!=0){
-				// if(this.haveShowToast) return
-				// // 只显示一次
-				// this.haveShowToast = true
-				// uni.showToast({
-				// 	title:"没有了~",
-				// 	icon:'none'
-				// })
-				return
-			}
+			if(this.list.length>=this.total && this.total!=0) return
 			this.sandTableQuery.curr_page++
 			this.getSandBoxList()
 		},
@@ -409,6 +400,7 @@
 							uni.navigateTo({url:'/pages-applyPermission/applyResult'})
 						})
 					}else{
+						this.haveGoToResult=true
 						uni.navigateTo({ url: '/pages-applyPermission/applyPermission?source=7&from_page=沙盘推演' })
 					}
 				}
@@ -479,7 +471,7 @@
 							current:index,
 							showmenu:false
 						})
-					},10)
+					},20)
 				})
 			},
 			// 生成海报

+ 315 - 0
pages-user/myCollect.vue

@@ -0,0 +1,315 @@
+<template>
+    <view class="my-collect-page">
+        <view :class="['top-wrap',!(!isSearchRes&&!keywords)?'top-wrap-ptb':'']">
+            <searchBox placeholder="搜索" @change="onChange" @search="onSearch" />
+            <view class="tab-box" v-show="!isSearchRes&&!keywords">
+                <text 
+                    :class="['tab-item',active==item.val?'tab-active':'']" 
+                    v-for="item in opts" 
+                    :key="item.val"
+                    @click="handleChangeOpt(item.val)"
+                >{{item.name}}</text>
+            </view>
+        </view>
+        <view class="list-wrap">
+            <view class="item" v-for="(item,index) in list" :key="item.CollectionId">
+                <view class="c-time">{{item.CreateTime|formatCTime}}</view>
+                <van-swipe-cell :right-width="90">
+                    <!-- 视频类别样式 -->
+                    <view class="flex video-box" v-if="[2,3].includes(item.CollectionType)" @click="goDetail(item)">
+                        <image class="img" :src="item.ImgUrl" mode="aspectFill" lazy-load="true"/>
+                        <view class="con">
+                            <view class="title" v-html="item.Title"></view>
+                            <view class="author">{{item.Author}}</view>
+                            <view class="time">发布时间:{{item.PublishTime}}</view>
+                        </view>
+                    </view>
+                    <!-- 报告类型样式 -->
+                    <view class="report-box" v-if="item.CollectionType==1" @click="goDetail(item)">
+                        <view class="title" v-html="item.Title"></view>
+                        <view class="con">
+                            <text v-if="item.ClassifyName">#{{item.ClassifyName}}</text>
+                            <text v-if="item.ClassifySecondName" style="margin-left:20rpx">#{{item.ClassifySecondName}}</text>
+                            <view class="time">发布时间:{{item.PublishTime}}</view>
+                        </view>
+                    </view>
+                    <view slot="right" class="cancel-btn" @click="handleCancel(item,index)">取消收藏</view>
+                </van-swipe-cell>
+            </view>
+              
+        </view>
+        <view class="report-empty-box" v-if="finished&&list.length==0">
+            <image :src="globalImgUrls.chartEmpty" mode="widthFix" />
+            <view>暂无相关收藏内容</view>
+        </view>
+        
+        <van-dialog id="van-dialog" />
+    </view>
+</template>
+
+<script>
+import searchBox from "@/components/searchBox/searchBox.vue";
+import {apiMyCollectList,apiCancelCollect} from '@/api/user'
+const moment=require('@/utils/moment-with-locales.min')
+export default {
+    components: {
+        searchBox
+    },
+    filters: {
+        formatCTime(e){
+            if(moment().isSame(e,'year')){//当年
+                return moment(e).format('MM-DD')
+            }else{
+                return moment(e).format('YYYY-MM-DD')
+            }
+        }
+    },
+    data() {
+        return {
+            opts:[
+                {
+                    name:'全部',
+                    val:0,
+                },
+                {
+                    name:'研报',
+                    val:1,
+                },
+                {
+                    name:'线上路演',
+                    val:3,
+                },
+                {
+                    name:'视频社区',
+                    val:2,
+                },
+            ],
+            active:0,
+
+            page:1,
+            pageSize:20,
+            finished:false,
+            list:[],
+            keywords:'',
+            isSearchRes:false
+        }
+    },
+    onLoad(){
+        this.getList()
+    },
+    onPullDownRefresh() {
+        this.keywords=''
+        this.page=1
+        this.list=[]
+        this.finished=false
+        this.isSearchRes=false
+        this.getList()
+        setTimeout(() => {
+            uni.stopPullDownRefresh()
+        }, 1500);
+    },
+    onReachBottom() {
+        if(this.finished) return
+        this.page++
+        this.getList()
+    },
+    methods: {
+        onChange(e){
+            this.keywords=e
+            this.finished=false
+            this.list=[]
+        },
+
+        onSearch(){
+            this.active=0
+            this.page=1
+            this.finished=false
+            this.list=[]
+            if(this.keywords){
+                this.isSearchRes=true
+            }else{
+                this.isSearchRes=false
+            }
+            
+            this.getList()
+        },
+
+        handleChangeOpt(e){
+            this.active=e
+            this.page=1
+            this.finished=false
+            this.list=[]
+            this.keywords=''
+            this.isSearchRes=false
+            this.getList()
+        },
+
+        async getList(){
+            const res=await apiMyCollectList({
+                curr_page:this.page,
+                page_size:this.pageSize,
+                keywords:this.keywords,
+                from_type:this.active
+            })
+            if(res.code===200){
+                const arr=res.data.list
+                this.list=[...this.list,...arr]
+                this.finished=res.data.paging.is_end
+            }
+        },
+
+        handleCancel(item,index){
+            this.$dialog.confirm({
+                title:'',
+                message: '确认取消收藏?',
+                confirmButtonText:'确定'
+            }).then(()=>{
+                apiCancelCollect({collection_id:Number(item.CollectionId)}).then(res=>{
+                    if(res.code===200){
+                        uni.showToast({
+                            title:'操作成功',
+                            icon:'none'
+                        })
+                        this.list.splice(index,1)
+                    }
+                })
+            }).catch(()=>{})
+        },
+
+        goDetail(item){
+            if(item.CollectionType==1){// 报告
+                if(item.ExtendId>0){
+                    uni.navigateTo({url: `/pages-report/chapterDetail?chapterId=${item.ExtendId}`})
+                }else{
+                    uni.navigateTo({url:'/pages-report/reportDetail?reportId='+item.PrimaryId})
+                }
+            }else if(item.CollectionType==2){//视频社区
+                //跳转tabbar不允许带参数 所以用relaunch
+                uni.reLaunch({url:'/pages/video/videoList?videoId='+item.PrimaryId})
+            }else if(item.CollectionType==3){//路演视频
+                uni.reLaunch({url:'/pages/roadShow/video/list?videoId='+item.PrimaryId})
+            }
+        }
+
+    },
+}
+</script>
+<style lang="scss">
+page{
+    padding-bottom: constant(safe-area-inset-bottom);
+    padding-bottom: env(safe-area-inset-bottom);
+}
+</style>
+
+<style lang="scss" scoped>
+.top-wrap{
+    position: sticky;
+    top: 0;
+    left: 0;
+    right: 0;
+    z-index: 50;
+    background-color: #fff;
+    padding: 40rpx 34rpx 0 34rpx;
+    box-shadow: 0px 4rpx 4rpx 0px rgba(198,198,198,0.25);
+    &.top-wrap-ptb{
+        box-shadow: none;
+        padding-bottom: 20rpx;
+    }
+    .tab-box{
+        padding-top: 40rpx;
+        padding-bottom: 10rpx;
+        .tab-item{
+            display: inline-block;
+            margin-right: 60rpx;
+            color: #666;
+            font-size: 32rpx;
+        }
+        .tab-active{
+            color: #333;
+            position: relative;
+            &::after{
+                position: absolute;
+                content: '';
+                display: block;
+                width: 36rpx;
+                height: 6rpx;
+                background: #E3B377;
+                border-radius: 3rpx;
+                bottom: -10rpx;
+                left: 50%;
+                transform: translateX(-50%);
+            }
+        }
+    }
+}
+.list-wrap{
+    padding: 34rpx;
+    .item{
+        padding: 30rpx 0;
+        border-bottom: 1px solid #E5E5E5;
+        .c-time{
+            display: inline-block;
+            font-size: 28rpx;
+            padding: 5rpx 10rpx;
+            color: #666;
+            background-color: #f6f6f6;
+            border-radius: 3rpx;
+            margin-bottom: 12rpx;
+        }
+        .video-box{
+            .img{
+                width: 221rpx;
+                height: 192rpx;
+                flex-shrink: 0;
+                border-radius: 4rpx;
+                margin-right: 20rpx;
+            }
+            .con{
+                flex: 1;
+            }
+            .title{
+                font-size: 32rpx;
+                color: #000;
+                min-height: 80rpx;
+            }
+            .author{
+                color: #666;
+                min-height: 40rpx;
+                margin: 10rpx 0 20rpx 0;
+            }
+            .time{
+                color: #666;
+            }
+        }
+
+        .report-box{
+            .title{
+                line-height: 1.7;
+                margin: 12rpx 0;
+            }
+            .con{
+                text{
+                    display: inline-block;
+                    color: #666;
+                }
+                .time{
+                    float: right;
+                }
+            }
+        }
+
+        .cancel-btn{
+            position: absolute;
+            top: 50%;
+            transform: translateY(-50%);
+            background: #F3A52F;
+            border-radius: 25px;
+            color: #fff;
+            font-size: 16px;
+            width: 84px;
+            text-align: center;
+            line-height: 30px;
+        }
+    }
+}
+</style>

+ 1 - 0
pages-voice/myVoice.vue

@@ -338,6 +338,7 @@ export default {
             })
             if(res.code===200){
                 console.log('上报音频播放记录');
+                this.$store.commit('audio/addAudioRecordId',{recordId:res.data,source:2})
             }
         }
     },

+ 19 - 1
pages-voice/voiceDetail.vue

@@ -22,6 +22,20 @@
         </view>
         <image class="del-btn" src="@/static/voice/del.png" mode="widthFix" @click="handleDel" v-if="info.IsAuthor"/>
         <image class="publish-btn" src="@/static/voice/publish.png" mode="widthFix" @click="handleSendMsg" v-if="info.CouldSendMsg"/>
+        <sharePoster 
+            :showSlot="true"
+            :shareData="{
+                type:'voice_detail',
+                code_page:'pages-voice/voiceDetail',
+                code_scene:JSON.stringify({voiceId:info.BroadcastId}),
+                data:{
+                    title:info.BroadcastName,
+                    img:info.ImgUrl
+                }
+            }"
+        >
+            <image style="width:34rpx;height:34rpx;float: right;" src="@/static/voice/creat-poster-icon.png" mode="aspectFill" />
+        </sharePoster>
 
         <!-- 图片部分 -->
         <view class="imgs-box">
@@ -61,12 +75,14 @@ import {apiGetSceneToParams} from '@/api/common'
 import noAuth from '@/pages/voice/components/noAuth.vue'
 import audioBox from '@/components/audioBox/audioBox.vue'
 import dragButton from '@/components/dragButton/dragButton.vue'
+import sharePoster from '@/components/sharePoster/sharePoster.vue'
 const dayjs=require('@/utils/dayjs.min')
 export default {
     components:{
         noAuth,
         audioBox,
-        audioBox
+        dragButton,
+        sharePoster
     },
     computed:{
         showAudioPop(){//是否显示音频弹窗
@@ -201,6 +217,7 @@ export default {
             })
             if(res.code===200){
                 console.log('上报音频播放记录');
+                this.$store.commit('audio/addAudioRecordId',{recordId:res.data,source:2})
             }
         },
 
@@ -305,6 +322,7 @@ export default {
             float: right;
             width: 36rpx;
             height: 36rpx;
+            margin-left: 40rpx;
         }
         .imgs-box{
             margin-top: 120rpx;

+ 34 - 12
pages.json

@@ -79,6 +79,13 @@
 				"navigationBarTitleText": "语音播报",
 				"enablePullDownRefresh": true
 			}
+		},
+		{
+			"path":"pages/roadShow/video/list",
+			"style": {
+				"navigationBarTitleText": "线上路演",
+				"enablePullDownRefresh": true
+			}
 		}
 	],
 	"subPackages":[
@@ -147,13 +154,20 @@
 						"enablePullDownRefresh": true
 					}
 				},
-			   {
-			   	"path": "mysetting",
-			   	"style":{
-			   		"navigationBarTitleText": "我的设置"
-			   	}
-			   }
-      ]
+			   	{
+					"path": "mysetting",
+					"style":{
+						"navigationBarTitleText": "我的设置"
+					}
+				},
+				{
+					"path": "myCollect",
+					"style":{
+						"navigationBarTitleText": "我的收藏",
+						"enablePullDownRefresh": true
+					}
+				}
+      		]
 		},
 		// 图库模块
 		{
@@ -245,6 +259,13 @@
 					"style":{
 						"navigationStyle": "custom"
 					}
+				},
+				//按用户有权限品种分的报告列表页
+				{
+					"path": "reportForVariety/list",
+					"style":{
+						"enablePullDownRefresh": true
+					}
 				}
 			]
 		},
@@ -344,10 +365,10 @@
 				"selectedIconPath": "./static/tabbar/report-s.png"
 			},
 			{
-				"pagePath": "pages/pricedriven/pricedriven",
-				"text": "价格驱动",
-				"iconPath": "./static/tabbar/price.png",
-				"selectedIconPath": "./static/tabbar/price-s.png"
+				"pagePath": "pages/roadShow/video/list",
+				"text": "线上路演",
+				"iconPath": "./static/tabbar/roadShow.png",
+				"selectedIconPath": "./static/tabbar/roadShow-s.png"
 			},
 			{
 				"pagePath": "pages/video/videoList",
@@ -402,7 +423,8 @@
 			"van-dialog": "/wxcomponents/vant/dialog/index",
 			"van-cell": "/wxcomponents/vant/cell/index",
 			"van-tree-select": "/wxcomponents/vant/tree-select/index",
-			"van-datetime-picker": "/wxcomponents/vant/datetime-picker/index"
+			"van-datetime-picker": "/wxcomponents/vant/datetime-picker/index",
+			"van-swipe-cell": "/wxcomponents/vant/swipe-cell/index"
 		}
 	}
 }

+ 1 - 1
pages/login.vue

@@ -26,7 +26,7 @@
                         </view>
                     </picker>
                 </template>
-                <button slot="button" class="tel-btn" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">获取微信手机号</button>
+                <!-- <button slot="button" class="tel-btn" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">获取微信手机号</button> -->
             </van-field>
             <van-field
                 :value="verifyCode"

+ 15 - 2
pages/pc.vue

@@ -21,7 +21,9 @@ const mapObj=new Map([
 	['pages-sandTable/sandTable','/sandBox/list'],
     ['pages/voice/voice','/voice/list'],
     ['pages-voice/voiceDetail','/voice/detail'],
-    ['pages-roadShow/video/list','/roadshow/video/list']
+    ['pages-roadShow/video/list','/roadshow/video/list'],
+    ['pages/roadShow/video/list','/roadshow/video/list'],
+    ['pages-report/reportForVariety/list','/report/varietyreportlist']
 ])//map映射小程序页面路径对应h5页面路径
 import {apiUserInfo} from '@/api/user'
 import {apiGetSceneToParams} from '@/api/common'
@@ -109,7 +111,18 @@ export default {
                 }
             }
             console.log('拼接字符串:',paramsObjStr);
-            this.url=`${pcBaseUrl}${mapObj.get(decodeURIComponent(options.xcxPath))||'/'}?${paramsObjStr}#wechat_redirect`
+			uni.getSystemInfo({
+					success: (data) => {
+						// 企业微信会额外返回一个 environment 字段 值为 wxwork 在企业微信PC版中,一旦后缀带上#wechat_redirect ,就打不开,不知道为何,社区也没有找到什么结果
+						this.url=`${pcBaseUrl}${mapObj.get(decodeURIComponent(options.xcxPath))||'/'}?${paramsObjStr}${data.environment=='wxwork'?'':'#wechat_redirect'}`
+                        // console.log(`${pcBaseUrl}${mapObj.get(decodeURIComponent(options.xcxPath))||'/'}?${paramsObjStr}${data.environment=='wxwork'?'':'#wechat_redirect'}`);
+					},
+					fail: (err) => {
+						this.url=`${pcBaseUrl}${mapObj.get(decodeURIComponent(options.xcxPath))||'/'}?${paramsObjStr}#wechat_redirect`
+						console.log(err);
+					}
+			})
+            
         }
     },
 

+ 4 - 3
pages/question/question.vue

@@ -150,6 +150,7 @@
 			title="问答评论"
 			@close="closeCommentHandle"
 			@clickOverlay="isShowComment=false"
+			z-index="99999"
 		>
 			<view class="comment-cont" @touchmove.stop>
 			   <view class="commment-top">
@@ -184,7 +185,7 @@
                   :show-confirm-bar="false"
                   :cursor-spacing="20"
                   class="write-ipt"
-                  @blur="setWritePosition(50)"
+                  @blur="setWritePosition(0)"
 					@focus="checkNickHandle"
                />
 				  <view class="confirm-btn" @click="publishMessageHandle">发布</view>
@@ -242,7 +243,7 @@ export default {
 			
 			isShowComment: false,
 			comment_cont: '',
-			writeBottom: 50,
+			writeBottom: 0,
 			select_comment_type:1,//默认全部
 			select_question_item: {},
 			comment_obj: {
@@ -439,7 +440,7 @@ export default {
       
       setWritePosition(val=50) {
          console.log(val)
-         this.writeBottom = val < 50 ? 50 : val;
+         this.writeBottom = val < 50 ? 0 : val;
       },
 	  
       

+ 2 - 2
pages/report/report.vue

@@ -120,9 +120,9 @@ export default {
       tabPathMap: new Map([
         ['report','/pages-report/classify'],
         ['chart','/pages/chart/chart'],
-        ['road','/pages-roadShow/video/list'],
         ['sandbox','/pages-sandTable/sandTable'],
-        ['activity','/pages/activity/activity']
+        ['activity','/pages/activity/activity'],
+        ['pricedriven','/pages/pricedriven/pricedriven']
       ]),
       tabCards: []
     }

+ 99 - 0
pages/roadShow/video/components/noAuth.vue

@@ -0,0 +1,99 @@
+<template>
+  <view class="voice-no-auth">
+        <image class="img" :src="globalImgUrls.activityNoAuth" mode="widthFix"></image>
+		<view style="margin-bottom:15px">您暂无权限查看线上路演</view>
+		<view v-if="info.type==='contact'" style="margin-bottom:15px">若想查看可以联系对口销售</view>
+		<view v-else style="margin-bottom:15px">若想查看可以申请开通</view>
+		<view v-if="info.type==='contact'">
+			{{info.name||''}}:<text @click="handleCall" style="color:#E3B377">{{info.mobile||''}}</text>
+		</view>
+		<view class="global-btn-yellow-change btn" @click="handleApply" v-else style="margin-top:30px">立即申请</view>
+  </view>
+</template>
+
+<script>
+import {apiApplyPermission} from '@/api/user'
+export default {    
+    props: {
+        info:null
+    },
+    watch:{
+        info(){
+            this.handleAutoApply()
+        }
+    },
+    
+    methods: {
+        handleCall(){
+
+            uni.makePhoneCall({
+                phoneNumber: this.info.mobile,
+                success: (result) => {},
+                fail: (error) => {}
+            })
+        },
+
+        handleAutoApply(){
+            if(this.info.type=='contact'&&!this.info.customer_info.has_apply){
+                if(this.info.customer_info.status=='冻结'||(this.info.customer_info.status=='试用'&&this.info.customer_info.is_suspend==1)){
+                    apiApplyPermission({
+                        company_name:this.info.customer_info.company_name,
+                        real_name:this.info.customer_info.name,
+                        source:10,
+                        from_page:'线上路演'
+                    }).then(res=>{
+                        if(res.code===200){
+                            console.log('主动申请成功');
+                        }
+                    }) 
+                }
+            }
+        },
+
+        async handleApply(){
+            await this.checkUserIsBind()
+            const {customer_info}=this.info
+            if(customer_info.has_apply){
+                uni.showToast({
+                  title:'您已提交过申请,请耐心等待',
+                  icon:'none'
+                })
+            }else{
+                if (!customer_info.status || customer_info.status != '流失') {
+                    uni.navigateTo({
+                        url: "/pages-applyPermission/applyPermission?source=10&from_page=线上路演"
+                    })
+                }else{
+                    apiApplyPermission({
+                        company_name:customer_info.company_name,
+                        real_name:customer_info.name,
+                        source:10,
+                        from_page:'线上路演'
+                    }).then(res=>{
+                        uni.navigateTo({url:'/pages-applyPermission/applyResult'})
+                    })
+                }
+            }
+        }
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+.voice-no-auth{
+    padding: 34rpx;
+    text-align: center;
+    font-size: $global-font-size-lg;
+    .img{
+        width: 100%;
+        margin-bottom: 50rpx;
+    }
+    .btn{
+        width: 380rpx;
+        line-height: 70rpx;
+        margin-left: auto;
+        margin-right: auto;
+        margin-top: 40rpx;
+    }
+}
+</style>

+ 495 - 0
pages/roadShow/video/list.vue

@@ -0,0 +1,495 @@
+<template>
+    <view class="video-list-page" v-if="isAuth">
+        <van-sticky style="background: #fff">
+            <view class="flex search-wrap">
+                <view @click="goSearchPage" style="flex:1;margin-right:30rpx" >
+                    <searchBox 
+                        placeholder="关键字搜索" 
+                        :hasRightBtn="false" 
+                        :disabled="true"
+                    ></searchBox>
+                </view>
+                <view class="flex" @click="showFilter=true">
+                    <image style="width:50rpx;height:50rpx" src="@/static/filter-icon.png" mode="aspectFill"/>
+                    <text style="color:#E3B377;font-size:32rpx">筛选</text>
+                </view>
+            </view>
+        </van-sticky>
+        <view class="empty-box" v-if="list.length==0&&finished">
+            <image
+                :src="globalImgUrls.activityNoAuth"
+                mode="widthFix"
+            />
+            <view v-if="videoId!=0&&noShareData">
+                <view>暂无权限查看该视频</view>
+                <view>请刷新页面后重试</view>
+            </view>
+            <view v-else-if="videoId!=0&&!noShareData">
+                <view>该视频不存在</view>
+                <view>请刷新页面后重试</view>
+            </view>
+            <view v-else>暂无数据</view>
+        </view>
+        <view class="list-wrap">
+            <view class="item" v-for="item in list" :key="item.road_video_id">
+                <view class="title-box">
+                    <text class="tag">{{item.chart_permission_name}}</text>
+                    <text class="title">{{item.title}}</text>
+                </view>
+                <collectBox
+                    :type="3"
+                    :primaryId="item.road_video_id"
+                    :collectId="item.collection_id"
+                    class="share-btn collect-btn"
+                />
+                <button 
+                    class="share-btn" 
+                    open-type="share" 
+                    :data-item="item">
+                    <image class="share-img" src="@/static/share-icon.png" mode="aspectFill"/>
+                </button>
+                <view style="padding-top:20rpx">
+                    <view class="time">发布时间:{{item.publish_time}}</view>
+                    <view class="user-name">{{item.admin_real_name}}</view>
+                </view>
+                <view class="video-content">
+                    <videoBox 
+                        :videoInfo="getDanmuData(item)"
+                        :curVideoId="curVideoId"
+                        :showDanmu="showDanmu"
+                        @videoPlay="handelClickPlay"
+                        @ended="handleVideoEnd"
+                        @pause="handleVideoPause"
+                        @timeupdate="handleTimeUpdate"
+                    />
+                </view>
+                <comment :showDanmu="showDanmu" :videoInfo="getCommentData(item)"></comment>
+            </view>
+        </view>
+
+        <!-- 筛选 -->
+        <van-popup 
+            :show="showFilter" 
+            position="bottom" 
+            :safe-area-inset-bottom="true" 
+            round 
+            @close="showFilter=false"
+        >
+            <view class="filter-wrap" @touchmove.stop>
+                <view class="flex top">
+                    <text style="color:#000">全部筛选</text>
+                    <text style="color:#E3B377" @click="showFilter=false">取消</text>
+                </view>
+                <view class="list-box">
+                    <van-collapse accordion @change="change" :value="active" :border="false">
+                        <van-collapse-item 
+                            :title="item.ClassifyName" 
+                            :name='item.ClassifyName' 
+                            :border="false"
+                            v-for="item in options"
+                            :key="item.ClassifyName"
+                        >
+                            <van-row gutter="5">
+                                <van-col 
+                                    :span="_item.PermissionName.length>7?16:8" 
+                                    v-for="_item in item.Items" 
+                                    :key="_item.PermissionId"
+                                >
+                                    <text 
+                                        :class="['list-item',_item.PermissionId==selectPerId&&'list-item-active']" 
+                                        @click="handleSelectPerItem(_item)"
+                                    >{{_item.PermissionName}}</text>
+                                </van-col>
+                            </van-row>
+                        </van-collapse-item>
+                    </van-collapse>
+                </view>
+            </view>
+        </van-popup>
+
+        <!-- 跳转去提问悬浮按钮 -->
+        <dragButton :existTabBar="true">
+            <navigator url="/pages-question/hasQuestion">
+                <view class="to-question-fixed-box">
+                    <image src="@/static/toquestion-icon.png" mode="widthFix" />
+                    <text>我要提问</text>
+                </view>
+            </navigator>
+        </dragButton>
+    </view>
+    <noAuth :info="noAuthData" v-else/>
+</template>
+<script>
+import {apiRoadShowVideoList,apiRoadShowVideoPlayLog} from '@/api/roadShow'
+import {apiGetSceneToParams,apiUserBindPermission,apiViewLogUpdate} from '@/api/common'
+import noAuth from './components/noAuth.vue'
+import dragButton from '@/components/dragButton/dragButton.vue'
+import comment from '@/components/videoComment/comment.vue'
+import collectBox from '@/components/collectBox/collectBox.vue'
+import videoBox from '@/components/videoBox/videoBox.vue'
+export default {
+    components:{
+        noAuth,
+        dragButton,
+        comment,
+        collectBox,
+        videoBox
+    },
+    data() {
+        return {
+            showFilter:false,
+            active:'',
+            options:[],
+            selectPerId:0,
+
+            videoId:0,
+            page:1,
+            pageSize:10,
+            finished:false,
+            list:[],
+
+            curVideoId:0,
+            curVideoTime:0,
+            videoRecordId:0,
+
+            isAuth:true,
+            noAuthData:null,
+
+            noShareData:false,//用户从分享进入没有该分享的视频的权限
+
+            showDanmu:true,//控制整个模块是否显示弹幕功能(没用了本来后台有个开关功能的 后来不要了 但是还是留着吧)
+        }
+    },
+    onLoad(options){
+        this.init(options)
+        this.getPermissionList()
+    },
+    onShow(){
+        //无权限时刷新列表
+        if(!this.isAuth){
+            this.getList()
+        }
+    },
+    onHide(){
+        this.showFilter=false
+        // this.curVideoId=0
+    },
+    onShareAppMessage({from,target}) {
+        console.log(from,target);
+        let path='/pages/roadShow/video/list?videoId=0'
+        let title='FICC线上路演'
+        let imageUrl=''
+        if(from=='button'){
+            title=target.dataset.item.title
+            path=`/pages/roadShow/video/list?videoId=${target.dataset.item.road_video_id}`
+            imageUrl=target.dataset.item.cover_img_url
+        }
+        return {
+            title:title,
+            path:path,
+            imageUrl:imageUrl
+        }
+    },
+    onPullDownRefresh(){
+        this.videoId=0
+        this.noShareData=false
+        this.selectPerId=0
+        this.page=1
+        this.list=[]
+        this.finished=false
+        this.getList()
+        setTimeout(() => {
+            uni.stopPullDownRefresh()
+        }, 1500)
+    },
+    onReachBottom() {
+        if(this.finished) return
+        this.page++
+        this.getList()
+    },
+    methods: {
+        // 处理弹幕模块需要的数据
+        getDanmuData(item){
+            return {
+                source:2,
+                id:item.road_video_id,
+                ...item
+            }
+        },
+        // 处理评论模块需要的数据
+        getCommentData(item){
+            return {
+                source:3,
+                id:item.road_video_id,
+                ...item
+            }
+        },
+        async init(options){
+            if(options.scene){
+                const resScene=await apiGetSceneToParams({scene_key:options.scene})
+                if(resScene.code===200){
+                    const obj=JSON.parse(resScene.data)
+                    this.videoId=obj.videoId||0
+                }
+            }else{
+                this.videoId=options.videoId||0
+            }
+            this.getList()
+        },
+
+        goSearchPage(){
+            uni.navigateTo({
+                url: '/pages-roadShow/video/search',
+            });
+        },
+
+        change(e){
+            this.active=e.detail
+        },
+
+        //点击分类某项
+        handleSelectPerItem(item){
+            if(this.selectPerId==item.PermissionId){
+                this.selectPerId=0
+            }else{
+                this.selectPerId=item.PermissionId
+            }
+            
+            this.videoId=0//重置掉分享进入的状态
+            this.noShareData=false
+            this.curVideoId=0
+            this.page=1
+            this.list=[]
+            this.finished=false
+            this.getList()
+            this.showFilter=false
+        },
+
+        async getList(){
+            const res=await apiRoadShowVideoList({
+                page_index:Number(this.page),
+                page_size:Number(this.pageSize),
+                video_id:Number(this.videoId),
+                chart_permission_id:Number(this.selectPerId)
+            })
+            if(res.code===200){
+                let arr=res.data.list||[]
+                this.list=[...this.list,...arr]
+                if(res.data.paging.is_end){
+                    this.finished=true
+                }
+                this.isAuth=true
+            }else if(res.code===403){
+                //无权限用户
+                this.isAuth=false
+                this.noAuthData=res.data
+            }else if(res.code===4001){
+                // 用户从分享进入没有这个视频的权限
+                this.noShareData=true
+                this.finished=true
+            }
+        },
+
+        //获取筛选项
+        async getPermissionList(){
+            const res=await apiUserBindPermission()
+            if(res.code===200){
+                const result = res.data.permission_list||[];
+                this.options = result.map(item=>{
+                    let obj = {};
+                    obj.ClassifyName = item.classify_name;
+                    obj.Items = item.list.map(_item=>{
+                        return {PermissionId:_item.chart_permission_id,PermissionName:_item.chart_permission_name};
+                    })
+                    return obj;
+                })
+            }
+        },
+
+        handelClickPlay(item){
+            this.curVideoId=item.road_video_id
+            // 记录播放
+            apiRoadShowVideoPlayLog({video_id:Number(item.road_video_id)}).then(res=>{
+                if(res.code===200){
+                    console.log('视频埋点成功');
+                    this.videoRecordId=res.data
+                }
+            })
+        },
+
+        //视频播放结束
+        handleVideoEnd(){
+            setTimeout(() => {
+                this.curVideoId=0
+            }, 200);
+        },
+
+        //时长变化
+        handleTimeUpdate(e){
+            // console.log(this.curVideoId,e.detail.currentTime);
+            this.curVideoTime=e.detail.currentTime
+        },
+
+        handleVideoPause(){
+            // console.log(`视频 pause---${this.videoRecordId}----${this.curVideoTime}`);
+            this.handleUpdateVideoPlayTime()
+        },
+
+        // 更新播放时长
+        handleUpdateVideoPlayTime(){
+            if(!this.videoRecordId) return
+            apiViewLogUpdate({
+                id:this.videoRecordId,
+                stop_seconds:parseInt(this.curVideoTime),
+                source:4
+            }).then(res=>{
+                console.log('更新播放时长成功');
+            })
+        }
+    },
+}
+</script>
+
+<style lang='scss'>
+.search-wrap .van-search{
+    padding: 0 !important;
+}
+
+.video-list-page{
+    .filter-wrap{
+        .van-cell__title, .van-cell__value{
+            flex: none !important;
+        }
+        .van-cell:after{
+            border: none !important;
+        }
+        .van-cell__title{
+            font-size: 14px;
+        }
+        .van-hairline--top:after{
+            border-top-width: 0 !important;
+        }
+    }
+}
+</style>
+<style lang="scss" scoped>
+.video-list-page{
+    .search-wrap {
+        background-color: #fff;
+        padding: 30rpx 34rpx;
+        align-items: center;
+        .menu-icon{
+            width: 52rpx;
+            height: 40rpx;
+            display: block;
+            flex-shrink: 0;
+            margin-left: 30rpx;
+        }
+    } 
+    
+    .list-wrap{
+        .item{
+            border-top: 10rpx solid #f9f9f9;
+            padding: 30rpx 34rpx;
+            position: relative;
+            .title-box{
+                margin-right: 110rpx;
+            }
+            .share-btn{
+                position: absolute;
+                top: 34rpx;
+                right: 34rpx;
+                background-color: transparent;
+                width: 36rpx;
+                height: 36rpx;
+                line-height: 1;
+                padding: 0;
+                &::after{
+                    border: none;
+                }
+            }
+            .share-img{
+                width: 32.5rpx;
+                height: 32rpx;
+            }
+            .collect-btn{
+                right: 96rpx;
+            }
+            .tag{
+                color: #E4B478;
+                background-color: #333;
+                padding: 5rpx 20rpx;
+                border-radius: 20rpx;
+                font-size: 24rpx;
+                margin-right: 26rpx;
+                max-width: 250rpx;
+                overflow: hidden;
+                text-overflow: ellipsis;
+                white-space: nowrap;
+                display: inline-block;
+                vertical-align: middle;
+            }
+            .title{
+                font-size: 32rpx;
+                color: #000;
+                vertical-align: middle;
+            }
+            .video-content{
+                width: 100%;
+                height: 400rpx;
+                margin: 30rpx 0 20rpx 0;
+            }
+            .time{
+                font-size: 28rpx;
+                color: #999;
+                display: inline-block;
+            }
+            .user-name{
+                float: right;
+                font-size: 28rpx;
+                color: #999;
+            }
+        }
+    }
+
+    .empty-box{
+        text-align: center;
+        font-size: 32rpx;
+        color: #999;
+        padding-top: 150rpx;
+        image{
+            width: 80vw;
+            margin-bottom: 57rpx;
+        }
+    }
+}
+
+.filter-wrap{
+    background-color: #fff;
+    padding-top: 53rpx;
+    padding-bottom: 100rpx;
+    .top{
+        font-size: 32rpx;
+        justify-content: space-between;
+        margin-bottom: 40rpx;
+        padding: 0 34rpx;
+    }
+    .list-box{
+        min-height: 30vh;
+        max-height: 60vh;
+        .list-item{
+            display: block;
+            margin: 10rpx;
+            height: 76rpx;
+            line-height: 76rpx;
+            color: #000;
+            background: #F6F6F6;
+            border-radius: 4px 4px 4px 4px;
+            text-align: center;
+        }
+        .list-item-active{
+            background-color: #FAEEDE;
+        }
+    }
+}
+</style>

+ 13 - 6
pages/user/user.vue

@@ -47,17 +47,15 @@
 				</block>
 				
 				<view v-else class="right-text look" @click="handleToUserPermission">
-					<text>查看</text>
+					<!-- <text>查看</text> -->
 					<van-icon name="arrow"></van-icon>
 				</view>
 			</view>
 			<view class="flex item-card" >
 				<image src="@/static/message_ico.png" mode="widthFix" />
-				<view class="label flex" style="align-items: center;">消息通知 
-					<text class="unread-ico" v-if="userInfo.un_read">{{userInfo.un_read}}</text> 
-				</view>
+				<view class="label flex" style="align-items: center;">消息通知</view>
 				<view class="right-text look" @click="toMessageHadle">
-					<text>查看</text>
+					<text class="unread-ico" v-if="userInfo.un_read">{{userInfo.un_read}}</text> 
 					<van-icon name="arrow"></van-icon>
 				</view>
 			</view>
@@ -77,7 +75,16 @@
 					<image src="../../static/voice/mine-voice-icon.png" mode="widthFix" />
 					<text class="label">我的语音</text>
 					<view class="right-text look">
-						<text>查看</text>
+						<van-icon name="arrow"></van-icon>
+					</view>
+				</view>
+				<view></view>
+			</navigator>
+			<navigator url="/pages-user/myCollect">
+				<view class="flex item-card">
+					<image src="../../static/collect-user-icon.png" mode="widthFix" />
+					<text class="label">我的收藏</text>
+					<view class="right-text look">
 						<van-icon name="arrow"></van-icon>
 					</view>
 				</view>

+ 76 - 45
pages/video/videoList.vue

@@ -32,25 +32,31 @@
                     <text class="tag">{{item.variety_tag_name}}</text>
                     <text class="title">{{item.title}}</text>
                 </view>
+                <collectBox
+                    :type="2"
+                    :primaryId="item.community_video_id"
+                    :collectId="item.collection_id"
+                    class="share-btn collect-btn"
+                />
                 <button 
                     class="share-btn" 
                     open-type="share" 
                     :data-item="item">
                     <image class="share-img" src="@/static/share-icon.png" mode="aspectFill"/>
                 </button>
-                <video
-                    autoplay
-                    object-fit="contain"
-                    show-mute-btn
-                    :poster="item.cover_img_url"
-                    :src="item.video_url"
-                    enable-play-gesture
-                    :id="item.community_video_id"
-                    @ended="handleVideoEnd"
-                    v-if="item.community_video_id==curVideoId"
-                ></video>
-                <image @click="handelClickPlay(item)" v-else class="poster" :src="item.cover_img_url" mode="aspectFill" lazy-load/>
                 <view class="time">发布时间:{{item.publish_time}}</view>
+                <view class="video-content">
+                    <videoBox 
+                        :videoInfo="getDanmuData(item)"
+                        :curVideoId="curVideoId"
+                        :showDanmu="showDanmu"
+                        @videoPlay="handelClickPlay"
+                        @ended="handleVideoEnd"
+                        @pause="handleVideoPause"
+                        @timeupdate="handleTimeUpdate"
+                    />
+                </view>
+                <comment :showDanmu="showDanmu" :videoInfo="getCommentData(item)"></comment>
             </view>
         </view>
 
@@ -109,13 +115,19 @@
 <script>
 import {apiVideoList,apiVideoPlayLog} from '@/api/video'
 import {apiOptionList} from '@/api/question'
-import {apiGetSceneToParams,apiGetTagTree} from '@/api/common'
+import {apiGetSceneToParams,apiGetTagTree,apiViewLogUpdate} from '@/api/common'
 import noAuth from './components/noAuth.vue'
 import dragButton from '@/components/dragButton/dragButton.vue'
+import comment from '@/components/videoComment/comment.vue'
+import collectBox from '@/components/collectBox/collectBox.vue'
+import videoBox from '@/components/videoBox/videoBox.vue'
 export default {
     components:{
         noAuth,
-        dragButton
+        comment,
+        dragButton,
+        collectBox,
+        videoBox
     },
     data() {
         return {
@@ -131,10 +143,13 @@ export default {
             list:[],
 
             curVideoId:0,
-            curVideoIns:null,
+            curVideoTime:0,
+            videoRecordId:0,
 
             isAuth:true,
             noAuthData:null,
+
+            showDanmu:true,//控制整个模块是否显示弹幕功能(没用了本来后台有个开关功能的 后来不要了 但是还是留着吧)
         }
     },
     onLoad(options){
@@ -149,7 +164,6 @@ export default {
     },
     onHide(){
         this.showFilter=false
-        // this.curVideoId=0
     },
     onShareAppMessage({from,target}) {
         console.log(from,target);
@@ -184,6 +198,22 @@ export default {
         this.getList()
     },
     methods: {
+        // 处理弹幕模块需要的数据
+        getDanmuData(item){
+            return {
+                source:1,
+                id:item.community_video_id,
+                ...item
+            }
+        },
+        // 处理评论模块需要的数据
+        getCommentData(item){
+            return {
+                source:2,
+                id:item.community_video_id,
+                ...item
+            }
+        },
         async init(options){
             if(options.scene){
                 const resScene=await apiGetSceneToParams({scene_key:options.scene})
@@ -267,25 +297,43 @@ export default {
 
         handelClickPlay(item){
             this.curVideoId=item.community_video_id
-            setTimeout(() => {
-                this.curVideoIns=uni.createVideoContext(this.curVideoId.toString())
-            }, 300);
             // 记录播放
             apiVideoPlayLog({video_id:Number(item.community_video_id)}).then(res=>{
                 if(res.code===200){
                     console.log('视频埋点成功');
+                    this.videoRecordId=res.data
                 }
             })
         },
 
         //视频播放结束
         handleVideoEnd(){
-            // 此处因为如果不调用退出全屏方法 安卓和ios页面均会表现异常,安卓横屏不恢复竖屏,ios底部tabbar渲染异常
-            this.curVideoIns.exitFullScreen()
             setTimeout(() => {
                 this.curVideoId=0
-                this.curVideoIns=null
             }, 200);
+        },
+
+         //时长变化
+        handleTimeUpdate(e){
+            // console.log(this.curVideoId,e.detail.currentTime);
+            this.curVideoTime=e.detail.currentTime
+        },
+
+        handleVideoPause(){
+            // console.log(`视频 pause---${this.videoRecordId}----${this.curVideoTime}`);
+            this.handleUpdateVideoPlayTime()
+        },
+
+        // 更新播放时长
+        handleUpdateVideoPlayTime(){
+            if(!this.videoRecordId) return
+            apiViewLogUpdate({
+                id:this.videoRecordId,
+                stop_seconds:parseInt(this.curVideoTime),
+                source:3
+            }).then(res=>{
+                console.log('更新播放时长成功');
+            })
         }
     },
 }
@@ -330,11 +378,10 @@ export default {
     
     .list-wrap{
         .item{
-            border-top: 10rpx solid #f9f9f9;
             padding: 30rpx 34rpx;
             position: relative;
             .title-box{
-                padding-right: 40rpx;
+                margin-right: 110rpx;
             }
             .share-btn{
                 position: absolute;
@@ -353,6 +400,9 @@ export default {
                 width: 32.5rpx;
                 height: 32rpx;
             }
+            .collect-btn{
+                right: 96rpx;
+            }
             .tag{
                 color: #E4B478;
                 background-color: #333;
@@ -365,34 +415,15 @@ export default {
                 font-size: 32rpx;
                 color: #000;
             }
-            video{
+            .video-content{
                 width: 100%;
                 height: 400rpx;
                 margin: 30rpx 0 20rpx 0;
-                border-radius: 20rpx;
-            }
-            .poster{
-                width: 100%;
-                height: 400rpx;
-                margin: 30rpx 0 20rpx 0;
-                border-radius: 20rpx;
-                position: relative;
-                &::after{
-                    content:'';
-                    display: block;
-                    position: absolute;
-                    width: 120rpx;
-                    height: 120rpx;
-                    top: 50%;
-                    left: 50%;
-                    transform: translate(-50%,-50%);
-                    background-image: url('@/static/video-play-btn.png');
-                    background-size: cover;
-                }
             }
             .time{
                 font-size: 28rpx;
                 color: #999;
+                margin-top: 20rpx;
             }
         }
     }

+ 78 - 45
pages/video/videoSearch.vue

@@ -23,25 +23,31 @@
                     <text class="tag">{{item.chart_permission_name}}</text>
                     <text class="title">{{item.title}}</text>
                 </view>
+                <collectBox
+                    :type="2"
+                    :primaryId="item.community_video_id"
+                    :collectId="item.collection_id"
+                    class="share-btn collect-btn"
+                />
                 <button 
                     class="share-btn" 
                     open-type="share" 
                     :data-item="item">
                     <image class="share-img" src="@/static/share-icon.png" mode="aspectFill"/>
                 </button>
-                <video
-                    autoplay
-                    object-fit="contain"
-                    show-mute-btn
-                    :poster="item.cover_img_url"
-                    :src="item.video_url"
-                    enable-play-gesture
-                    :id="item.community_video_id"
-                    @ended="handleVideoEnd"
-                    v-if="item.community_video_id==curVideoId"
-                ></video>
-                <image @click="handelClickPlay(item)" v-else class="poster" :src="item.cover_img_url" mode="aspectFill" lazy-load/>
                 <view class="time">发布时间:{{item.publish_time}}</view>
+                <view class="video-content">
+                    <videoBox 
+                        :videoInfo="getDanmuData(item)"
+                        :curVideoId="curVideoId"
+                        :showDanmu="showDanmu"
+                        @videoPlay="handelClickPlay"
+                        @ended="handleVideoEnd"
+                        @pause="handleVideoPause"
+                        @timeupdate="handleTimeUpdate"
+                    />
+                </view>
+                <comment :showDanmu="showDanmu" :videoInfo="getCommentData(item)"></comment>
             </view>
         </view>
     </view>
@@ -50,9 +56,16 @@
 <script>
 import searchBox from '@/components/searchBox/searchBox.vue'
 import {apiVideoList,apiVideoPlayLog} from '@/api/video'
+import {apiViewLogUpdate} from '@/api/common'
+import comment from '@/components/videoComment/comment.vue'
+import collectBox from '@/components/collectBox/collectBox.vue'
+import videoBox from '@/components/videoBox/videoBox.vue'
 export default {
     components: {
-        searchBox
+        searchBox,
+        comment,
+        collectBox,
+        videoBox
     },
     data() {
         return {
@@ -64,7 +77,10 @@ export default {
             pageSize:10,
 
             curVideoId:0,
-            curVideoIns:null
+            curVideoTime:0,
+            videoRecordId:0,
+
+            showDanmu:true,//控制整个模块是否显示弹幕功能(没用了本来后台有个开关功能的 后来不要了 但是还是留着吧)
         }
     },
     onReachBottom() {
@@ -89,6 +105,22 @@ export default {
         }
     },
     methods: {
+         // 处理弹幕模块需要的数据
+        getDanmuData(item){
+            return {
+                source:1,
+                id:item.community_video_id,
+                ...item
+            }
+        },
+        // 处理评论模块需要的数据
+        getCommentData(item){
+            return {
+                source:2,
+                id:item.community_video_id,
+                ...item
+            }
+        },
         onChange(e){
             this.searchVal=e
         },
@@ -122,25 +154,43 @@ export default {
 
         handelClickPlay(item){
             this.curVideoId=item.community_video_id
-            setTimeout(() => {
-                this.curVideoIns=uni.createVideoContext(this.curVideoId.toString())
-            }, 300);
             // 记录播放
             apiVideoPlayLog({video_id:Number(item.community_video_id)}).then(res=>{
                 if(res.code===200){
                     console.log('视频埋点成功');
+                    this.videoRecordId=res.data
                 }
             })
         },
 
         //视频播放结束
         handleVideoEnd(){
-            // 此处因为如果不调用退出全屏方法 安卓和ios页面均会表现异常,安卓横屏不恢复竖屏,ios底部tabbar渲染异常
-            this.curVideoIns.exitFullScreen()
             setTimeout(() => {
                 this.curVideoId=0
-                this.curVideoIns=null
             }, 200);
+        },
+
+        //时长变化
+        handleTimeUpdate(e){
+            // console.log(this.curVideoId,e.detail.currentTime);
+            this.curVideoTime=e.detail.currentTime
+        },
+
+        handleVideoPause(){
+            // console.log(`视频 pause---${this.videoRecordId}----${this.curVideoTime}`);
+            this.handleUpdateVideoPlayTime()
+        },
+
+        // 更新播放时长
+        handleUpdateVideoPlayTime(){
+            if(!this.videoRecordId) return
+            apiViewLogUpdate({
+                id:this.videoRecordId,
+                stop_seconds:parseInt(this.curVideoTime),
+                source:3
+            }).then(res=>{
+                console.log('更新播放时长成功');
+            })
         }
     },
 }
@@ -172,19 +222,18 @@ page{
     
     .list-wrap{
         .item{
-            border-top: 10rpx solid #f9f9f9;
             padding: 30rpx 34rpx;
             position: relative;
             .title-box{
-                padding-right: 40rpx;
+                margin-right: 110rpx;
             }
             .share-btn{
                 position: absolute;
                 top: 34rpx;
                 right: 34rpx;
                 background-color: transparent;
-                width: 32rpx;
-                height: 32rpx;
+                width: 36rpx;
+                height: 36rpx;
                 line-height: 1;
                 padding: 0;
                 &::after{
@@ -195,6 +244,9 @@ page{
                 width: 32rpx;
                 height: 32rpx;
             }
+            .collect-btn{
+                right: 96rpx;
+            }
             .tag{
                 color: #E4B478;
                 background-color: #333;
@@ -207,34 +259,15 @@ page{
                 font-size: 32rpx;
                 color: #000;
             }
-            video{
-                width: 100%;
-                height: 400rpx;
-                margin: 30rpx 0 20rpx 0;
-                border-radius: 20rpx;
-            }
-            .poster{
+            .video-content{
                 width: 100%;
                 height: 400rpx;
                 margin: 30rpx 0 20rpx 0;
-                border-radius: 20rpx;
-                position: relative;
-                &::after{
-                    content:'';
-                    display: block;
-                    position: absolute;
-                    width: 120rpx;
-                    height: 120rpx;
-                    top: 50%;
-                    left: 50%;
-                    transform: translate(-50%,-50%);
-                    background-image: url('@/static/video-play-btn.png');
-                    background-size: cover;
-                }
             }
             .time{
                 font-size: 28rpx;
                 color: #999;
+                margin-top: 20rpx;
             }
         }
     }

+ 59 - 64
pages/voice/voice.vue

@@ -23,7 +23,6 @@
             </van-tabs>
         </view>
           
-          
         <view class="empty-box" v-if="list.length==0&&finished">
             <image
                 :src="globalImgUrls.activityNoAuth"
@@ -42,20 +41,24 @@
                     />
                     <text>{{item.VoicePlaySeconds|formatVoiceTime}}</text>
                 </view>
-                <button class="publish-btn" @click.stop="handleSendMsgItem(item)" v-if="item.CouldSendMsg">
-                    <image class="publish-img" src="@/static/voice/publish.png" mode="widthFix"/>
-                </button>
-                <button class="del-btn" @click.stop="handleDelItem(item)" v-if="item.IsAuthor">
-                    <image class="del-img" src="@/static/voice/del.png" mode="widthFix"/>
-                </button>
-                <button 
-                    class="share-btn" 
-                    open-type="share" 
-                    :data-item="item"
-                    @click.stop=""
-                >
-                    <image class="share-img" src="@/static/share-icon.png" mode="aspectFill"/>
-                </button>
+                <view class="opt-box">
+                    <image style="width:34rpx;height:34rpx" src="@/static/voice/publish.png" mode="widthFix" @click.stop="handleSendMsgItem(item)" v-if="item.CouldSendMsg"/>
+                    <image style="width:34rpx;height:34rpx" src="@/static/voice/del.png" mode="widthFix" v-if="item.IsAuthor" @click.stop="handleDelItem(item)" />
+                    <sharePoster 
+                        :showSlot="true"
+                        :shareData="getItemShareData(item)"
+                    >
+                        <image style="width:32rpx;height:32rpx" src="@/static/voice/creat-poster-icon.png" mode="aspectFill" />
+                    </sharePoster>
+                    <button 
+                        class="share-btn" 
+                        open-type="share" 
+                        :data-item="item"
+                        @click.stop=""
+                    >
+                        <image class="share-img" src="@/static/share-icon.png" mode="aspectFill"/>
+                    </button>
+                </view>
             </view>
         </view>
 
@@ -115,12 +118,14 @@ import {apiGetSceneToParams} from '@/api/common'
 import noAuth from './components/noAuth.vue'
 import audioBox from '@/components/audioBox/audioBox.vue'
 import dragButton from '@/components/dragButton/dragButton.vue'
+import sharePoster from '@/components/sharePoster/sharePoster.vue'
 const dayjs=require('@/utils/dayjs.min')
 export default {
     components:{
         noAuth,
         audioBox,
-        dragButton
+        dragButton,
+        sharePoster
     },
     filters:{
         formatTime(e){
@@ -423,6 +428,20 @@ export default {
             })
             if(res.code===200){
                 console.log('上报音频播放记录');
+                this.$store.commit('audio/addAudioRecordId',{recordId:res.data,source:2})
+            }
+        },
+
+        //语音详情生成海报参数
+        getItemShareData(item){
+            return {
+                type:'voice_detail',
+                code_page:'pages-voice/voiceDetail',
+                code_scene:JSON.stringify({voiceId:item.BroadcastId}),
+                data:{
+                    title:item.BroadcastName,
+                    img:item.ImgUrl
+                }
             }
         }
     },
@@ -503,58 +522,34 @@ export default {
         border-bottom: 1px solid #CDCDCD;
         padding: 30rpx 0;
         position: relative;
-        .publish-btn{
-            position: absolute;
-            right: 192rpx;
-            bottom: 30rpx;
-            width: 36rpx;
-            height: 36rpx;
-            background-color: transparent;
-            line-height: 1;
-            padding: 0;
-            &::after{
-                border: none;
+        .opt-box{
+            position: relative;
+            float: right;
+            bottom: 40rpx;
+            display: flex;
+            image{
+                margin-left: 40rpx;
             }
-        }
-        .publish-img{
-            width: 34rpx;
-            height: 34rpx;
-        }
-        .del-btn{
-            position: absolute;
-            right: 96rpx;
-            bottom: 30rpx;
-            width: 36rpx;
-            height: 36rpx;
-            background-color: transparent;
-            line-height: 1;
-            padding: 0;
-            &::after{
-                border: none;
+            .share-btn{
+                background-color: transparent;
+                width: 36rpx;
+                height: 36rpx;
+                line-height: 1;
+                padding: 0;
+                margin-left: 40rpx;
+                &::after{
+                    border: none;
+                }
+                .share-img{
+                    width: 32.5rpx;
+                    height: 32rpx;
+                    margin-left: 0;
+                }
             }
-        }
-        .del-img{
-            width: 34rpx;
-            height: 34rpx;
+            
         }
 
-        .share-btn{
-            position: absolute;
-            bottom: 30rpx;
-            right: 0rpx;
-            background-color: transparent;
-            width: 36rpx;
-            height: 36rpx;
-            line-height: 1;
-            padding: 0;
-            &::after{
-                border: none;
-            }
-        }
-        .share-img{
-            width: 32.5rpx;
-            height: 32rpx;
-        }
+
         .title{
             font-size: 32rpx;
         }

BIN
static/collect-s.png


BIN
static/collect-user-icon.png


BIN
static/collect.png


BIN
static/danmu-close-btn-2.png


BIN
static/danmu-close-btn.png


BIN
static/danmu-show-btn-2.png


BIN
static/danmu-show-btn.png


BIN
static/headphones-icon.png


BIN
static/tabbar/roadShow-s.png


BIN
static/tabbar/roadShow.png


BIN
static/voice/creat-poster-icon.png


+ 7 - 0
store/modules/audio.js

@@ -11,6 +11,8 @@ const audioModules={
         questionId:0,//当前是哪个问答的音频
         paused:true,//当前是否音频正在播放 true暂停状态
         curTime:0,//当前正在播放的音频播放的时间
+        recordId:0,//播放记录id
+        lastType:0,//上次播放的是那种的音频,用于更新媒体播放记录时长中的source
     },
     mutations: {
         addAudio(state,e){
@@ -51,6 +53,11 @@ const audioModules={
         // 关闭弹窗
         closePopAudio(state){
             state.show=false
+        },
+        // 设置播放记录id
+        addAudioRecordId(state,e){
+            state.recordId=e.recordId
+            state.lastType=e.source
         }
     }
 }

+ 5 - 5
utils/config.js

@@ -47,11 +47,11 @@ const defaultTabBarListConfig=[
         selectedIconPath: "../static/tabbar/report-s.png",
     },
 	{
-		key: 'pricedriven',
-		pagePath: "pages/pricedriven/pricedriven",
-		text: "价格驱动",
-		iconPath: "../static/tabbar/price.png",
-		selectedIconPath: "../static/tabbar/price-s.png"
+		key: 'road',
+		pagePath: "pages/roadShow/video/list",
+		text: "线上路演",
+		iconPath: "../static/tabbar/roadShow.png",
+		selectedIconPath: "../static/tabbar/roadShow-s.png"
 	},
     {
         key: "video",

+ 1 - 1
utils/request.js

@@ -96,7 +96,7 @@ const http=(url,params,method)=>{
 			method:method,
 			header:{
 				Authorization:store.state.user.token,
-				version:'yb11.0'
+				version:'yb11.1'
 			},
 			success(e) {
 				// 接口404