jwyu 2 years ago
parent
commit
d9d695bc1b
4 changed files with 456 additions and 18 deletions
  1. 10 0
      src/router/index.js
  2. 369 0
      src/views/voice/Detail.vue
  3. 15 4
      src/views/voice/List.vue
  4. 62 14
      src/views/voice/Mine.vue

+ 10 - 0
src/router/index.js

@@ -372,6 +372,16 @@ const routes=[
           keepAlive:true,
           isRoot:true
         }
+      },
+      {
+        path:"detail",
+        name:"VoiceDetail",
+        component:()=>import('@/views/voice/Detail.vue'),
+        meta: {
+          title: "语音详情",
+          keepAlive:false,
+          isRoot:false
+        }
       }
     ]
   },

+ 369 - 0
src/views/voice/Detail.vue

@@ -0,0 +1,369 @@
+<script setup>
+import {ref,onMounted} from 'vue'
+import {apiVoiceDetail,apiVoiceDel,apiVoicePlayRecord,apiVoiceSendMsg} from '@/api/voice'
+import {apiGetWechatQRCode} from '@/api/common'
+import {apiApplyPermission} from '@/api/user'
+import { useRoute, useRouter } from 'vue-router'
+import { useStore } from 'vuex'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import moment from 'moment'
+
+const route=useRoute()
+const router=useRouter()
+const store=useStore()
+
+let voiceId=route.query.voiceId
+
+// 获取详情
+let noAuth=ref(null)
+let info=ref(null)
+const getDetail=async ()=>{
+    const res=await apiVoiceDetail({broadcast_id:Number(voiceId)})
+    if(res.code===200){
+        info.value=res.data
+        noAuth.value=null
+        document.title=res.data.SectionName||'播报详情'
+        store.commit('modifyBreadCrumb',res.data.SectionName||'播报详情')
+        handelGetQRCodeImg()
+        //向小程序发送消息
+        let postData = {
+            path: "/pages-voice/voiceDetail",
+            params:{
+                voiceId:info.BroadcastId
+            },
+            title: `${info.value.SectionName}:${info.value.BroadcastName}`,
+            shareImg:info.value.ImgUrl
+        };
+        wx.miniProgram.postMessage({ data: postData });
+        
+    }else if(res.code===403){
+        noAuth.value=res.data
+        handleAutoApply()
+        //向小程序发送消息
+        let postData = {
+            path: "/pages-voice/voiceDetail",
+            params:{
+                voiceId:voiceId
+            },
+            title: `播报详情`,
+            shareImg:''
+        };
+        wx.miniProgram.postMessage({ data: postData });
+    }
+}
+getDetail()
+
+//获取音频对应的小程序二维码
+const handelGetQRCodeImg=async ()=>{
+    const res=await apiGetWechatQRCode({
+        CodeScene:JSON.stringify({voiceId:info.value.BroadcastId}),
+        CodePage:'pages-voice/voiceDetail'
+    })
+    if(res.code===200){
+        info.value.QRCodeImg=res.data
+    }
+}
+
+//无权限时申请
+const handleAutoApply=()=>{
+    if(noAuth.value.type=='contact'&&!noAuth.value.customer_info.has_apply){
+        if(noAuth.value.customer_info.status=='冻结'||(noAuth.value.customer_info.status=='试用'&&noAuth.value.customer_info.is_suspend==1)){
+            apiApplyPermission({
+                company_name:noAuth.value.customer_info.company_name,
+                real_name:noAuth.value.customer_info.name,
+                source:8,
+                from_page:'语音播报'
+            }).then(res=>{
+                if(res.code===200){
+                    console.log('主动申请成功');
+                }
+            }) 
+        }
+    }
+}
+const handleApply=()=>{
+    if(noAuth.value.customer_info.has_apply){
+        const htmlStr=`<p>您已提交过申请,请耐心等待</p>`
+        ElMessageBox({
+            title:`语音播报`,
+            message:htmlStr,
+            center: true,
+            dangerouslyUseHTMLString: true,
+            confirmButtonText:'知道了',
+            confirmButtonClass:'self-elmessage-confirm-btn'
+        })
+    }else{
+        if (!noAuth.value.customer_info.status || noAuth.value.customer_info.status != '流失') {
+            console.log('跳转申请页');
+            router.push({
+                path:'/apply/permission',
+                query:{
+                    source:8,
+                    fromPage:'语音播报'
+                }
+            })
+        }else{
+            apiApplyPermission({
+                company_name:noAuth.value.customer_info.company_name,
+                real_name:noAuth.value.customer_info.name,
+                source:8,
+                from_page:'语音播报'
+            }).then(res=>{
+                onsole.log('主动申请成功');
+                const htmlStr=`<p>申请已提交</p><p>请等待销售人员与您联系</p>`
+                ElMessageBox({
+                    title:`语音播报`,
+                    message:htmlStr,
+                    center: true,
+                    dangerouslyUseHTMLString: true,
+                    confirmButtonText:'知道了',
+                    confirmButtonClass:'self-elmessage-confirm-btn'
+                })
+            })
+        }
+    }
+}
+
+//删除音频
+const handleDel=(item)=>{
+    ElMessageBox({
+        title:`温馨提醒`,
+        message:'确定要删除该语音播报吗?',
+        center: true,
+        dangerouslyUseHTMLString: true,
+        confirmButtonText:'确定',
+        confirmButtonClass:'self-elmessage-confirm-btn',
+        showCancelButton:true,
+        cancelButtonText:'取消',
+        cancelButtonClass:'self-elmessage-cancel-btn'
+    }).then(()=>{
+        if(store.state.audioData.voiceId==item.BroadcastId){
+            //删除的正在播放
+            store.commit('closeAudio')
+        }
+        apiVoiceDel({broadcast_id:Number(item.BroadcastId)}).then(res=>{
+            if(res.code===200){
+                ElMessage.success('操作成功')
+                if(window.history.state.back){
+                    console.log('返回上一页');
+                    router.go(-1)
+                }else{
+                    console.log('返回列表');
+                    router.push({path:'/voice/list'})
+                }
+            }
+        })
+    }).catch(()=>{
+            
+    })
+}
+
+//发送模板消息
+const handleSendMsg=async (item)=>{
+    ElMessageBox({
+        title:`温馨提醒`,
+        message:'该操作将推送模板消息和客群,确认推送吗?',
+        center: true,
+        dangerouslyUseHTMLString: true,
+        confirmButtonText:'确定',
+        confirmButtonClass:'self-elmessage-confirm-btn',
+        showCancelButton:true,
+        cancelButtonText:'取消',
+        cancelButtonClass:'self-elmessage-cancel-btn'
+    }).then(()=>{
+        apiVoiceSendMsg({broadcast_id:Number(item.BroadcastId)}).then(res=>{
+            if(res.code===200){
+                ElMessage.success('操作成功')
+                info.value.CouldSendMsg=false
+            }
+        })
+    }).catch(()=>{
+            
+    })
+}
+
+//处理音频时长显示
+const formarVoiceTime=(e)=>{
+    let m=parseInt(e/60)
+    let s=parseInt(e%60)
+    return `${m>9?m:'0'+m}:${s>9?s:'0'+s}`
+}
+
+//播放音频
+const handlePlay=(item)=>{
+    if(store.state.audioData.voiceId==item.BroadcastId){
+        if(store.state.audioData.paused){
+            store.state.audioData.INS.play()
+        }else{
+            store.state.audioData.INS.pause()
+        }
+        return
+    }
+    store.commit('addAudio',{
+        list:[{name:item.BroadcastName,url:item.VoiceUrl,time:item.VoicePlaySeconds}],
+        voiceId:item.BroadcastId,
+        index:0
+    })
+    handleVoiceRecord(item)
+}
+
+//上报音频播放记录
+const handleVoiceRecord=async (item)=>{
+    const res=await apiVoicePlayRecord({
+        broadcast_id:item.BroadcastId
+    })
+    if(res.code===200){
+        console.log('上报音频播放记录');
+    }
+}
+
+</script>
+
+<template>
+    <div class="voice-no-auth" v-if="noAuth">
+        <img :src="$store.state.globalImgUrls.activityNoAuth" alt="">
+        <p style="font-size:16px;margin-bottom: 0;">您暂无权限查看语音播报</p>
+        <template v-if="noAuth.type=='contact'">
+            <p style="font-size:16px;margin-top: 5px;margin-bottom: 62px;">若想查看,可以联系对口销售--{{noAuth.name}}:<span style="color:#F3A52F">{{noAuth.mobile}}</span></p>
+        </template>
+        <template v-else>
+            <p style="font-size:16px;margin-top: 5px;margin-bottom: 62px;">若想参加可以申请开通</p>
+            <div class="global-main-btn btn" @click="handleApply" style="margin-bottom: 20px;">立即申请</div>
+        </template>
+    </div>
+    <div class="voice-detail-page" v-if="!noAuth&&info">
+        <h2 class="title">{{info.BroadcastName}}</h2>
+        <p class="publish-time">发布时间:{{moment(info.CreateTime).format('YYYY-MM-DD HH:mm:ss')}}</p>
+        <div class="flex bot-box">
+            <div class="flex audio-box" @click.stop="handlePlay(info)">
+                <div :class="['icon',($store.state.audioData.voiceId==info.BroadcastId)&&!$store.state.audioData.paused?'active':'']"></div>
+                <div>{{formarVoiceTime(info.VoicePlaySeconds)}}</div>
+            </div>
+            <div class="flex btns-box">
+                <img 
+                    class="btn publish-btn" 
+                    v-if="info.CouldSendMsg"
+                    src="@/assets/voice/publish.png" 
+                    alt=""
+                    @click.stop="handleSendMsg(info)"
+                />
+                <img 
+                    class="btn del-btn" 
+                    v-if="info.IsAuthor" 
+                    src="@/assets/voice/del.png" 
+                    alt=""
+                    @click.stop="handleDel(info)"
+                />
+                <el-popover
+                    :width="200"
+                    trigger="hover"
+                >
+                    <template #reference>
+                        <div class="btn icon-wechat"></div>
+                    </template>
+                    <template #default>
+                        <img style="width:100%" :src="info.QRCodeImg" alt="">
+                    </template>
+                </el-popover>
+            </div>
+        </div>
+        <div class="img-box">
+            <el-image
+                style="width: 100%; height: auto"
+                :src="item"
+                :preview-src-list="info.Imgs"
+                :initial-index="index"
+                fit="contain"
+                v-for="item,index in info.Imgs" 
+                :key="item"
+            />
+        </div>
+
+    </div>
+</template>
+
+<style lang="scss" scoped>
+.icon-wechat{
+    cursor: pointer;
+    width: 24px;
+    height: 24px;
+    background-image: url('@/assets/icon-wechat.png');
+    background-size: cover;
+    margin-left: 30px;
+    &:hover{
+        background-image: url('@/assets/icon-wechat2.png');
+    }
+}
+.voice-no-auth{
+    text-align: center;
+    img{
+        width: 400px;
+    }
+    .btn{
+        width: 218px;
+        margin-left: auto;
+        margin-right: auto;
+    }
+}
+.voice-detail-page{
+    border-left: 1px solid #F2F2F2;
+    border-right: 1px solid #F2F2F2;
+    padding: 30px;
+    .title{
+        font-size: 16px;
+        margin: 0 0 10px 0;
+    }
+    .publish-time{
+        margin: 0;
+        font-size: 14px;
+        color: #666;
+    }
+    .audio-box{
+        width: 193px;
+        height: 38px;
+        background: #F4E1C9;
+        border-radius: 28px;
+        color: #E3B377;
+        font-size: 14px;
+        align-items: center;
+        padding-left: 20px;
+        cursor: pointer;
+        .icon{
+            width: 16px;
+            height: 19px;
+            background-image: url('@/assets/voice/pause.png');
+            background-size: cover;
+            margin-right: 10px;
+        }
+        .active{
+            background-image: url('@/assets/voice/playing.png');
+        }
+    }
+    .bot-box{
+        justify-content: space-between;
+        align-items: baseline;
+        margin-top: 20px;
+        .btn{
+            margin-left: 30px;
+        }
+        .del-btn{
+            width: 23px;
+            height: 23px;
+            cursor: pointer;
+        }
+        .publish-btn{
+            width: 23px;
+            height: 23px;
+            cursor: pointer;
+        }
+    }
+    .img-box{
+        margin-top: 30px;
+        img{
+            width: 100%;
+            object-fit: contain;
+            margin-bottom: 30px;
+        }
+    }
+}
+</style>

+ 15 - 4
src/views/voice/List.vue

@@ -263,6 +263,16 @@ const handleVoiceRecord=async (item)=>{
     }
 }
 
+//跳转详情
+const goDetail=(item)=>{
+    router.push({
+        path:'/voice/detail',
+        query:{
+            voiceId:item.BroadcastId,     
+        }
+    })
+}
+
 
 onMounted(() => {
   //向小程序发送消息
@@ -321,9 +331,9 @@ onActivated(()=>{
         >
             <div class="list-wrap">
                 <div class="item" v-for="item in listState.list" :key="item.BroadcastId">
-                    <h2 class="title">{{item.BroadcastName}}</h2>
+                    <h2 class="title" @click="goDetail(item)">{{item.BroadcastName}}</h2>
                     <div class="time">发布时间:{{moment(item.CreateTime).format('YYYY-MM-DD HH:mm:ss')}}</div>
-                    <div class="flex audio-box" @click="handlePlay(item)">
+                    <div class="flex audio-box" @click.stop="handlePlay(item)">
                         <div :class="['icon',($store.state.audioData.voiceId==item.BroadcastId)&&!$store.state.audioData.paused?'active':'']"></div>
                         <div>{{formarVoiceTime(item.VoicePlaySeconds)}}</div>
                     </div>
@@ -332,14 +342,14 @@ onActivated(()=>{
                         v-if="item.CouldSendMsg"
                         src="@/assets/voice/publish.png" 
                         alt=""
-                        @click="handleSendMsg(item)"
+                        @click.stop="handleSendMsg(item)"
                     />
                     <img 
                         class="del-btn" 
                         v-if="item.IsAuthor" 
                         src="@/assets/voice/del.png" 
                         alt=""
-                        @click="handleDel(item)"
+                        @click.stop="handleDel(item)"
                     />
                     <el-popover
                         :width="200"
@@ -388,6 +398,7 @@ onActivated(()=>{
             .title{
                 font-size: 16px;
                 margin: 0 0 10px 0;
+                cursor: pointer;
             }
             .time{
                 color: #666;

+ 62 - 14
src/views/voice/Mine.vue

@@ -2,7 +2,7 @@
 import {ref,reactive,onMounted,onActivated} from 'vue'
 import {apiGetWechatQRCode} from '@/api/common'
 import {apiVoiceList,apiVoiceDel,apiVoicePlayRecord,apiVoiceSendMsg,apiMyVoiceCount,apiVoicePublish} from '@/api/voice'
-import {apiApplyPermission} from '@/api/user'
+import {apiApplyPermission,apiUserInfo} from '@/api/user'
 import SelfList from '@/components/SelfList.vue'
 import { ElMessage, ElMessageBox } from 'element-plus'
 import { useElementSize } from '@vueuse/core'
@@ -18,6 +18,19 @@ const store=useStore()
 const listPageEl=ref('')
 const {width}=useElementSize(listPageEl)
 
+let user_id=store.state.userInfo?.user_id||''
+const init=async ()=>{
+    if(!user_id){
+        const res=await apiUserInfo()
+        if(res.code===200){
+            user_id=res.data.user_id
+        }
+    }
+    getStatusCount()
+    getVoiceList()
+}
+
+
 //状态选项
 let status=reactive({
     list:[
@@ -43,14 +56,14 @@ let status=reactive({
     select:0
 })
 const getStatusCount=async ()=>{
-    const res=await apiMyVoiceCount({author_id:store.state.userInfo.user_id})
+    const res=await apiMyVoiceCount({author_id:user_id})
     if(res.code===200){
         status.list.forEach(item=>{
             item.count=res.data[item.key]
         })
     }
 }
-getStatusCount()
+
 
 //状态切换
 const handleChangeStatus=(item)=>{
@@ -76,7 +89,7 @@ const getVoiceList=async ()=>{
     const res=await apiVoiceList({
         page_index:Number(listState.page),
         page_size:listState.pageSize,
-        author_id:Number(store.state.userInfo.user_id),
+        author_id:Number(user_id),
         mine_status:status.select
     })
     listState.loading=false
@@ -88,7 +101,6 @@ const getVoiceList=async ()=>{
         }
     }
 }
-getVoiceList()
 
 // 加载下一页
 const onLoad=()=>{
@@ -236,16 +248,51 @@ const handleVoiceRecord=async (item)=>{
     }
 }
 
+//跳转详情
+const goDetail=async (item)=>{
+    if(item.PublishState==0){
+        const res=await apiGetWechatQRCode({
+            CodeScene:JSON.stringify({voiceId:item.BroadcastId}),
+            CodePage:'pages-voice/addVoice'
+        })
+        let htmlStr=`<div>PC端暂不支持编辑语音播报,请扫码进入小程序编辑</div>`
+        if(res.code===200){
+            htmlStr=`<div>PC端暂不支持编辑语音播报,请扫码进入小程序编辑</div><div><img style="width:150px;height:150px" src="${res.data}" ></div>`
+        }
+
+        ElMessageBox({
+            title:`温馨提醒`,
+            message:htmlStr,
+            center: true,
+            dangerouslyUseHTMLString: true,
+            confirmButtonText:'知道了',
+            confirmButtonClass:'self-elmessage-confirm-btn',
+            showCancelButton:false,
+            cancelButtonText:'取消',
+            cancelButtonClass:'self-elmessage-cancel-btn'
+        }).then(()=>{}).catch(()=>{})
+    }else{
+        router.push({
+            path:'/voice/detail',
+            query:{
+                voiceId:item.BroadcastId,     
+            }
+        })
+    }
+    
+}
+
 
 onMounted(() => {
-  //向小程序发送消息
-  let postData = {
-    path: "/pages/voice/voice",
-    params:{},
-    title: "语音播报",
-    shareImg:''
-  };
-  wx.miniProgram.postMessage({ data: postData });
+    init()
+    //向小程序发送消息
+    let postData = {
+        path: "/pages/voice/voice",
+        params:{},
+        title: "语音播报",
+        shareImg:''
+    };
+    wx.miniProgram.postMessage({ data: postData });
 });
 onActivated(()=>{
     //向小程序发送消息
@@ -280,7 +327,7 @@ onActivated(()=>{
         >
             <div class="list-wrap">
                 <div class="item" v-for="item in listState.list" :key="item.BroadcastId">
-                    <h2 class="title">{{item.BroadcastName}}</h2>
+                    <h2 class="title" @click="goDetail(item)">{{item.BroadcastName}}</h2>
                     <div class="time">发布时间:{{moment(item.CreateTime).format('YYYY-MM-DD HH:mm:ss')}}</div>
                     <div class="flex audio-box" @click="handlePlay(item)">
                         <div :class="['icon',($store.state.audioData.voiceId==item.BroadcastId)&&!$store.state.audioData.paused?'active':'']"></div>
@@ -390,6 +437,7 @@ onActivated(()=>{
             .title{
                 font-size: 16px;
                 margin: 0 0 10px 0;
+                cursor: pointer;
             }
             .time{
                 color: #666;