jwyu 2 lat temu
rodzic
commit
90ac2be5cd

+ 1 - 1
README.md

@@ -9,4 +9,4 @@ https://ybpc.hzinsights.com
 开发说明
 1./components/SelfList.vue 为公共列表加载组件。如列表加载逻辑同样 请使用此组件
 2.mac PC小程序尺寸 1024*720
-
+3.微信扫码登录文档:https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html

+ 1 - 0
index.html

@@ -6,6 +6,7 @@
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     <script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
     <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
+    <script src="https://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"></script>
     <title>弘则研报</title>
   </head>
   <body>

+ 9 - 0
src/api/common.js

@@ -9,4 +9,13 @@ import {get,post} from './http'
  */
 export const apiGetPermissionList=()=>{
     return get('/public/get_apply_variety_list')
+}
+
+/**
+ * 获取分享用的小程序码
+ * @param CodeScene 页面所需参数
+ * @param CodePage  小程序页面路径
+ */
+export const apiGetWechatQRCode=params=>{
+    return post('/pc/getSunCode',params)
 }

+ 8 - 2
src/api/http.js

@@ -40,8 +40,14 @@ _axios.interceptors.response.use(
       data=response.data
     }
     if(data.code===401){//token失效
-      ElMessage.error('请重新登录')
-      wx.miniProgram.switchTab({url: '/pages/report/report'})
+      // ElMessage.error('请重新登录')
+      console.log('miniprogram:',window.__wxjs_environment)
+      if(window.__wxjs_environment === 'miniprogram'){
+        wx.miniProgram.switchTab({url: '/pages/report/report'})
+      }else{
+        store.commit('showLogin')
+      }
+      
     }
     if(data.code!==200&&data.code!==403&&data.code!==4001&&data.code!==401){
       ElMessage.error(data.msg)

+ 7 - 0
src/api/report.js

@@ -108,6 +108,13 @@ export const apiReportIndexNewbanner=()=>{
     return get('/pc/banner',{})
 }
 
+/**
+ * 研报首页上新公共内容
+ */
+export const apiReportIndexNew=params=>{
+    return get('/pc/latest_release',params)
+}
+
 /**
  * 专栏详情中客户评价
  */

+ 8 - 2
src/api/user.js

@@ -17,11 +17,17 @@ export const apiUserInfo=()=>{
  * @param permission 选择的权限
  * @param real_name 姓名
  * @param source 来源:我的1、活动2、图库3、研报4
- * @param source_agent 来源平台:1:小程序、2:pc
+ * @param source_agent 来源平台:1:小程序、2:小程序(pc)、3:公众号、4:web(pc)
  * @param from_page 来源页面: '活动列表'、'活动详情'等
  */
 export const apiApplyPermission=params=>{
-	return post('/user/apply',{...params,source_agent:2})
+	let source_agent=2
+	if(window.__wxjs_environment === 'miniprogram'){
+		source_agent=2
+	}else{
+		source_agent=4
+	}
+	return post('/user/apply',{...params,source_agent:source_agent})
 }
 
 /**

BIN
src/assets/icon-success.png


BIN
src/assets/leftNav/activity-s.png


BIN
src/assets/leftNav/activity.png


BIN
src/assets/leftNav/chart-s.png


BIN
src/assets/leftNav/chart.png


BIN
src/assets/leftNav/report-s.png


BIN
src/assets/leftNav/report.png


+ 52 - 0
src/components/LoginPop.vue

@@ -0,0 +1,52 @@
+<script setup>
+import { onMounted } from 'vue';
+
+let obj = null
+
+onMounted(()=>{
+    const redirect_uri=encodeURIComponent('https://ybpc.hzinsights.com/report/index')
+    obj=new WxLogin({
+        self_redirect:true,
+        id:"wx-qrcode-box", 
+        appid: "wxb059c872d79b9967", 
+        scope: "snsapi_login", 
+        redirect_uri: redirect_uri,
+        state: "",
+        style: "",
+        href: ""
+    });
+    console.log(obj);
+})
+
+
+</script>
+
+<template>
+    <div class="login-wrap">
+        <div id="wx-qrcode-box" class="wx-qrcode-box">
+        </div>
+    </div>
+</template>
+
+<style lang="scss">
+.login-wrap{
+    position: fixed;
+    left: 0;
+    right: 0;
+    bottom: 00;
+    top: 0;
+    background-color: rgba(0,0,0,0.4);
+    z-index: 9999;
+    .wx-qrcode-box{
+        position: absolute;
+        top: 50%;
+        left: 50%;
+        transform: translate(-50%,-50%);
+        width: 400px;
+        height: 500px;
+        background-color: #fff;
+        border-radius: 16px;
+    }
+
+}
+</style>

+ 4 - 0
src/layout/Index.vue

@@ -3,6 +3,7 @@ import Aside from "./component/Aside.vue";
 import Header from './component/Header.vue'
 import Footer from './component/Footer.vue'
 import AudioBox from '@/components/Audio.vue'
+import LoginPop from '@/components/LoginPop.vue'
 
 
 </script>
@@ -37,6 +38,9 @@ import AudioBox from '@/components/Audio.vue'
 
     <!-- 音频模块 -->
     <AudioBox></AudioBox>
+
+    <!-- 登录弹窗 -->
+    <LoginPop v-if="$store.state.showLogin"></LoginPop>
   </div>
 </template>
 

+ 12 - 12
src/layout/component/Aside.vue

@@ -19,18 +19,18 @@ const menuList = reactive([
     MenuId: 1,
     name: "研报",
     path: "/report/index",
-    icon_path: new URL('../../assets/leftNav/activity-s.png', import.meta.url).href,
+    icon_path: new URL('../../assets/leftNav/report-s.png', import.meta.url).href,
     children: null,
   },
+  // {
+  //   MenuId: 1,
+  //   name: "ETA图库",
+  //   path: "/chart/list",
+  //   icon_path: new URL('../../assets/leftNav/chart-s.png', import.meta.url).href,
+  //   children: null,
+  // },
   {
-    MenuId: 1,
-    name: "ETA图库",
-    path: "/chart/list",
-    icon_path: new URL('../../assets/leftNav/activity-s.png', import.meta.url).href,
-    children: null,
-  },
-  {
-    MenuId: 1,
+    MenuId: 3,
     name: "活动",
     path: "/activity/list",
     icon_path: new URL('../../assets/leftNav/activity-s.png', import.meta.url).href,
@@ -43,11 +43,11 @@ const menuList = reactive([
   <div class="aside-wrap">
     <el-menu router :default-active="activePath" unique-opened text-color="#333" active-text-color="#F3A52F" class="el-menu-wrap">
       <template v-for="menu in menuList">
-        <el-menu-item :index="menu.path" :key="menu.id" v-if="!menu.children">
+        <el-menu-item :index="menu.path" :key="menu.MenuId" v-if="!menu.children">
           <img class="menu-icon" :src="menu.icon_path" alt="" />
           <span class="menu-text">{{ menu.name }}</span>
         </el-menu-item>
-        <el-sub-menu :index="menu.MenuId + ''" :key="menu.MenuId" v-else>
+        <!-- <el-sub-menu :index="menu.MenuId + ''" :key="menu.MenuId" v-else>
           <template #title>
             <img class="menu-icon" :src="menu.icon_path" alt="" />
             <span class="menu-text">{{ menu.name }}</span>
@@ -55,7 +55,7 @@ const menuList = reactive([
           <el-menu-item v-for="child in menu.children" :key="child.MenuId" :index="child.path" style="text-align: center">
             {{ child.name }}
           </el-menu-item>
-        </el-sub-menu>
+        </el-sub-menu> -->
       </template>
     </el-menu>
   </div>

+ 14 - 0
src/store/index.js

@@ -16,6 +16,7 @@ export default createStore({
       ficcServiceImg:'https://hzstatic.hzinsights.com/static/icon/hzyb/ficc_service_pc.png',
       specialColumnBanner:'https://hzstatic.hzinsights.com/static/icon/hzyb/special_column_banner_pc.png'
     },
+    showLogin:false,//是否显示微信扫码弹窗
     token:token,
     userInfo:null,
     audioData:{
@@ -36,6 +37,11 @@ export default createStore({
     breadCrumbList:breadcrumb,//面包屑数据
   },
   mutations: {
+    //显示微信扫码登陆
+    showLogin(state,e){
+      state.showLogin=true
+    },
+      
     // 获取token
     getToken(state,e){
       console.log(e);
@@ -140,6 +146,14 @@ export default createStore({
         }
       }
 
+      sessionStorage.setItem('breadcrumb',JSON.stringify(state.breadCrumbList))
+    },
+
+    // 修改面包屑
+    modifyBreadCrumb(state,data){
+      let temarr=state.breadCrumbList
+      temarr[temarr.length-1].name=data
+      state.breadCrumbList=temarr
       sessionStorage.setItem('breadcrumb',JSON.stringify(state.breadCrumbList))
     }
 

+ 6 - 0
src/style/global.scss

@@ -239,4 +239,10 @@ img {
       }
     }
   }
+}
+
+// 免责申明弹窗样式
+.disclaimers-box{
+  font-size: 16px;
+  line-height: 1.7;
 }

+ 12 - 5
src/views/activity/Detail.vue

@@ -103,7 +103,14 @@ let audioList=ref([])
 const getAudio=async ()=>{
     const res=await apiActivityAudios({activity_id: Number(route.query.id)})
     if(res.code===200){
-        audioList.value=res.data||[]
+        const arr=res.data||[]
+        audioList.value=arr.map(_item=>{
+            return {
+                name:_item.voiceName,
+                url:_item.voiceUrl,
+                time:_item.voicePlaySeconds
+            }
+        })
     }
 }
 getAudio()
@@ -125,7 +132,7 @@ const goDetail=()=>{
 import { useStore } from "vuex";
 const store=useStore()
 const curAudiourl=computed(()=>{
-    return store.state.audioData.list[store.state.audioData.index]&&store.state.audioData.list[store.state.audioData.index].voiceUrl
+    return store.state.audioData.list[store.state.audioData.index]&&store.state.audioData.list[store.state.audioData.index].url
 })
 const aduioIconDefault=new URL('../../assets/audio-pause-2.png', import.meta.url).href
 const aduioIconPlay=new URL('../../assets/audio-doing.png', import.meta.url).href
@@ -287,10 +294,10 @@ const cancelRegister=async ()=>{
             <div 
                 class="flex audio-item" 
                 v-for="(item,index) in audioList" 
-                :key="item.voiceUrl"
+                :key="item.url"
             >
-                <img @click="handlePlayAudio(index)" :src="curAudiourl==item.voiceUrl?$store.state.audioData.paused?aduioIconPause:aduioIconPlay:aduioIconDefault" alt="">
-                <div :class="['name',curAudiourl==item.voiceUrl&&'name-active']">{{item.voiceName}}</div>
+                <img @click="handlePlayAudio(index)" :src="curAudiourl==item.url?$store.state.audioData.paused?aduioIconPause:aduioIconPlay:aduioIconDefault" alt="">
+                <div :class="['name',curAudiourl==item.url&&'name-active']">{{item.name}}</div>
                 <!-- <span class="time">{{formatAudioTime(item.voicePlaySeconds)}}</span> -->
             </div>
         </div>

+ 12 - 1
src/views/activity/List.vue

@@ -167,7 +167,18 @@ const handleGetAudio=async (item)=>{
     if(!(item.firstActivityTypeId===1&&item.activityState===3&&item.hasPlayBack)) return
     const res=await apiActivityAudios({activity_id:Number(item.activityId)})
     if(res.code===200){
-        store.commit('addAudio',{list:res.data,activityId:item.activityId,index:0})
+        const arr=res.data.map(_item=>{
+            return {
+                name:_item.voiceName,
+                url:_item.voiceUrl,
+                time:_item.voicePlaySeconds
+            }
+        })
+        store.commit('addAudio',{
+            list:arr,
+            activityId:item.activityId,
+            index:0
+        })
     }else if(res.code===403){
         applyAuth(res,'会议',2,'活动列表')
     }

+ 19 - 30
src/views/applyPermission/Apply.vue

@@ -98,14 +98,14 @@ const handleApply=(formEl)=>{
                 <div class="img-box">
                     <img style="width:100%;height:100%" :src="idCardImg" alt="" v-if="idCardImg">
                     <div style="text-align:center" v-else>
-                        <img style="width:35px" src="@/assets/add.png" alt="">
-                        <span class="exp-text">上传名片</span>
+                        <img style="width:40px" src="@/assets/add.png" alt="">
+                        <!-- <span class="exp-text">上传名片</span> -->
                     </div>
                 </div>
             </el-upload>
-            <div class="img-box" style="margin-left:20px">
+            <div class="img-box" style="margin-left:20px;border: none;">
                 <img style="width:100%;height:100%" :src="$store.state.globalImgUrls.idCardExp" alt="">
-                <span class="exp-text">名片示例</span>
+                <!-- <span class="exp-text">名片示例</span> -->
             </div>
         </div>
         <el-form
@@ -114,19 +114,19 @@ const handleApply=(formEl)=>{
             :model="formData"
             :rules="rules"
             ref="formRef"
-            style="max-width: 460px"
+            style="max-width: 500px"
         >
             <el-form-item label="姓名" prop="name">
-                <el-input v-model="formData.name" style="width:350px" placeholder="请输入姓名"></el-input>
+                <el-input v-model="formData.name" style="width:450px" placeholder="请输入姓名"></el-input>
             </el-form-item>
             <el-form-item label="公司名称" prop="companyName">
-                <el-input v-model="formData.companyName" style="width:350px" placeholder="请输入公司名"></el-input>
+                <el-input v-model="formData.companyName" style="width:450px" placeholder="请输入公司名"></el-input>
             </el-form-item>
             <el-form-item label="手机号码" prop="tel" v-if="!$store.state.userInfo.email">
-                <el-input v-model="formData.tel" disabled style="width:350px"></el-input>
+                <el-input v-model="formData.tel" disabled style="width:450px"></el-input>
             </el-form-item>
             <el-form-item label="关注品种" prop="permission">
-                <el-select v-model="formData.permission" multiple collapse-tags placeholder="请选择您的关注品种" style="width:350px">
+                <el-select v-model="formData.permission" multiple collapse-tags placeholder="请选择您的关注品种" style="width:450px">
                     <el-option 
                         v-for="item in varietyList"
                         :key="item.name"
@@ -136,31 +136,29 @@ const handleApply=(formEl)=>{
                 </el-select>
             </el-form-item>
         </el-form>
-        <div class="btn" @click="handleApply(formRef)">立即申请</div>
+        <div class="global-main-btn btn" @click="handleApply(formRef)">立即申请</div>
 
     </div>
 </template>
 <style lang="scss" scoped>
 .apply-permission-page{
-    padding: 30px;
-    border: 1px solid #EBEBEB;
-    border-radius: 4px;
-    margin-top: 40px;
     .tips{
-        font-size: 16px;
+        font-size: 18px;
         text-align: center;
     }
     .img-wrap{
         justify-content: center;
         .img-box{
-            width: 200px;
-            height: 140px;
-            border-radius: 4px;
-            border: 1px solid #EBEBEB;
+            width: 240px;
+            height: 160px;
+            border-radius: 8px;
+            background-color: #FAFBFC;
+            border: 1px solid #F3A52F;
             display: flex;
             justify-content: center;
             align-items: center;
             position: relative;
+            overflow: hidden;
             .exp-text{
                 position: absolute;
                 left: 50%;
@@ -179,17 +177,8 @@ const handleApply=(formEl)=>{
         }
     }
     .btn{
-        width: 180px;
-        height: 36px;
-        background: #DAB37C;
-        border-radius: 4px;
-        margin-left: auto;
-        margin-right: auto;
-        text-align: center;
-        line-height: 36px;
-        color: #fff;
-        font-size: 16px;
-        cursor: pointer;
+        width: 218px;
+        margin: 60px auto 0 auto;
     }
 }
 </style>

+ 3 - 16
src/views/applyPermission/Result.vue

@@ -4,35 +4,22 @@
 
 <template>
     <div class="apply-result-page">
-        <img style="width:96px" :src="$store.state.globalImgUrls.imgSuccess" alt="">
+        <img style="width:96px" src="@/assets/icon-success.png" alt="">
         <p>申请已提交</p>
         <p>请等待销售人员与您联系</p>
-        <div class="btn" @click="$router.replace({path:'/'})">返回</div>
+        <div class="global-main-btn btn" @click="$router.back()">返回</div>
     </div>
 </template>
 
 <style lang="scss" scoped>
 .apply-result-page{
-    padding: 30px;
-    border: 1px solid #EBEBEB;
-    border-radius: 4px;
     margin-top: 40px;
     text-align: center;
     padding-top: 76px;
     font-size: 16px;
     .btn{
         width: 180px;
-        height: 36px;
-        border-radius: 4px;
-        border: 1px solid #DAB37C;
-        text-align: center;
-        line-height: 36px;
-        color: #DAB37C;
-        margin-top: 100px;
-        margin-left: auto;
-        margin-right: auto;
-        margin-bottom: 80px;
-        cursor: pointer;
+        margin: 90px auto 0 auto;
     }
 }
 </style>

+ 110 - 7
src/views/report/ChapterDetail.vue

@@ -1,11 +1,15 @@
 <script setup>
 import {ref,onMounted} from 'vue'
 import {apiChapterDetail,apiChapterTickerValue} from '@/api/report'
+import {apiApplyPermission} from '@/api/user'
+import {apiGetWechatQRCode} from '@/api/common'
+import { ElMessageBox } from 'element-plus'
 import moment from 'moment';
 import AudioBox from './components/AudioBox.vue'
-import { useRoute } from 'vue-router';
+import { useRoute, useRouter } from 'vue-router';
 
 const route=useRoute()
+const router=useRouter()
 
 let chapterId=ref(route.query.chapterId||'') //章节id
 let frompage=ref(route.query.frompage||'')//如果来自报告详情页 则展示底部章节列表
@@ -85,10 +89,48 @@ const getChapterReportDetail=async ()=>{
         if(res.data.auth_ok&&res.data.report_chapter_item.classify_name_first==='晨报'){
           getTickerValue()
         }
+        
+        // 获取详情如果为联系销售根据判断条件是否主动申请一次
+        if(!res.data.auth_ok){
+            if(info.value.permission_check.type=='contact'&&!info.value.permission_check.customer_info.has_apply){
+                if(info.value.permission_check.customer_info.status=='冻结'||(info.value.permission_check.customer_info.status=='试用'&&info.value.permission_check.customer_info.is_suspend==1)){
+                    apiApplyPermission({
+                        company_name:info.value.permission_check.customer_info.company_name,
+                        real_name:info.value.permission_check.customer_info.name,
+                        source:4,
+                        from_page:'报告详情'
+                    }).then(res=>{
+                        if(res.code===200){
+                            console.log('主动申请成功');
+                        }
+                    }) 
+                }
+            }
+        }
     }
 }
 getChapterReportDetail()
 
+//点击底部切换章节
+const handleChangeChapter=(item)=>{
+    chapterId.value=item.report_chapter_id
+    document.body.scrollTop=document.documentElement.scrollTop=0
+    getChapterReportDetail()
+}
+
+// 获取小程序码
+let QRCodeImg=ref('')
+const getQRCodeImg=async ()=>{
+    const res=await apiGetWechatQRCode({
+        CodeScene:JSON.stringify({chapterId:chapterId.value}),
+        CodePage:'pages-report/chapterDetail'
+    })
+    if(res.code===200){
+        QRCodeImg.value=res.data
+    }
+}
+getQRCodeImg()
+
 
 let preViewImgs=ref([])
 let preViewImgIndex=ref(0)
@@ -113,6 +155,49 @@ onMounted(()=>{
     })
 })
 
+// 无权限点击申请
+const handleGoApply=async ()=>{
+    if(info.value.permission_check.type=='apply'){
+        if(info.value.permission_check.customer_info.has_apply){// 已经申请过
+		    const htmlStr=`<p>您已提交过申请,请耐心等待</p>`
+            ElMessageBox({
+                title:'温馨提醒',
+                message:htmlStr,
+                center: true,
+                dangerouslyUseHTMLString: true,
+                confirmButtonText:'知道了',
+                confirmButtonClass:'self-elmessage-confirm-btn'
+            })
+        }else{
+          if(!info.value.permission_check.customer_info.status||info.value.permission_check.customer_info.status!='流失'){
+            router.push('/apply/permission?source=4&fromPage=报告详情')
+          }else{//主动调一次申请权限接口 
+            const res=await apiApplyPermission({
+              company_name:info.value.permission_check.customer_info.company_name,
+              real_name:info.value.permission_check.customer_info.name,
+              source:4,
+              from_page:'报告详情'
+            })
+            if(res.code===200){
+                getChapterReportDetail()
+			    const htmlStr=`<p>申请已提交</p><p>请等待销售人员与您联系</p>`
+                ElMessageBox({
+                    title:'温馨提醒',
+                    message:htmlStr,
+                    center: true,
+                    dangerouslyUseHTMLString: true,
+                    confirmButtonText:'知道了',
+                    confirmButtonClass:'self-elmessage-confirm-btn'
+                })
+            }
+          }
+        }
+                
+    }
+}
+
+let showDisclaimers=ref(false)//显示免责声明
+
 </script>
 
 <template>
@@ -127,7 +212,7 @@ onMounted(()=>{
                     </div>
                     <div class="tips">
                         <span>注:请务必阅读</span>
-                        <span style="color:#F3A52F;margin-left:20px;cursor: pointer;">免责声明</span>
+                        <span style="color:#F3A52F;margin-left:20px;cursor: pointer;" @click="showDisclaimers=true">免责声明</span>
                     </div>
                     <AudioBox :data="audioData" v-if="info.report_chapter_item.video_url&&info.report_chapter_item.video_play_seconds>0"></AudioBox>
                     <div class="abstract" v-if="info.report_chapter_item.abstract">摘要:{{info.report_chapter_item.abstract}}</div>
@@ -164,7 +249,12 @@ onMounted(()=>{
                 <div class="chapter-list-wrap" v-if="frompage=='reportdetail'">
                     <div class="top-name">更多</div>
                     <div class="flex list">
-                        <div :class="['item',item.report_chapter_id==chapterId&&'active']" v-for="item in info.report_chapter_menu_list" :key="item.report_chapter_id">
+                        <div 
+                            :class="['item',item.report_chapter_id==chapterId&&'active']" 
+                            v-for="item in info.report_chapter_menu_list" 
+                            :key="item.report_chapter_id"
+                            @click="handleChangeChapter(item)"
+                        >
                             <img :src="item.report_chapter_type_thumb" alt="">
                             <span>{{item.report_chapter_type_name}}</span>
                         </div>
@@ -172,17 +262,17 @@ onMounted(()=>{
                 </div>
 
             </div>
-            <div class="right-aside-box">
+            <div class="right-aside-box" v-if="info.auth_ok">
                 <div class="fix-top">
                 <div class="share-box">
                     <div class="label">分享</div>
                     <el-popover 
-                        :width="120" 
+                        :width="200" 
                         popper-style="box-shadow: rgb(14 18 22 / 35%) 0px 10px 38px -10px, rgb(14 18 22 / 20%) 0px 10px 20px -15px; padding: 20px;"
                     >
                         <template #reference><div class="icon"></div></template>
                         <template #default>
-                            <img src="" class="share-xcx-img" alt="" style="width: 80px;height: 80px;">
+                            <img :src="QRCodeImg" class="share-xcx-img" alt="" style="width: 150px;display: block;margin: 0 auto;">
                         </template>
                     </el-popover>
                 </div>
@@ -217,11 +307,20 @@ onMounted(()=>{
         @close="showPreViewImg=false"
         :url-list="preViewImgs"
     />
+
+    <!-- 免责申明 -->
+    <el-dialog v-model="showDisclaimers" title="免责声明" center draggable width="40%">
+        <div class="disclaimers-box">
+            <div style="margin-bottom:10px">1、本报告仅供弘则弥道(上海)投资咨询有限公司正式签约的机构客户使用,不会仅因接收人/接受机构收到本报告而将其视为客户。</div>
+            <div style="margin-bottom:10px">2、本报告根据国际和行业通行的准则,以合法渠道获得这些信息,尽可能保证可靠、准确和完整,但并不保证报告所述信息的准确性和完整性,也不保证本报告所包含的信息或建议在本报告发出后不会发生任何变更。本报告中所提供的信息仅供参考。</div>
+            <div style="margin-bottom:10px">3、报告中的内容不对投资者做出的最终操作建议做任何的担保,也没有任何形式的分享投资收益或者分担投资损失的书面或口头承诺。不作为客户在投资、法律、会计或税务等方面的最终操作建议,也不作为道义的、责任的和法律的依据或者凭证,无论是否已经明示或者暗示。</div>
+            <div style="margin-bottom:10px">4、在任何情况下,本公司不对客户/接受人/接受机构因使用报告中内容所引致的一切损失负责任,客户/接受人/接受机构需自行承担全部风险。</div>
+        </div>
+    </el-dialog>
 </template>
 
 <style lang="scss" scoped>
 .report-chapter-detail-page{
-
     .content-box{
         flex: 1;
         padding-right: 30px;
@@ -295,6 +394,8 @@ onMounted(()=>{
         margin-top: -140px;
         padding-top: 140px;
         min-height: 200px;
+        position: relative;
+        z-index: 5;
         background: linear-gradient(360deg, #FFFFFF 60%, rgba(255, 255, 255, 0) 88%);
         .btn{
             width: 218px;
@@ -330,6 +431,8 @@ onMounted(()=>{
                 height: 36px;
                 background-color: #F7F7F7;
                 border-radius: 4px;
+                margin-right: 20px;
+                margin-bottom: 20px;
                 cursor: pointer;
                 img{
                     width: 20px;

+ 95 - 28
src/views/report/Detail.vue

@@ -1,9 +1,11 @@
 <script setup>
 import {onMounted, ref} from 'vue'
+import { ElMessageBox } from 'element-plus'
 import moment from 'moment';
 import 'moment/dist/locale/zh-cn'
 import AudioBox from './components/AudioBox.vue'
 import {apiReportDetail} from '@/api/report'
+import {apiGetWechatQRCode} from '@/api/common'
 import { useRoute, useRouter } from 'vue-router';
 
 moment.locale('zh-cn')
@@ -30,7 +32,23 @@ const getReportDetail=async ()=>{
             reportId:res.data.report_info.report_id
         }
         document.title = res.data.report_info.classify_name_first
-
+        // 获取详情如果为联系销售根据判断条件是否主动申请一次
+        if(!res.data.auth_ok){
+            if(info.value.permission_check.type=='contact'&&!info.value.permission_check.customer_info.has_apply){
+                if(info.value.permission_check.customer_info.status=='冻结'||(info.value.permission_check.customer_info.status=='试用'&&info.value.permission_check.customer_info.is_suspend==1)){
+                    apiApplyPermission({
+                        company_name:info.value.permission_check.customer_info.company_name,
+                        real_name:info.value.permission_check.customer_info.name,
+                        source:4,
+                        from_page:'报告详情'
+                    }).then(res=>{
+                        if(res.code===200){
+                            console.log('主动申请成功');
+                        }
+                    }) 
+                }
+            }
+        }
     }
 }
 getReportDetail()
@@ -75,11 +93,68 @@ const goChapterDetail=(item)=>{
     router.push({
         path:'/report/chapterdetail',
         query:{
-            chapterId:item.report_chapter_id
+            chapterId:item.report_chapter_id,
+            frompage:'reportdetail'
         }
     })
 }
 
+// 点击申请
+const handleGoApply=async ()=>{
+    if(info.value.permission_check.type=='apply'){
+        if(info.value.permission_check.customer_info.has_apply){// 已经申请过
+            const htmlStr=`<p>您已提交过申请,请耐心等待</p>`
+            ElMessageBox({
+                title:'温馨提醒',
+                message:htmlStr,
+                center: true,
+                dangerouslyUseHTMLString: true,
+                confirmButtonText:'知道了',
+                confirmButtonClass:'self-elmessage-confirm-btn'
+            })
+        }else{
+            if(!info.value.permission_check.customer_info.status||info.value.permission_check.customer_info.status!='流失'){
+                router.push('/apply/permission?source=4&fromPage=报告详情')
+            }else{//主动调一次申请权限接口 
+                const res=await apiApplyPermission({
+                    company_name:info.value.permission_check.customer_info.company_name,
+                    real_name:info.value.permission_check.customer_info.name,
+                    source:4,
+                    from_page:'报告详情'
+                })
+                if(res.code===200){
+                    getReportDetail()
+                    const htmlStr=`<p>申请已提交</p><p>请等待销售人员与您联系</p>`
+                    ElMessageBox({
+                        title:'温馨提醒',
+                        message:htmlStr,
+                        center: true,
+                        dangerouslyUseHTMLString: true,
+                        confirmButtonText:'知道了',
+                        confirmButtonClass:'self-elmessage-confirm-btn'
+                    })
+                }
+            }
+        }     
+    }
+}
+
+// 获取小程序码
+let QRCodeImg=ref('')
+const getQRCodeImg=async ()=>{
+    const res=await apiGetWechatQRCode({
+        CodeScene:JSON.stringify({reportId:reportId.value}),
+        CodePage:'pages-report/reportDetail'
+    })
+    if(res.code===200){
+        QRCodeImg.value=res.data
+    }
+}
+getQRCodeImg()
+
+
+let showDisclaimers=ref(false)//显示免责声明
+
 </script>
 
 <template>
@@ -114,10 +189,10 @@ const goChapterDetail=(item)=>{
                     </div>
                     <!-- 无权限 -->
                     <div class="no-auth-wrap" v-if="!info.auth_ok">
-                        <img class="img" src="https://hzstatic.hzinsights.com/static/icon/hzyb/activity_no_auth.png" mode="widthFix" />
+                        <img class="img" width="400" src="https://hzstatic.hzinsights.com/static/icon/hzyb/activity_no_auth.png" mode="widthFix" />
                         <div class="apply-box" v-if="info.permission_check.type=='apply'">
                             <div>您暂无权限查看报告,若想查看请申请开通</div>
-                            <div class="btn" @click="handleGoApply">立即申请</div>
+                            <div class="global-main-btn btn" @click="handleGoApply">立即申请</div>
                         </div>
                         <div class="apply-box" v-else>
                             <div>您暂无权限查看报告 </div>
@@ -134,7 +209,7 @@ const goChapterDetail=(item)=>{
                     </div>
                     <div class="tips">
                         <span>注:请务必阅读</span>
-                        <span style="color:#F3A52F;margin-left:20px;cursor: pointer;">免责声明</span>
+                        <span style="color:#F3A52F;margin-left:20px;cursor: pointer;" @click="showDisclaimers=true">免责声明</span>
                     </div>
                     <!-- 音频模块 -->
                     <AudioBox :data="audioData" v-if="info.report_info.video_url&&info.report_info.video_play_seconds>0"></AudioBox>
@@ -149,7 +224,7 @@ const goChapterDetail=(item)=>{
                     <div class="no-auth-wrap" v-if="!info.auth_ok">
                         <div class="apply-box" v-if="info.permission_check.type=='apply'">
                             <div>您暂无权限查看报告,若想查看请申请开通</div>
-                            <div class="btn" @click="handleGoApply">立即申请</div>
+                            <div class="global-main-btn btn" @click="handleGoApply">立即申请</div>
                         </div>
                         <div class="apply-box" v-else>
                             <div>您暂无权限查看报告 </div>
@@ -163,12 +238,12 @@ const goChapterDetail=(item)=>{
                 <div class="share-box">
                     <div class="label">分享</div>
                     <el-popover 
-                        :width="120" 
+                        :width="200" 
                         popper-style="box-shadow: rgb(14 18 22 / 35%) 0px 10px 38px -10px, rgb(14 18 22 / 20%) 0px 10px 20px -15px; padding: 20px;"
                     >
                         <template #reference><div class="icon"></div></template>
                         <template #default>
-                            <img src="" class="share-xcx-img" alt="" style="width: 80px;height: 80px;">
+                            <img :src="QRCodeImg" class="share-xcx-img" alt="" style="width: 150px;display: block;margin: 0 auto;">
                         </template>
                     </el-popover>
                 </div>
@@ -203,6 +278,16 @@ const goChapterDetail=(item)=>{
         @close="showPreViewImg=false"
         :url-list="preViewImgs"
     />
+
+    <!-- 免责申明 -->
+    <el-dialog v-model="showDisclaimers" title="免责声明" center draggable width="40%">
+        <div class="disclaimers-box">
+            <div style="margin-bottom:10px">1、本报告仅供弘则弥道(上海)投资咨询有限公司正式签约的机构客户使用,不会仅因接收人/接受机构收到本报告而将其视为客户。</div>
+            <div style="margin-bottom:10px">2、本报告根据国际和行业通行的准则,以合法渠道获得这些信息,尽可能保证可靠、准确和完整,但并不保证报告所述信息的准确性和完整性,也不保证本报告所包含的信息或建议在本报告发出后不会发生任何变更。本报告中所提供的信息仅供参考。</div>
+            <div style="margin-bottom:10px">3、报告中的内容不对投资者做出的最终操作建议做任何的担保,也没有任何形式的分享投资收益或者分担投资损失的书面或口头承诺。不作为客户在投资、法律、会计或税务等方面的最终操作建议,也不作为道义的、责任的和法律的依据或者凭证,无论是否已经明示或者暗示。</div>
+            <div style="margin-bottom:10px">4、在任何情况下,本公司不对客户/接受人/接受机构因使用报告中内容所引致的一切损失负责任,客户/接受人/接受机构需自行承担全部风险。</div>
+        </div>
+    </el-dialog>
 </template>
 
 <style lang="scss" scoped>
@@ -275,6 +360,8 @@ const goChapterDetail=(item)=>{
         margin-top: -140px;
         padding-top: 140px;
         min-height: 200px;
+        position: relative;
+        z-index: 5;
         background: linear-gradient(360deg, #FFFFFF 60%, rgba(255, 255, 255, 0) 88%);
         .btn{
             width: 218px;
@@ -359,26 +446,6 @@ const goChapterDetail=(item)=>{
                 }
             }
         }
-        .no-auth-box{
-            text-align: center;
-            font-size: 32px;
-            color: #E3B377;
-            img{
-                width: 100%;
-                margin-bottom: 50px;
-            }
-            .btn{
-                width: 90%;
-                margin-left: auto;
-                margin-right: auto;
-                line-height: 80px;
-                background-color: #E6B77D;
-                border-radius: 4px;
-                color: #fff;
-                margin-top: 100px;
-                display: block;
-            }
-        }
     }
 }
 </style>

+ 5 - 2
src/views/report/Index.vue

@@ -1,5 +1,5 @@
 <script setup>
-import { apiReportIndexPageAuthList, apiReportIndexPageList,apiReportIndexNewbanner } from '@/api/report'
+import { apiReportIndexPageAuthList, apiReportIndexPageList,apiReportIndexNewbanner,apiReportIndexNew } from '@/api/report'
 import { onMounted, reactive, ref } from "vue"
 import Search from "@/components/Search.vue"
 import SelfList from '@/components/SelfList.vue'
@@ -127,7 +127,10 @@ const onLoad=()=>{
 
 // 获取上新公告
 const getNewAnnounce=async ()=>{
-  // const res1=await apiReportIndexNewbanner()
+  const res1=await apiReportIndexNewbanner()
+  if(res1.code===200){
+    const res2=await apiReportIndexNew({ClassifyId:res1.data.ClassifyId})
+  }
 }
 getNewAnnounce()
 

+ 1 - 0
src/views/report/Search.vue

@@ -36,6 +36,7 @@ const handleSearch=(e)=>{
     listState.list=[]
     listState.finished=false
     listState.keyword=e||''
+    if(!e) return
     getSearchList()
 }
 

+ 2 - 0
src/views/report/specialColumn/Detail.vue

@@ -18,6 +18,7 @@ const getSpecialColumnDetail=async ()=>{
     if(res.code===200){
         info.value=res.data
         document.title=res.data.classify_name_second
+        store.commit('modifyBreadCrumb',res.data.classify_name_second)
     }
 }
 getSpecialColumnDetail()
@@ -194,6 +195,7 @@ const handlePlayAudio=(item)=>{
             border-radius: 50%;
             object-fit: cover;
             margin-right: 13px;
+            flex-shrink: 0;
         }
         .name{
             font-size: 20px;