jwyu 2 years ago
parent
commit
f31f7ea8ab
5 changed files with 433 additions and 49 deletions
  1. 25 0
      api/voice.js
  2. 181 12
      pages-voice/addVoice.vue
  3. 3 2
      pages/pc.vue
  4. 27 12
      pages/voice/components/noAuth.vue
  5. 197 23
      pages/voice/voice.vue

+ 25 - 0
api/voice.js

@@ -7,7 +7,32 @@ import { httpGet, httpPost } from "@/utils/request.js";
  * @param page_index 
  * @param page_size
  * @param broadcast_id 语音id
+ * @param section_id 板块id
  */
 export const apiVoiceList=params=>{
     return httpPost('/voice/broadcast/list',params)
+}
+
+/**
+ * 语音板块列表
+ */
+export const apiVoiceSectionList=()=>{
+    return httpGet('/voice/broadcast/section/list',{})
+}
+
+/**
+ * 删除语音
+ * @param broadcast_id
+ */
+export const apiVoiceDel=params=>{
+    return httpGet('/voice/broadcast/delete',params)
+}
+
+/**
+ * 播放记录
+ * @param broadcast_id
+ * @param source 来源平台:1:小程序、2:小程序(pc)、3:公众号、4:官网web(pc)
+ */
+export const apiVoicePlayRecord=params=>{
+    return httpPost('/voice/broadcast/statistics/add',{...params,source:1})
 }

+ 181 - 12
pages-voice/addVoice.vue

@@ -5,17 +5,28 @@
             placeholder="请输入语音标题"
             :border="false"
             clearable
+            @change="inputChange"
             label="语音标题"
         />
-        <van-cell 
-            title="品种" 
-            value="原油" 
+        <van-field
+            :value="form.variety_name"
+            placeholder="请选择品种"
             :border="false"
+            readonly
+            is-link
+            label="品种"
+            @click-input="showFilter=true"
+            @click-icon="showFilter=true"
         />
-        <van-cell 
-            title="板块名称" 
-            value="每日原油播报" 
+        <van-field
+            :value="form.section_name"
+            placeholder="请选择板块名称"
             :border="false"
+            readonly
+            is-link
+            label="板块名称"
+            @click-input="showFilter=true"
+            @click-icon="showFilter=true"
         />
 
         <view class="flex audio-box" v-if="recorderStatus==='stop'">
@@ -72,12 +83,39 @@
             >完成</view>
         </view>
 
-        <view class="publish-btn" v-if="recorderStatus==='stop'">发布</view>
-          
+        <view class="publish-btn" v-if="recorderStatus==='stop'" @click="handlePublish">发布</view>
+        
+        <!-- 筛选弹窗 -->
+        <van-popup 
+            :show="showFilter" 
+            position="bottom"  
+            :close-on-click-overlay="true"
+            @close="showFilter = false"
+            round
+        >
+            <view class="fliter-wrap-list">
+                <view class="flex top">
+                    <text style="color:#000">全部选项</text>
+                    <text style="color:#E3B377" @click="showFilter=false">取消</text>
+                </view>
+                <van-tree-select
+                    :items="options"
+                    :main-active-index="mainActiveIndex"
+                    :active-id="activeId"
+                    @click-nav="onClickNav"
+                    @click-item="onClickItem"
+                    main-active-class="main-active-class"
+                    content-active-class="content-active-class"
+                />
+            </view>
+        </van-popup>
     </view>
 </template>
 
 <script>
+import {apiVoiceSectionList} from '@/api/voice'
+import {baseApiUrl} from '@/utils/config.js'
+import CryptoJS from '@/utils/crypto.js'
 const recorderManager = wx.getRecorderManager();//录音实例
 const innerAudioContext = uni.createInnerAudioContext();//播放音频实例
 let TIMER=null//计时器
@@ -106,6 +144,10 @@ export default {
         return {
             form:{
                 title:'',//语音标题
+                variety_name:'',
+                variety_id:'',
+                section_id:'',
+                section_name:''
             },
 
             recorderStatus:'start',//当前录音状态 start开始 doing正在录音 stop停止录音 pause录音暂停
@@ -119,6 +161,12 @@ export default {
                 curTime:0,//播放时当前播放的时间
                 paused:true,
             },//临时音频文件信息
+
+            showFilter:false,
+            options:[],
+            mainActiveIndex:0,
+            activeId:0,//选择的板块id
+
         }
     },
     onLoad(){
@@ -129,6 +177,7 @@ export default {
         })
         this.listenVoice()
         this.listenAudio()
+        this.getOptionsList()
     },
     methods: {
         //录音事件
@@ -188,7 +237,8 @@ export default {
         handleClickBtn(){
             if(this.recorderStatus==='start'){
                 recorderManager.start({
-                    duration:600000
+                    duration:600000,
+                    format:'mp3'
                 })
             }
             if(this.recorderStatus==='doing'){
@@ -268,13 +318,113 @@ export default {
             this.temAudio.url=''
             this.time=0
             TIMER=null
+        },
+
+        //获取选项数据
+        async getOptionsList(){
+            const res=await apiVoiceSectionList()
+            if(!res.code===200) return
+            const arr=res.data||[]
+        
+            this.options=arr.filter(item=>{
+                item.text=item.VarietyName
+                item.children=item.Children.filter(_item=>{
+                    if(_item.Status===1){
+                        _item.text=_item.SectionName
+                        _item.id=_item.SectionId
+                        return _item
+                    }
+                })
+                if(item.children.length>0){
+                    delete item.Children
+                    return item
+                }
+            })
+        },
+
+        onClickNav({detail}){
+            console.log(detail);
+            this.mainActiveIndex=detail.index
+        },
+
+        onClickItem({detail}){
+            console.log(detail);
+            this.activeId=detail.id
+            this.form.section_id=detail.SectionId
+            this.form.section_name=detail.SectionName
+            this.form.variety_name=this.options[this.mainActiveIndex].VarietyName
+            this.form.variety_id=this.options[this.mainActiveIndex].VarietyId
+            this.showFilter=false
+        },
+
+        inputChange(event) {
+            this.form.title=event.detail
+        },
+
+        // 发布
+        handlePublish(){
+            if(!this.form.title||!this.form.variety_id){
+                uni.showToast({
+					title:'请将内容填写完整',
+					icon:'none'
+				})
+                return
+            }
+            let formData={
+                broadcast_name:this.form.title,
+                section_id:Number(this.form.section_id),
+                section_name:this.form.section_name,
+                variety_id:Number(this.form.variety_id),
+                variety_name:this.form.variety_name,
+                author_id:Number(this.$store.state.user.userInfo.user_id),
+                author:this.$store.state.user.userInfo.real_name
+            }
+            uni.uploadFile({
+                url: baseApiUrl + "/voice/broadcast/add",
+                filePath: this.temAudio.url,
+                name: 'file',
+                header: {
+                    Authorization: this.$store.state.user.token,
+                },
+                formData: formData,
+                success: (result) => {
+                    const { envVersion } = uni.getAccountInfoSync().miniProgram
+                    const res =  envVersion === 'release' ? JSON.parse(CryptoJS.Des3Decrypt(result.data)) :  JSON.parse(result.data);
+                    console.log(res);
+                    if(res.code===200){
+                        uni.showToast({
+                            title:'发布成功',
+                            icon:'success'
+                        })
+                        setTimeout(() => {
+                            uni.navigateBack()
+                        }, 1000);
+                    }else{
+                        uni.showToast({
+                            title:res.msg,
+                            icon:'none'
+                        })
+                    }
+                },
+                fail: () => {
+                    console.log('发布失败');
+                    uni.showToast({
+                        title:'发布失败,请稍后重试!',
+                        icon:'none'
+                    })
+                },
+                complete: () => {
+                    console.log('con');
+                }
+            });
+              
         }
 
     },
 }
 </script>
 
-<style>
+<style lang="scss">
 .add-voice-page .van-cell{
     border-bottom: 1px solid #e5e5e5;
 }
@@ -282,18 +432,37 @@ export default {
     font-size: 32rpx;
     color: #333;
 }
-.add-voice-page .van-cell__title{
+/* .add-voice-page .van-cell__title{
     max-width: 6.2em;
     min-width: 6.2em;
     margin-right: 12px;
     font-size: 32rpx;
     color: #333;
-}
+} */
 .add-voice-page .van-cell__value{
     text-align: left;
     font-size: 32rpx;
 }
 
+.add-voice-page{
+    .fliter-wrap-list{
+        background-color: #fff;
+        padding-top: 53rpx;
+        .top{
+            font-size: 32rpx;
+            justify-content: space-between;
+            margin-bottom: 40rpx;
+            padding: 0 34rpx;
+        }
+        .main-active-class{
+            border-color: #E3B377;
+        }
+        .content-active-class{
+            color: #E3B377;
+        }
+    }
+}
+
 page{
     padding-bottom:constant(safe-area-inset-bottom);
     padding-bottom:env(safe-area-inset-bottom);

+ 3 - 2
pages/pc.vue

@@ -8,7 +8,7 @@
 import {pcBaseUrl} from '../utils/config'
 const mapObj=new Map([
     ['pages/activity/activity','/activity/list'],
-	 ['pages/pricedriven/pricedriven','/pricedriven'],
+	['pages/pricedriven/pricedriven','/pricedriven'],
     ['pages-activity/detail','/activity/detail'],
     ['pages/report/report','/report/index'],
     ['pages-report/classify','/report/classify'],
@@ -17,7 +17,8 @@ const mapObj=new Map([
     ['pages-report/chapterDetail','/report/chapterdetail'],
     ['pages-report/specialColumn/list','/report/specialcolumnlist'],
     ['pages-report/specialColumn/detail','/report/specialcolumndetail'],
-    ['pages/video/videoList','/video/list']
+    ['pages/video/videoList','/video/list'],
+    ['pages/voice/voice','/voice/list']
 ])//map映射小程序页面路径对应h5页面路径
 import {apiUserInfo} from '@/api/user'
 import {apiGetSceneToParams} from '@/api/common'

+ 27 - 12
pages/voice/components/noAuth.vue

@@ -7,7 +7,7 @@
 		<view v-if="info.type==='contact'">
 			{{info.name||''}}:<text @click="handleCallPhone(info.mobile+'')">{{info.mobile||''}}</text>
 		</view>
-		<view class="btn" @click="handleGoApply" v-else style="margin-top:30px">立即申请</view>
+		<view class="global-btn-yellow-change btn" @click="handleApply" v-else style="margin-top:30px">立即申请</view>
   </view>
 </template>
 
@@ -17,6 +17,11 @@ export default {
     props: {
         info:null
     },
+    watch:{
+        info(){
+            this.handleAutoApply()
+        }
+    },
     
     methods: {
         handleCall(){
@@ -29,7 +34,7 @@ export default {
         },
 
         handleAutoApply(){
-            if(!this.info.customer_info.has_apply){
+            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,
@@ -46,18 +51,28 @@ export default {
         },
 
         handleApply(){
-            if(this.info.customer_info.status=='流失'){
-                apiApplyPermission({
-                    company_name:this.info.customer_info.company_name,
-                    real_name:this.info.customer_info.name,
-                    source:8,
-                    from_page:'语音播报'
-                }).then(res=>{
-                    uni.navigateTo({url:'/pages-applyPermission/applyResult'})
+            const {customer_info}=this.info
+            if(customer_info.has_apply){
+                uni.showToast({
+                  title:'您已提交过申请,请耐心等待',
+                  icon:'none'
                 })
-                return
+            }else{
+                if (!customer_info.status || customer_info.status != '流失') {
+                    uni.navigateTo({
+                        url: "/pages-applyPermission/applyPermission?source=8&from_page=语音播报"
+                    })
+                }else{
+                    apiApplyPermission({
+                        company_name:customer_info.company_name,
+                        real_name:customer_info.name,
+                        source:8,
+                        from_page:'语音播报'
+                    }).then(res=>{
+                        uni.navigateTo({url:'/pages-applyPermission/applyResult'})
+                    })
+                }
             }
-            uni.navigateTo({ url: '/pages-applyPermission/applyPermission?source=8&from_page=语音播报' })
         }
     }
 }

+ 197 - 23
pages/voice/voice.vue

@@ -1,8 +1,8 @@
 <template>
     <view class="voice-play-page" v-if="isAuth">
         <view class="top-filter-box">
-            <image src="@/static/question/select.png" mode="aspectFill" />
-            <text>筛选</text>
+            <image src="@/static/question/select.png" mode="aspectFill" @click="showFilter = true" />
+            <text @click="showFilter = true">筛选</text>
         </view>
           
         <view class="empty-box" v-if="list.length==0&&finished">
@@ -12,15 +12,19 @@
             />
             <view>暂无数据</view>
         </view>
-        <view class="list-wrap" v-else>
+        <view class="list-wrap" :style="{paddingBottom:IsVoiceAdmin&&'200rpx'}" v-else>
             <view class="item" v-for="item in list" :key="item.BroadcastId">
                 <view class="title">{{item.BroadcastName}}</view>
                 <view class="time">发布时间:{{item.CreateTime|formatTime}}</view>
-                <view class="flex audio-box">
-                    <image src="@/static/voice/pause.png" mode="widthFix" />
-                    <text>06:27</text>
+                <view class="flex audio-box" @click="handlePlay(item)">
+                    <image 
+                        :src="item.BroadcastId==temAudio.id&&!temAudio.paused?require('@/static/voice/playing.png'):require('@/static/voice/pause.png')" 
+                        mode="widthFix" 
+                    />
+                    <text v-if="item.BroadcastId==temAudio.id">{{temAudio.curTime|formatVoiceTime}}</text>
+                    <text v-else>{{item.VoicePlaySeconds|formatVoiceTime}}</text>
                 </view>
-                <image class="del-btn" src="@/static/voice/del.png" mode="widthFix" />
+                <image class="del-btn" src="@/static/voice/del.png" @click="handleDelItem(item)" mode="widthFix" v-if="item.IsAuthor" />
                 <button 
                     class="share-btn" 
                     open-type="share" 
@@ -35,34 +39,42 @@
             <view class="add-btn" v-if="IsVoiceAdmin">新建语音</view>
         </navigator>
 
-        
         <!-- 筛选弹窗 -->
         <van-popup 
             :show="showFilter" 
             position="bottom"  
             :close-on-click-overlay="true"
             @close="showFilter = false"
+            round
         >
             <view class="fliter-wrap-list">
+                <view class="flex top">
+                    <text style="color:#000">全部筛选</text>
+                    <text style="color:#E3B377" @click="showFilter=false">取消</text>
+                </view>
                 <van-tree-select
-                    :items="items"
+                    :items="options"
                     :main-active-index="mainActiveIndex"
                     :active-id="activeId"
                     @click-nav="onClickNav"
                     @click-item="onClickItem"
+                    main-active-class="main-active-class"
+                    content-active-class="content-active-class"
                 />
             </view>
         </van-popup>
 
+        <van-dialog id="van-dialog" />
     </view>
     <noAuth :info="noAuthData" v-else/>
 </template>
 
 <script>
-import {apiVoiceList} from '@/api/voice'
+import {apiVoiceList,apiVoiceSectionList,apiVoicePlayRecord} from '@/api/voice'
 import {apiGetSceneToParams} from '@/api/common'
 import noAuth from './components/noAuth.vue'
 const moment=require('@/utils/moment-with-locales.min')
+const innerAudioContext = uni.createInnerAudioContext();//播放音频实例
 export default {
     components:{
         noAuth
@@ -70,6 +82,11 @@ export default {
     filters:{
         formatTime(e){
             return moment(e).format('YYYY-MM-DD HH:mm:ss')
+        },
+        formatVoiceTime(e){
+            let m=parseInt(e/60)
+            let s=parseInt(e%60)
+            return `${m>9?m:'0'+m}:${s>9?s:'0'+s}`
         }
     },
     data() {
@@ -86,21 +103,28 @@ export default {
             noAuthData:null,
 
             showFilter:false,
-            options:[
-                {
-                    text:'选项一',
-                    
-                }
-            ]
+            options:[],
+            mainActiveIndex:0,
+            activeId:0,//选择的板块id
+
+            temAudio:{
+                paused:true,
+                url:'',//临时音频地址
+                duration:'',//时长
+                id:0,
+                curTime:''
+            }
         }
     },
     onLoad(options){
         this.init(options)
+        this.getOptionsList()
+        this.listenAudio()
     },
     onShareAppMessage({from,target}) {
         console.log(from,target);
         let path='/pages/voice/voice?voiceId=0'
-        let title='FICC语音播报'
+        let title='语音播报'
         let imageUrl=''
         if(from=='button'){
             title=`${target.dataset.item.SectionName}:${target.dataset.item.BroadcastName}`
@@ -119,6 +143,7 @@ export default {
         this.list=[]
         this.finished=false
         this.getVoiceList()
+        this.getOptionsList()
         setTimeout(() => {
             uni.stopPullDownRefresh()
         }, 1500)
@@ -137,6 +162,8 @@ export default {
                     const obj=JSON.parse(res.data)
                     this.voiceId=obj.voiceId
                 }
+            }else{
+                this.voiceId=options.voiceId||0
             }
             this.getVoiceList()
         },
@@ -146,7 +173,8 @@ export default {
             const res=await apiVoiceList({
                 page_index:this.page,
                 page_size:this.pageSize,
-                broadcast_id:Number(this.voiceId)
+                broadcast_id:Number(this.voiceId),
+                section_id:Number(this.activeId)
             })
             if(res.code===200){
                 this.IsVoiceAdmin=res.data.IsVoiceAdmin
@@ -160,15 +188,164 @@ export default {
                 this.isAuth=false
                 this.noAuthData=res.data
             }
+        },
+
+        //获取筛选数据
+        async getOptionsList(){
+            const res=await apiVoiceSectionList()
+            if(res.code!==200) return
+            const arr=res.data||[]
+            this.options=arr.map(item=>{
+                let obj={
+                    text:'',
+                    children:[]
+                }
+                obj.text=item.VarietyName
+                obj.children=item.Children.map(_item=>{
+                    return {
+                        text:_item.SectionName,
+                        id:_item.SectionId
+                    }
+                })
+                return obj
+            })
+        },
+
+        onClickNav({detail}){
+            console.log(detail);
+            this.mainActiveIndex=detail.index
+        },
+
+        onClickItem({detail}){
+            console.log(detail);
+            if(this.activeId==detail.id){
+                this.activeId=0
+            }else{
+                this.activeId=detail.id
+            }
+            this.voiceId=0
+            this.page=1
+            this.list=[]
+            this.finished=false
+            this.getVoiceList()
+            this.showFilter=false
+        },
+        
+        //删除音频
+        handleDelItem(item){
+            this.$dialog.confirm({
+                title:'',
+                message: '确定要删除该语音播报吗?',
+                confirmButtonText:'确定'
+            }).then(()=>{
+                apiVoiceDel({broadcast_id:Number(item.BroadcastId)}).then(res=>{
+                    if(res.code===200){
+                        uni.showToast({
+                            message:'操作成功',
+                            icon:'none'
+                        })
+                        this.page=1
+                        this.list=[]
+                        this.finished=false
+                        this.getVoiceList()
+                    }
+                })
+            }).catch(()=>{})
+        },
+
+        handlePlay(item){
+            
+            //没有初始化时
+            if(!innerAudioContext.src){
+                this.temAudio.id=item.BroadcastId
+                this.temAudio.duration=item.VoicePlaySeconds
+                this.temAudio.curTime=item.VoicePlaySeconds
+                innerAudioContext.src=item.VoiceUrl 
+                innerAudioContext.play()
+                this.handleVoicePlayRecord(item)
+                return
+            }
+
+            if(innerAudioContext.paused){
+                innerAudioContext.play()
+            }else{
+                innerAudioContext.pause()
+            }
+        },
+
+        //音频播放事件
+        listenAudio(){
+            innerAudioContext.onPlay(()=>{
+                console.log('开始播放录音');
+                this.temAudio.paused=false
+            })
+            innerAudioContext.onPause(()=>{
+                console.log('录音播放暂停');
+                this.temAudio.paused=true
+            })
+            innerAudioContext.onStop(()=>{
+                console.log('录音播放停止');
+                this.temAudio.paused=true
+                setTimeout(() => {
+                    this.temAudio.id=0
+                }, 100);
+                innerAudioContext.src=''
+            })
+            innerAudioContext.onEnded(()=>{
+                console.log('录音播放自然结束');
+                this.temAudio.paused=true
+                setTimeout(() => {
+                    this.temAudio.id=0
+                }, 100);
+                innerAudioContext.src=''
+            })
+            innerAudioContext.onTimeUpdate(()=>{
+                this.temAudio.curTime=parseInt(this.temAudio.duration)-parseInt(innerAudioContext.currentTime)
+            })
+        },
+
+        //上报音频播放记录
+        async handleVoicePlayRecord(item){
+            const res=await apiVoicePlayRecord({
+                broadcast_id:item.BroadcastId
+            })
+            if(res.code===200){
+                console.log('上报音频播放记录');
+            }
         }
     },
 }
 </script>
 
+<style lang="scss">
+.voice-play-page{
+    
+    .fliter-wrap-list{
+        background-color: #fff;
+        padding-top: 53rpx;
+        padding-bottom: 100rpx;
+        .top{
+            font-size: 32rpx;
+            justify-content: space-between;
+            margin-bottom: 40rpx;
+            padding: 0 34rpx;
+        }
+        .main-active-class{
+            border-color: #E3B377;
+        }
+        .content-active-class{
+            color: #E3B377;
+        }
+    }
+}
+</style>
+
 <style lang="scss" scoped>
 .voice-play-page{
-    padding: 34rpx;
+    
     .top-filter-box{
+        padding-left: 34rpx;
+        padding-bottom: 10rpx;
         position: sticky;
         top: 0;
         left: 0;
@@ -195,6 +372,7 @@ export default {
     }
 }
 .list-wrap{
+    padding: 0 34rpx 34rpx 34rpx;
     .item{
         border-bottom: 1px solid #CDCDCD;
         padding: 30rpx 0;
@@ -265,8 +443,4 @@ export default {
     box-shadow: 0px 4rpx 20rpx rgba(160, 126, 84, 0.25);
     border-radius: 40rpx;
 }
-
-.fliter-wrap-list{
-
-}
 </style>