Эх сурвалжийг харах

Merge branch 'cygx_5.0' of http://8.136.199.33:3000/Karsa/raiwechat_link_h5 into cygx_5.1

# Conflicts:
#	src/api/cygx/api.js
#	src/views/cygx/raiReportDtl.vue
bd 3 жил өмнө
parent
commit
967637cb55

+ 2 - 1
package.json

@@ -20,7 +20,8 @@
     "normalize.css": "^8.0.1",
     "vant": "^3.3.4",
     "vue": "^3.2.16",
-    "vue-router": "^4.0.12"
+    "vue-router": "^4.0.12",
+    "vuex": "^4.0.2"
   },
   "devDependencies": {
     "@vitejs/plugin-vue": "^1.9.3",

+ 8 - 0
src/api/cygx/api.js

@@ -51,4 +51,12 @@ export const FreeButton = {
   userIsShowAlert: (params) => {
     return get("/user/isShow/alert", params);
   },
+  /* 页面复制监听*/
+  researcharticleHotList: (params) => {
+    return get("/research/article/hotList", params, 1);
+  },
+  /* 收藏 ArticleId*/
+  collectRpt: (params) => {
+    return post("/article/collect", params, 0);
+  },
 };

+ 15 - 0
src/api/hzyb/common.js

@@ -6,4 +6,19 @@ export const getWxConfig=(params)=>{
     const url=window.location.href
     console.log(url)
     return get('/wechat/getWxJsConf',{url:url,...params})
+}
+
+/**
+ * 获取海报
+ * @param code_page 分享海报小程序页面地址
+ * @param code_scene 小程序页面参数
+ * @param source 来源 activity_detail(活动详情) activity_list(活动列表)
+ *                    special_column_list(专栏列表) special_column_detail(专栏详情)
+ *                    report_list(报告列表) report_detail(报告详情)
+ *                    chart_list(图库列表) chart_detail(图库详情)
+ * @param version 
+ * @param pars 生成海报需要的页面参数
+ */
+export const apiGetPoster=params=>{
+    return post('/public/get_share_poster',{version:'3.0',...params})
 }

+ 11 - 8
src/api/hzyb/http.js

@@ -24,14 +24,17 @@ _axios.interceptors.request.use(
   function (config) {
     // Do something before request is sent
     // 设置loading
-    if (LOADINGCOUNT === 0) {
-      LOADING = Toast.loading({
-        message: "loading...",
-        duration: 0,
-        forbidClick: true,
-      });
+    if(config.url!='/public/get_share_poster'){
+      if (LOADINGCOUNT === 0) {
+        LOADING = Toast.loading({
+          message: "loading...",
+          duration: 0,
+          forbidClick: true,
+        });
+      }
+      LOADINGCOUNT++;
     }
-    LOADINGCOUNT++;
+    
     
     config.headers.Authorization = localStorage.getItem('hzyb-token')||''
     return config;
@@ -59,7 +62,7 @@ _axios.interceptors.response.use(
     }else{
       data=response.data
     }
-    if(data.code!==200){
+    if(![200,403].includes(data.code)){
       setTimeout(() => {
         Toast(data.msg)
       }, 10);

+ 23 - 0
src/api/hzyb/report.js

@@ -12,3 +12,26 @@ export const apiGetWeekReportDetail=params=>{
     return get('/report/research_report_chapter',params)
 }
 
+/**
+ * 研报详情
+ * @param report_id 
+ */
+export const apiReportDetail=params=>{
+    return get('/report/detail',params)
+}
+
+/**
+ * 章节详情
+ * @param report_chapter_id
+ */
+export const apiChapterDetail=params=>{
+    return get('/report/chapter/detail',params)
+}
+
+/**
+ * 章节详情中指标数据
+ * @param report_chapter_id
+ */
+export const apiChapterTickerValue=params=>{
+    return get('/report/chapter/ticker',params)
+}

+ 14 - 0
src/api/hzyb/user.js

@@ -7,4 +7,18 @@ import {get,post} from './http'
  */
 export const apiUserInfo=(params)=>{
 	return get('/user/info',params)
+}
+
+/**
+ * 用户权限申请
+ * @param business_card_url 名片地址
+ * @param company_name 公司名
+ * @param permission 选择的权限
+ * @param real_name 姓名
+ * @param source 来源:我的1、活动2、图库3、研报4
+ * @param source_agent 来源平台:1:小程序、2:pc
+ * @param from_page 来源页面: '活动列表'、'活动详情'等
+ */
+ export const apiApplyPermission=params=>{
+	return post('/user/apply',{...params,source_agent:1})
 }

BIN
src/assets/hzyb/loading.png


BIN
src/assets/hzyb/report/audio-change-small-grey.png


BIN
src/assets/hzyb/report/audio-change-small.png


BIN
src/assets/hzyb/report/audio-pause-small.png


BIN
src/assets/hzyb/report/audio-pause.png


BIN
src/assets/hzyb/report/audio-play-small.png


BIN
src/assets/hzyb/report/audio-play.png


BIN
src/assets/hzyb/report/back-top.png


BIN
src/assets/hzyb/share-poster-chart-icon.png


BIN
src/assets/hzyb/share-poster-icon.png


+ 2 - 2
src/main.js

@@ -1,9 +1,9 @@
 import { createApp } from 'vue'
 import App from './App.vue'
 import router from './router'
+import store from './store'
 import 'normalize.css'
 import './style/common.scss'
 import '@vant/touch-emulator';//vant 
 
-
-createApp(App).use(router).mount('#app')
+createApp(App).use(router).use(store).mount('#app')

+ 18 - 0
src/router/hzyb/index.js

@@ -35,4 +35,22 @@ export const hzybRoutes=[
             }
         ]
     },
+    // 报告模块
+    {
+        path:'/hzyb/report',
+        name:'hzybReport',
+        component: () => import("@/views/hzyb/Index.vue"),
+        children:[
+            {
+                path:"detail",
+                name:"hzybReportDetailNew",
+                component: () => import("@/views/hzyb/report/Detail.vue"),
+            },
+            {
+                path:"chapterdetail",
+                name:"hzybChapterDetail",
+                component: () => import("@/views/hzyb/report/ChapterDetail.vue"),
+            },
+        ]
+    }
 ]

+ 24 - 0
src/store/index.js

@@ -0,0 +1,24 @@
+import { createStore, Store } from "vuex";
+import hzyb from "./modules/hzyb";
+
+const store = createStore({
+  state: {
+    userData: {
+      CompanyCode: "",
+      CompanyName: "",
+      Email: "",
+      Sign: null,
+    },
+  },
+  mutations: {
+    getUserData(state, payload) {
+      state.userData = payload;
+    },
+  },
+  actions: {},
+  modules: {
+    hzyb
+  }
+});
+
+export default store;

+ 45 - 0
src/store/modules/hzyb.js

@@ -0,0 +1,45 @@
+const hzybStore={
+    namespaced: true,
+    state:{
+        audioData:{
+            INS:null,
+            url:'',//音频链接
+            videoTime:0,//音频时长
+            videoName:'',//音频名称
+            videoImg:'',//音频图片
+            paused:true,//音频是否在暂停
+            show:false,// 显示音频弹窗
+        }
+    },
+    mutations: {
+        // 点击播放音频
+        addAudio(state,e){
+            state.audioData.url=e.video_url
+            state.audioData.videoTime=e.video_play_seconds
+            state.audioData.videoName=e.video_name
+            state.audioData.videoImg=e.video_img
+            state.audioData.INS.play()
+            state.audioData.show=true
+        },
+        // 更新音频播放状态
+        upateAudioStatus(state,e){
+            if(e==='end'){
+                state.audioData.url=''
+                state.audioData.show=false
+            }else if(e==='play'){
+                state.audioData.paused=false
+            }else if(e==='paused'){
+                state.audioData.paused=true
+            }
+        },
+        //关闭音频弹窗
+        closeAudioPop(state){
+            state.audioData.show=false
+        },
+        showAudioPop(state){
+            state.audioData.show=true
+        }
+    }
+}
+
+export default hzybStore

+ 360 - 0
src/views/cygx/index.scss

@@ -0,0 +1,360 @@
+.container-cygx {
+   @media screen and (min-width:790px) {
+    width: 1200px;
+    margin:  0 auto;
+  }
+  padding: 54px 34px 34px 34px;
+  position: relative;
+  z-index: 5;
+  @media screen and (min-width:790px) {
+    padding: 25PX 17PX 17PX;
+  }
+  .z-index-content {
+    position: relative;
+    z-index: 5;
+  }
+  .host-collect {
+    padding-bottom: 100px;
+    h4 {
+      font-size: 28px;
+      @media screen and (min-width:790px) {
+        font-size: 14px;
+      }
+    }
+    @media screen and (min-width:790px) {
+      padding-bottom: 50PX;
+    }
+    background-color: #fff;
+    .host-content {
+      border-top: 1px solid #ECECEC;
+      .host-title {
+        margin: 30px 0;
+        color: #333;
+        font-size: 28px;
+        font-weight: 500;
+        @media screen and (min-width:790px) {
+          margin: 15PX 0;
+          font-size: 14px;
+        }
+      }
+      .item-more {
+        display:flex;
+        align-items: center;
+        justify-content: space-between;
+        color: #CECECE;
+        font-size: 24px;
+        margin-bottom: 30px;
+        @media screen and (min-width:790px) {
+          font-size: 12PX;
+          margin-bottom: 15PX;
+        }
+      }
+      .pv-ollect {
+        display:flex;
+        align-items: center;
+        justify-content: space-between;
+        width: 30%;
+        img {
+          width: 21px;
+          height: 21px;
+          margin-left: 10px;
+          @media screen and (min-width:790px) {
+            width: 12PX;
+            height: 12PX;
+            margin-left: 5PX;
+          }
+        }
+        .pv {
+          height: 16px;
+          @media screen and (min-width:790px) {
+            height: 8PX;
+          }
+        }
+      }
+    }
+  }
+  .search {
+    width: 100%;
+    padding: 20px 20px;
+    line-height: 70px;
+    position: fixed;
+    top: 0;
+    left: 0;
+    background: #fff;
+    z-index: 9;
+    @media screen and (min-width:790px) {
+     padding: 10PX 10PX;
+     line-height: 35PX;
+    }
+    .search-box {
+      display: flex;
+      align-items: center;
+      padding-left: 20px;
+      width: 100%;
+      height: 70px;
+      border-radius: 35px;
+      background: #f6f6f6;
+      color: #8d8d8d;
+      font-size: 24px;
+      @media screen and (min-width:790px) {
+      padding-left: 10PX;
+      height: 25PX;
+      border-radius: 18PX;
+      font-size: 12PX;
+    }
+    }
+  }
+  .content-top {
+    .report-research {
+      display: flex;
+      align-items: center;
+      justify-content:space-between;
+      font-size: 28px;
+      font-weight: 500;
+      color: #333;
+      margin-bottom: 20px;
+       @media screen and (min-width:790px) {
+        font-size: 14PX;
+        margin-bottom: 10PX;
+      }
+      img {
+        width: 81px;
+        height: 81px;
+        overflow: hidden;
+        margin-right: 30px;
+        @media screen and (min-width:790px) {
+        width: 40PX;
+        height: 40PX;
+        margin-right: 15PX;
+      }
+      }
+      .time {
+        font-size: 24px;
+        color: #999999;
+        font-weight: 300;
+        @media screen and (min-width:790px) {
+        font-size: 12PX;
+      }
+      }
+      .is-follow {
+        padding: 5px 28px;
+        background-color:#3385FF ;
+        border-radius:59px;
+        color: #fff;
+        @media screen and (min-width:790px) {
+        padding: 3PX 14PX;
+        border-radius:30PX;
+      }
+      }
+      .follow-cancel {
+        background: #F0F0F0;
+        color: #999999;
+      }
+    }
+    .report-title {
+      font-size: 34px;
+      font-weight: bold;
+      color: #4a4a4a;
+      margin: 60px 0 20px;
+  @media screen and (min-width:790px) {
+       margin: 30PX 0 10PX;
+       font-size: 18PX;
+  }
+    }
+    .report-text {
+      color: #999999;
+      font-size: 28px;
+  @media screen and (min-width:790px) {   
+       font-size: 14PX;
+  }
+      .seller-list {
+        margin: 20px 0;
+ @media screen and (min-width:790px) {
+        margin: 10PX 0;
+  }
+      }
+      .report_desc {
+        display: flex;
+        justify-content: space-between;
+      }
+      .tip {
+        color: #3385ff;
+      }
+      .container-abstract {
+        margin: 40px 0 20px;
+        padding-bottom: 40px;
+        border-bottom: 2px dashed #999;
+        position: relative;
+        line-height: 44px;
+        color: #333;
+        &::before {
+          content: "";
+          position: absolute;
+          top: 0;
+          left: 0;
+          width: 8px;
+          height: 44px;
+          background: #2a65f5;
+        }
+    @media screen and (min-width:790px) {
+        margin: 20PX 0 10PX;
+        padding-bottom: 20PX;
+        border-bottom: 1PX dashed #999;
+        position: relative;
+        line-height: 22PX;
+         &::before {
+          content: "";
+          position: absolute;
+          top: 0;
+          left: 0;
+          width: 4PX;
+          height: 22PX;
+          background: #2a65f5;
+        }
+  }
+      }
+    }
+  }
+  .report-link {
+    font-size: 28px;
+    line-height: 80px;
+      @media screen and (min-width:790px) {   
+      font-size: 14PX;
+     line-height: 40PX;
+    }
+  }
+  .detail-report {
+    @media screen and (min-width:790px) { 
+      padding-bottom: 65PX;
+      font-size: 14PX !important;
+    }
+    
+    p,
+    span {
+      font-size: 28px !important;
+    @media screen and (min-width:790px) {
+      font-size: 14PX !important;
+    }
+    }
+    img {
+      width: 100% !important;
+    }
+    a {
+      color: #333;
+    }
+    table {
+      border-collapse: collapse;
+      width: 100% !important;
+      margin-left: 0 !important;
+    }
+    tr td,
+    th {
+      border: 1px solid #333;
+    @media screen and (min-width:790px) {
+      font-size: 1PX !important;
+    }
+    }
+  }
+  pre {
+    width: 100%;
+    overflow-y: auto;
+    overflow-x: hidden;
+    outline: none;
+    border: 0;
+    white-space: pre-wrap;
+    word-break: normal;
+  }
+  .btn-returntop {
+    position: fixed;
+    right: 40px;
+    bottom: 290px;
+    width: 88px;
+    height: 88px;
+    z-index: 10;
+  @media screen and (min-width:790px) {
+    right: 20PX;
+    bottom: 145PX;
+    width: 44PX;
+    height: 44PX;
+  }
+  }
+  .fixed_cont {
+    position: fixed;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    display: flex;
+    justify-content: space-around;
+    border-top: 1px solid #ddd;
+    padding-bottom: calc(5px + constant(safe-area-inset-bottom));
+    padding-bottom: calc(5px + env(safe-area-inset-bottom));
+    background-color: #fff;
+    z-index: 9;
+    box-sizing: border-box;
+    .handle-item {
+      padding-top: 14px;
+      text-align: center;
+      line-height: 33px;
+      font-size: 20px;
+      color: #888888;
+
+      img {
+        width: 44px;
+        height: 44px;
+        padding: 0;
+        margin: 0;
+      }
+      div {
+        padding: 0;
+        margin: 0;
+      }
+    }
+  }
+}
+.no-cv {
+  -webkit-user-select: none;
+  -khtml-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+#tutorial {
+  position: absolute;
+  top: 0;
+  left: 0;
+  z-index: 1;
+  width: 100%;
+  height: 100%;
+  opacity: 0.1;
+  // transform: translateX(130px) rotate(-38deg);
+}
+.van-dialog--round-button .van-dialog__footer {
+  border-top: 1px solid rgba(0, 0, 0, 0.1) !important;
+  padding: 0 !important;
+  .van-button--warning {
+    color: #333 !important;
+    border-right: 1px solid rgba(0, 0, 0, 0.1) !important;
+  }
+  .van-button--danger {
+    color: #3385ff !important;
+  }
+  .van-button--warning,
+  .van-button--danger {
+    height: 80px !important;
+    border-radius: 0 !important;
+  }
+  .van-goods-action-button--first {
+    border-right: 1px solid rgba(0, 0, 0, 0.1) !important;
+  }
+}
+.van-icon-search {
+  font-size: 28px;
+  margin-right: 10px;
+   @media screen and (min-width:790px) {
+    font-size: 14PX;
+    margin-right: 5PX;
+  }
+}
+.detail-bottom {
+  padding-bottom: 130px;
+}

+ 74 - 288
src/views/cygx/raiReportDtl.vue

@@ -11,17 +11,30 @@
       <div class="content-top">
         <div class="report-title">{{ reportInfo.Title }}</div>
         <div class="report-text">
-          <div class="report_desc">
-            <span class="author">{{ reportInfo.Department }}</span>
-            <span>{{ reportInfo.PublishDate }}</span>
-          </div>
-          <div class="seller-list" v-if="!reportInfo.IsResearch">
-            <span>联系人:</span>
-            <span v-for="(item, index) in reportInfo.SellerList" :key="index"> {{ item.SellerName }}({{ item.SellerMobile }})&nbsp;&nbsp; </span>
-          </div>
-          <div class="seller-list" v-else>
-            <span>作者:{{ reportInfo.SellerAndMobile }} </span>
-          </div>
+          <template v-if="!reportInfo.IsResearch">
+            <div class="report_desc">
+              <span class="author">{{ reportInfo.Department }}</span>
+              <span>{{ reportInfo.PublishDate }}</span>
+            </div>
+            <div class="seller-list">
+              <span>联系人:</span>
+              <span v-for="(item, index) in reportInfo.SellerList" :key="index"> {{ item.SellerName }}({{ item.SellerMobile }})&nbsp;&nbsp; </span>
+            </div>
+          </template>
+          <template v-else>
+            <div class="report-research">
+              <div style="display: flex">
+                <img :src="reportInfo.DepartmentImgUrl" />
+                <div class="research-author">
+                  <p>{{ reportInfo.SellerAndMobile }}</p>
+                  <p class="time">{{ reportInfo.PublishDate }}</p>
+                </div>
+              </div>
+              <div @click="attentionBtn" class="is-follow" :class="reportInfo.IsFollow ? 'follow-cancel' : ''">
+                {{ reportInfo.IsFollow ? "取消关注" : "+ 关注" }}
+              </div>
+            </div>
+          </template>
           <div>注:请务必阅读<span class="tip" @click="showTips = true"> &nbsp;免责声明</span></div>
           <div class="container-abstract">&nbsp;&nbsp;摘要:&nbsp;{{ reportInfo.Abstract }}</div>
         </div>
@@ -30,9 +43,29 @@
         报告全文:
         <span style="color: #0808e5" @click="downloadFile">(PDF格式报告下载.pdf)</span>
       </div>
-      <div class="detail-report">
+      <div class="detail-report" :class="reportInfo.IsResearch ? '' : 'detail-bottom'">
         <div id="report-content" v-html="reportInfo.Body"></div>
       </div>
+      <div class="host-collect" v-if="reportInfo.IsResearch && reportResearch.length">
+        <h4>相关热门收藏:</h4>
+        <div class="host-content" v-for="item in reportResearch" :key="item.ArticleId">
+          <p class="host-title" @click="goDetail(item)">{{ item.Title }}</p>
+          <div class="item-more">
+            <p>{{ item.PublishDate }}</p>
+            <div class="pv-ollect">
+              <div>
+                <img class="pv" src="https://hzchart.oss-cn-shanghai.aliyuncs.com/cygx/czbk/examine_icon.png" />
+                {{ item.Pv }}
+              </div>
+              <div @click="collectClick(item)">
+                <img v-if="item.IsCollect" src="https://hzchart.oss-cn-shanghai.aliyuncs.com/cygx/czbk/collect_act.png" />
+                <img v-else src="https://hzchart.oss-cn-shanghai.aliyuncs.com/cygx/czbk/collect_ico.png" />
+                {{ item.CollectNum }}人收藏
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
     </div>
     <div class="btn-returntop">
       <img src="~@/assets/cygx/returntop.png" @click="scrolltop" style="width: 40px" />
@@ -52,12 +85,11 @@
         <img src="@/assets/cygx/quiz_ico.png" class="img_ico" />
         <div>提问</div>
       </div>
-      <div class="handle-item" @click="attentionBtn" v-if="reportInfo.IsResearch">
+      <!-- <div class="handle-item" @click="attentionBtn" v-if="reportInfo.IsResearch">
         <img src="@/assets/cygx/attention_act.png" class="img_ico" v-if="reportInfo.IsFollow" />
         <img src="@/assets/cygx/attention_ico.png" class="img_ico" v-else />
         <div>{{ `${reportInfo.FollowNum}人关注` }}</div>
-      </div>
-
+      </div> -->
       <div class="handle-item" @click="collectHandle">
         <img src="@/assets/cygx/collect_act.png" class="img_ico" v-if="reportInfo.IsCollect" />
         <img src="@/assets/cygx/collect_ico.png" class="img_ico" v-else />
@@ -81,6 +113,7 @@ const router = useRouter();
 const route = useRoute();
 const state = reactive({
   reportInfo: {},
+  reportResearch: [],
 });
 const rerportId = ref(null);
 const from_type = ref(null);
@@ -171,6 +204,13 @@ const applyHandle = () => {
 const scrolltop = () => {
   document.body.scrollTop = document.documentElement.scrollTop = 0;
 };
+/* 文章相关热门 */
+const researcharticleHotList = async () => {
+  const res = await RaiApi.researcharticleHotList({ ArticleId: Number(rerportId.value) });
+  if (res.Ret === 200) {
+    state.reportResearch = res.Data.List || [];
+  }
+};
 //关注作者事件
 const attentionBtn = () => {
   RaiApi.fllowDepartment({
@@ -219,17 +259,30 @@ const collectHandle = () => {
   }).then((res) => {
     if (res.Ret === 200) {
       state.reportInfo.IsCollect = !state.reportInfo.IsCollect;
-      if (state.reportInfo.IsCollection == 1) {
+      if (res.Data.Status == 2) {
         state.reportInfo.CollectionNum -= 1;
-        state.reportInfo.IsCollection = 0;
       } else {
         state.reportInfo.CollectionNum += 1;
-        state.reportInfo.IsCollection = 1;
       }
       Toast(res.Msg);
     }
   });
 };
+/* 文章相关热门跳转 */
+const goDetail = (item) => {
+  wx.miniProgram.navigateTo({
+    url: "/pageMy/reportDetail/reportDetail?id=" + item.ArticleId,
+  });
+};
+/* 文章相关热门收藏 */
+const collectClick = async (item) => {
+  const res = await RaiApi.collectRpt({ ArticleId: item.ArticleId });
+  if (res.Ret === 200) {
+    item.IsCollect = !item.IsCollect;
+    item.IsCollect ? (item.CollectNum += 1) && Toast("收藏成功") : (item.CollectNum -= 1);
+    !item.IsCollect && Toast("已取消收藏");
+  }
+};
 /* 复制 */
 const copyMonitor = () => {
   RaiApi.pageHistoryCopy({
@@ -337,279 +390,12 @@ onMounted(() => {
         copyMonitor();
       });
     }
+    researcharticleHotList();
   }
 });
-const { reportInfo } = toRefs(state);
+const { reportInfo, reportResearch } = toRefs(state);
 </script>
 
 <style lang="scss">
-.container-cygx {
-  @media screen and (min-width: 790px) {
-    width: 1200px;
-    margin: 0 auto;
-  }
-  padding: 54px 34px 34px 34px;
-  position: relative;
-  z-index: 5;
-  @media screen and (min-width: 790px) {
-    padding: 25px 17px 17px;
-  }
-  .z-index-content {
-    position: relative;
-    z-index: 5;
-  }
-  .search {
-    width: 100%;
-    padding: 20px 20px;
-    line-height: 70px;
-    position: fixed;
-    top: 0;
-    left: 0;
-    background: #fff;
-    z-index: 9;
-    @media screen and (min-width: 790px) {
-      padding: 10px 10px;
-      line-height: 35px;
-    }
-    .search-box {
-      display: flex;
-      align-items: center;
-      padding-left: 20px;
-      width: 100%;
-      height: 70px;
-      border-radius: 35px;
-      background: #f6f6f6;
-      color: #8d8d8d;
-      font-size: 24px;
-      @media screen and (min-width: 790px) {
-        padding-left: 10px;
-        height: 25px;
-        border-radius: 18px;
-        font-size: 12px;
-      }
-    }
-  }
-  .content-top {
-    .report-title {
-      font-size: 34px;
-      font-weight: bold;
-      color: #4a4a4a;
-      margin: 60px 0 20px;
-      @media screen and (min-width: 790px) {
-        margin: 20px 0 10px;
-        font-size: 18px;
-      }
-    }
-    .report-text {
-      color: #999999;
-      font-size: 28px;
-      @media screen and (min-width: 790px) {
-        font-size: 14px;
-      }
-      .seller-list {
-        margin: 20px 0;
-        @media screen and (min-width: 790px) {
-          margin: 10px 0;
-        }
-      }
-      .report_desc {
-        display: flex;
-        justify-content: space-between;
-      }
-      .tip {
-        color: #3385ff;
-      }
-      .container-abstract {
-        margin: 40px 0 20px;
-        padding-bottom: 40px;
-        border-bottom: 2px dashed #999;
-        position: relative;
-        line-height: 44px;
-        color: #333;
-        &::before {
-          content: "";
-          position: absolute;
-          top: 0;
-          left: 0;
-          width: 8px;
-          height: 44px;
-          background: #2a65f5;
-        }
-        @media screen and (min-width: 790px) {
-          margin: 20px 0 10px;
-          padding-bottom: 20px;
-          border-bottom: 1px dashed #999;
-          position: relative;
-          line-height: 22px;
-          &::before {
-            content: "";
-            position: absolute;
-            top: 0;
-            left: 0;
-            width: 4px;
-            height: 22px;
-            background: #2a65f5;
-          }
-        }
-      }
-    }
-  }
-  .report-link {
-    font-size: 28px;
-    line-height: 80px;
-    @media screen and (min-width: 790px) {
-      font-size: 14px;
-      line-height: 40px;
-    }
-  }
-  .detail-report {
-    padding-bottom: 130px;
-    @media screen and (min-width: 790px) {
-      padding-bottom: 65px;
-      font-size: 14px !important;
-    }
-
-    p,
-    span {
-      font-size: 28px !important;
-      @media screen and (min-width: 790px) {
-        font-size: 14px !important;
-      }
-    }
-    img {
-      width: 100% !important;
-    }
-    a {
-      color: #333;
-    }
-    table {
-      border-collapse: collapse;
-      width: 100% !important;
-      margin-left: 0 !important;
-    }
-    tr td,
-    th {
-      border: 1px solid #333;
-      @media screen and (min-width: 790px) {
-        font-size: 1px !important;
-      }
-    }
-  }
-  pre {
-    width: 100%;
-    overflow-y: auto;
-    overflow-x: hidden;
-    outline: none;
-    border: 0;
-    white-space: pre-wrap;
-    word-break: normal;
-  }
-  .btn-returntop {
-    position: fixed;
-    right: 40px;
-    bottom: 220px;
-    width: 88px;
-    height: 88px;
-    z-index: 10;
-    @media screen and (min-width: 790px) {
-      right: 20px;
-      bottom: 145px;
-      width: 44px;
-      height: 44px;
-    }
-  }
-  .btn-freecharge {
-    position: fixed;
-    right: 20px;
-    bottom: 300px;
-    z-index: 10;
-    .image {
-      width: 156px;
-      height: 156px;
-    }
-    .remove-icon {
-      width: 31px;
-      height: 31px;
-      position: absolute;
-      right: 0;
-      top: 0;
-    }
-  }
-  .fixed_cont {
-    position: fixed;
-    bottom: 0;
-    left: 0;
-    right: 0;
-    display: flex;
-    justify-content: space-around;
-    border-top: 1px solid #ddd;
-    padding-bottom: calc(5px + constant(safe-area-inset-bottom));
-    padding-bottom: calc(5px + env(safe-area-inset-bottom));
-    background-color: #fff;
-    z-index: 9;
-    box-sizing: border-box;
-    .handle-item {
-      padding-top: 14px;
-      text-align: center;
-      line-height: 33px;
-      font-size: 20px;
-      color: #888888;
-
-      img {
-        width: 44px;
-        height: 44px;
-        padding: 0;
-        margin: 0;
-      }
-      div {
-        padding: 0;
-        margin: 0;
-      }
-    }
-  }
-}
-.no-cv {
-  -webkit-user-select: none;
-  -khtml-user-select: none;
-  -moz-user-select: none;
-  -ms-user-select: none;
-  user-select: none;
-}
-#tutorial {
-  position: absolute;
-  top: 0;
-  left: 0;
-  z-index: 1;
-  width: 100%;
-  height: 100%;
-  opacity: 0.1;
-  // transform: translateX(130px) rotate(-38deg);
-}
-.van-dialog--round-button .van-dialog__footer {
-  border-top: 1px solid rgba(0, 0, 0, 0.1) !important;
-  padding: 0 !important;
-  .van-button--warning {
-    color: #333 !important;
-    border-right: 1px solid rgba(0, 0, 0, 0.1) !important;
-  }
-  .van-button--danger {
-    color: #3385ff !important;
-  }
-  .van-button--warning,
-  .van-button--danger {
-    height: 80px !important;
-    border-radius: 0 !important;
-  }
-  .van-goods-action-button--first {
-    border-right: 1px solid rgba(0, 0, 0, 0.1) !important;
-  }
-}
-.van-icon-search {
-  font-size: 28px;
-  margin-right: 10px;
-  @media screen and (min-width: 790px) {
-    font-size: 14px;
-    margin-right: 5px;
-  }
-}
+@import "./index.scss";
 </style>

+ 218 - 0
src/views/hzyb/Index.vue

@@ -0,0 +1,218 @@
+<script setup>
+import {ref} from 'vue'
+import { Slider,Icon as VanIcon,Progress as VanProgress } from 'vant';
+import { useStore } from "vuex";
+
+const store=useStore()
+
+const audioIconPlaysmall=new URL('../../assets/hzyb/report/audio-play-small.png', import.meta.url).href
+const audioIconPausesmall=new URL('../../assets/hzyb/report/audio-pause-small.png', import.meta.url).href
+
+const formatVoiceTime = (e) => {
+  let minus = parseInt(e / 60);
+  let sec = parseInt(e % 60);
+  return `${minus > 9 ? minus : "0" + minus}:${sec > 9 ? sec : "0" + sec}`;
+};
+
+let currentTime=ref(0)
+let showBigAudio=ref(false)
+const audioIns=ref('')
+store.state.hzyb.audioData.INS=audioIns
+
+// 以下为音频事件
+const audioError=()=>{
+    console.log('音频加载出错');
+}
+
+const audioPlay=()=>{
+    console.log('音频开始播放');
+    store.commit('hzyb/upateAudioStatus','play')
+}
+
+const audioPause=()=>{
+    console.log('音频暂停');
+    store.commit('hzyb/upateAudioStatus','paused')
+}
+
+const audioTimeupdate=(e)=>{
+    // console.log(e.target.currentTime);
+    currentTime.value=e.target.currentTime
+}
+
+const audioEnded=()=>{
+    console.log('音频播放结束');
+    store.commit('hzyb/upateAudioStatus','end')
+}
+
+// 音频进度条变化
+const SliderChange=(e)=>{
+    store.state.hzyb.audioData.INS.currentTime=e
+}
+
+const handleClickAudio=()=>{
+    if(store.state.hzyb.audioData.paused){
+        store.state.hzyb.audioData.INS.play()
+    }else{
+        store.state.hzyb.audioData.INS.pause()
+    }
+}
+// 关闭音频弹窗
+const handleCloseAudioPup=()=>{
+    showBigAudio.value=false
+    store.commit('hzyb/closeAudioPop')
+}
+
+</script>
+
+
+<template>
+    <router-view />
+    <audio
+        ref="audioIns"
+        autoplay
+        :src="$store.state.hzyb.audioData.url"
+        @error="audioError"
+        @play="audioPlay"
+        @pause="audioPause"
+        @timeupdate="audioTimeupdate"
+        @ended="audioEnded"
+        style="display:none"
+    />
+    <!-- 悬浮音频模块 -->
+    <div class="popup-audio-box" v-if="$store.state.hzyb.audioData.show">
+        <div class="small-box" v-if="!showBigAudio" @click="showBigAudio=true">
+            <img :src="$store.state.hzyb.audioData.videoImg" class="bg-img">
+            <div class="small-con">
+                <div class="audio-name-box" style="flex:1">
+                    <div class="van-ellipsis title">{{$store.state.hzyb.audioData.videoName}}</div>
+                    <div style="color:#666">时长 {{ formatVoiceTime($store.state.hzyb.audioData.videoTime) }}</div>
+                </div>
+                <img class="btn-img" :src="$store.state.hzyb.audioData.paused?audioIconPausesmall:audioIconPlaysmall" @click.stop="handleClickAudio" alt="">
+                <van-icon name="cross" color="#BBC3C9" size="16" @click.stop="handleCloseAudioPup" />
+            </div>
+            <van-progress 
+                class="bot-progress" 
+                stroke-width="1px" 
+                color="#D4AC78" 
+                :percentage="(currentTime/$store.state.hzyb.audioData.videoTime)*100" 
+                :show-pivot="false" 
+            />
+        </div>
+        <div class="big-box" v-else>
+            <van-icon name="arrow-down" color="#BBC3C9" size="16" class="arrow-d" @click="showBigAudio=false" />
+            <van-icon name="cross" color="#BBC3C9" size="16" class="arrow-c" @click.stop="handleCloseAudioPup" />
+            <div class="title">{{$store.state.hzyb.audioData.videoName}}</div>
+            <div class="flex">
+                <span>{{formatVoiceTime(currentTime)}}</span>
+                <Slider 
+                    button-size="14px" 
+                    v-model="currentTime" 
+                    :max="$store.state.hzyb.audioData.videoTime" 
+                    active-color="#D5AD79" 
+                    inactive-color="#E9E9E9"
+                    @change="SliderChange" 
+                    class="slider"
+                ></Slider>
+                <span>{{ formatVoiceTime($store.state.hzyb.audioData.videoTime) }}</span>
+            </div>
+            <div class="flex" style="justify-content: center;">
+                <img src="@/assets/hzyb/report/audio-change-small-grey.png">
+                <img :src="$store.state.hzyb.audioData.paused?audioIconPausesmall:audioIconPlaysmall" @click="handleClickAudio" style="margin:0 20px">
+                <img src="@/assets/hzyb/report/audio-change-small-grey.png" style="transform: rotate(180deg)">
+            </div>
+        </div>
+        <!-- <div>{{$store.state.hzyb.audioData.videoName}}</div>
+        <div class="flex">
+            <span>{{formatVoiceTime(currentTime)}}</span>
+            <Slider button-size="10px" v-model="currentTime" :max="$store.state.hzyb.audioData.videoTime" active-color="#D5AD79" @change="SliderChange" class="slider"></Slider>
+            <span>{{ formatVoiceTime($store.state.hzyb.audioData.videoTime) }}</span>
+            <img :src="$store.state.hzyb.audioData.paused?audioIconPausesmall:audioIconPlaysmall"  alt="" @click="handleClickAudio">
+        </div> -->
+    </div>
+</template>
+
+<style lang="scss" scoped>
+.popup-audio-box{
+    position: fixed;
+    z-index: 99;
+    bottom: 30px;
+    width: 90vw;
+    left: 5vw;
+    background-color: #fff;
+    box-shadow: 0px 0px 33px 1px rgba(50,35,17,0.25);
+    border: 1px solid #E4E4E4;
+    .small-box{
+        display: flex;
+        height: 100px;
+        position: relative;
+        .bg-img{
+            background-color: #f5f5f5;
+            width: 74px;
+            display: block;
+            height: 100%;
+            flex-shrink: 0;
+            margin-right: 16px;
+        }
+        .small-con{
+            overflow: hidden;
+            display: flex;
+            align-items: center;
+            flex: 1;
+            font-size: 20px;
+            padding-right: 33px;
+            .title{
+                font-size: 23px;
+            }
+            .btn-img{
+                width: 49px;
+                height: 49px;
+                display: block;
+                margin-right: 36px;
+            }
+        }
+        .bot-progress{
+            position: absolute;
+            left: 0;
+            right: 0;
+            bottom: 0;
+        }
+    }
+    .big-box{
+        padding: 25px;
+        position: relative;
+        .arrow-d{
+            position: absolute;
+            left: 25px;
+            top: 25px;
+        }
+        .arrow-c{
+            position: absolute;
+            right: 25px;
+            top: 25px;
+        }
+        .title{
+            padding: 0 40px;
+            text-align: center;
+            font-size: 23px;
+        }
+        .flex{
+            display: flex;
+            align-items: center;
+            margin-top: 40px;
+            span{
+                flex-shrink: 0;
+                font-size: 20px;
+                color: #666;
+            }
+            .slider{
+                flex: 1;
+                margin: 0 10px;
+            }
+            img{
+                width: 49px;
+                height: 49px;
+            }
+        }
+    }
+}
+</style>

+ 92 - 20
src/views/hzyb/chart/Detail.vue

@@ -1,7 +1,9 @@
 <script setup>
 import chartBox from './component/chartBox.vue'
+import noAuth from './component/noAuth.vue'
+import sharePoster from '../components/SharePoster.vue'
 import { Popup, Toast,Picker } from 'vant';
-import {ref,onMounted, reactive, watch} from 'vue'
+import {ref,onMounted, reactive, watch,computed} from 'vue'
 import {useRoute, useRouter,onBeforeRouteUpdate} from 'vue-router'
 import moment from 'moment'
 import Highcharts from 'highcharts/highstock';
@@ -64,7 +66,7 @@ const makeTimeData=(type)=>{
 }
 const handleShowDate=()=>{
     // if(columns.value.length===0){
-        if(resData.value.ChartInfo.ChartType===1){//曲线图
+        if( sameOptionType.value.includes(resData.value.ChartInfo.ChartType)){//曲线图
             columns.value=makeTimeData(1)
         }else if(resData.value.ChartInfo.ChartType===2){//季节性图表
             columns.value=makeTimeData(2)
@@ -75,7 +77,7 @@ const handleShowDate=()=>{
 // 确定选择时间
 const handleConfirmDate=(e)=>{
     let start='',end=''
-    if(resData.value.ChartInfo.ChartType===1){
+    if(sameOptionType.value.includes(resData.value.ChartInfo.ChartType)){
         start=e[0]+'-'+e[1]
         end=e[2]+'-'+e[3]
     }else if(resData.value.ChartInfo.ChartType===2){
@@ -148,6 +150,16 @@ let chartData=ref({
 })// 图表配置数据
 let resData=ref(null)//接口详情数据
 let loading=ref(false)
+const sameOptionType = ref([1,3,4,5,6]);//筛选框一样的图表类型 曲线/面积/柱状/散点/组合 常规图
+const chartItemStyleArr = ref([
+    { label: '曲线图', key: 1 ,value: 'spline'},
+    { label: '面积图', key: 3 ,value: 'areaspline'},
+    { label: '柱状图', key: 4 ,value: 'column'},
+    { label: '散点图', key: 5 ,value: 'scatter'}
+])//组合图配置时可选类型
+
+let noauth=ref(false)
+let noAuthData=ref(null)
 // 如果type:init 则是初始化获取数据 
 const getChartInfo=async (type)=>{
     // resData.value=null
@@ -155,8 +167,8 @@ const getChartInfo=async (type)=>{
     const res=await apiChartInfo({
         ChartInfoId:ChartInfoId,
         DateType:dateType.value,
-        StartDate:startDate.value&&resData.value.ChartInfo.ChartType===1?startDate.value:'',
-        EndDate:endDate.value&&resData.value.ChartInfo.ChartType===1?endDate.value:'',
+        StartDate:startDate.value&&sameOptionType.value.includes(resData.value.ChartInfo.ChartType)?startDate.value:'',
+        EndDate:endDate.value&&sameOptionType.value.includes(resData.value.ChartInfo.ChartType)?endDate.value:'',
         SeasonStartDate:startDate.value&&resData.value.ChartInfo.ChartType===2?startDate.value:'',
         SeasonEndDate:endDate.value&&resData.value.ChartInfo.ChartType===2?endDate.value:'',
         Calendar:calendarType.value,
@@ -169,7 +181,7 @@ const getChartInfo=async (type)=>{
         // document.title=res.data.ChartInfo.ChartName
         
         // 设置highchart配置 ChartType: 1曲线图 2季节图:季节图中公历和农历数据结构不同
-        if(res.data.ChartInfo.ChartType===1){
+        if( res.data.ChartInfo.ChartType !==2 ){
             if(type=='init'){
                 dateType.value=res.data.ChartInfo.DateType
                 startDate.value=res.data.ChartInfo.StartDate||''
@@ -187,6 +199,24 @@ const getChartInfo=async (type)=>{
             
             setSeasonOpt(res.data.EdbInfoList[0])
         }
+
+        // 向小程序发送分享数据
+        let postData = {
+            params:{
+                chartInfoId:ChartInfoId,
+                searchVal:decodeURIComponent(route.query.searchVal)||'',
+                MyChartId:route.query.MyChartId||'',
+                MyChartClassifyId:route.query.MyChartClassifyId||'',
+            },
+            title: res.data.ChartInfo.ChartName,
+            shareImg:res.data.ChartInfo.ChartImage
+        };
+        wx.miniProgram.postMessage({ data: postData });
+        
+
+    }else if(res.code==403){
+        noauth.value=true
+        noAuthData.value=res.data
     }
 }
 getChartInfo('init')
@@ -224,7 +254,7 @@ const handleCloseLimit=()=>{//点击遮罩层关闭弹窗或者点击取消关
 }
 
 
-// 设置曲线图配置
+// 设置常规图配置 曲线 散点 面积 柱状等
 const setSplineOpt=(data)=>{
     let series=[]
     let xAxis={
@@ -251,6 +281,15 @@ const setSplineOpt=(data)=>{
 
     let minAndMaxTimeTemArr=[]//存放所有指标的最大最小时间
 
+    /* 支持图的类型 */
+    const chartTypeMap = {
+        1: 'spline',
+        3: 'areaspline',
+        4: 'column',
+        5: 'scatter',
+    };
+    let chartStyle = chartTypeMap[resData.value.ChartInfo.ChartType];
+
     data.forEach((item,index)=>{
         let dynamic_title = item.EdbName;
         let dynamic_arr = data.filter(
@@ -289,14 +328,16 @@ const setSplineOpt=(data)=>{
             dataGrouping:{
                 enabled:false
             },
-            type:item.ChartStyle,
+            type: resData.value.ChartInfo.ChartType ===6 ? item.ChartStyle : chartStyle,
             yAxis:index,
             // name:dynamic_arr.length > 1
             //   ? `${item.EdbName}(${item.SourceName})${dynamic_tag}`
             //   : `${item.EdbName}${dynamic_tag}`,//拼接标题 判断相同指标名称拼接来源
             name:temName,
             color: item.ChartColor,
-            lineWidth: Number(item.ChartWidth),
+            // lineWidth: Number(item.ChartWidth),
+            lineWidth: (resData.value.ChartInfo.ChartType === 1 || (resData.value.ChartInfo.ChartType === 6 && item.ChartStyle === 'spline')) ? Number(item.ChartWidth) : 0,
+            fillColor: (resData.value.ChartInfo.ChartType === 3 || (resData.value.ChartInfo.ChartType === 6 && item.ChartStyle === 'areaspline')) ? item.ChartColor : undefined,
             visible:true,
             LatestDate:item.LatestDate,
             LatestValue:item.LatestValue
@@ -683,7 +724,7 @@ const handleGoSearch=()=>{
 }
 
 // 获取当前图表
-let searchVal=route.query.searchVal
+let searchVal=decodeURIComponent(route.query.searchVal)
 let searchListData=ref([])//搜索的数据
 const getSearchListData=async ()=>{
     const res=await apiChartList({Keywords:searchVal,Page:1,Limit:10000,Authorization:route.query.token})
@@ -801,7 +842,7 @@ onMounted(()=>{
 // 保存
 const handleSaveChart=async ()=>{
     let params={}
-    if(resData.value.ChartInfo.ChartType===1){//曲线图
+    if(sameOptionType.value.includes(resData.value.ChartInfo.ChartType)){//曲线图
         let arr=chartData.value.yAxis.map(item=>{
             return {
                 ChartColor: item.chartEdbInfo.ChartColor,
@@ -895,10 +936,31 @@ const pageTouchmove=(e)=>{
 
     event.preventDefault();//阻止页面移动
 }
+
+// 生成海报所需跳转到小程序页面参数
+const code_scene=computed(()=>{
+    let obj= {
+        chartInfoId:ChartInfoId,
+        searchVal:decodeURIComponent(route.query.searchVal)||'',
+        MyChartId:route.query.MyChartId||'',
+        MyChartClassifyId:route.query.MyChartClassifyId||'',
+        from:'share'
+    }
+    return JSON.stringify(obj)
+})
+// 生成海报图片所需要的数据
+const posterParams=computed(()=>{
+    return {
+        chart_name:resData.value.ChartInfo.ChartName,
+        chart_image:resData.value.ChartInfo.ChartImage
+    }
+})
+
+
 </script>
 
 <template>
-    <div class="chart-detail" v-if="!loading">
+    <div class="chart-detail" v-if="!loading&&!noauth">
         <div class="chart-title">{{resData.ChartInfo.ChartName}}</div>
         <div class="top-box">
             <div class="flex calendar-box" style="float:left" @click="handleShowDate">
@@ -908,6 +970,14 @@ const pageTouchmove=(e)=>{
                 <span class="date">{{endDate||'结束日期'}}</span>
             </div>
             <img class="icon" src="../../../assets/hzyb/chart/search.png" alt="" @click="handleGoSearch">
+            <share-poster 
+                :shareData="{
+                    type:'chart_detail',
+                    code_scene:code_scene,
+                    code_page:'pages-chart/chartDetail',
+                    data:posterParams
+                }"
+            ></share-poster>
             <img class="icon" src="../../../assets/hzyb/chart/save.png" alt="" @click="handleSaveChart" v-if="canSave">
             <img class="icon" src="../../../assets/hzyb/chart/refresh.png" alt="" @click="handleRefreshChart">
         </div>
@@ -915,16 +985,17 @@ const pageTouchmove=(e)=>{
         <chartBox :options='chartData' v-if="!loading"></chartBox>
         
         <div class="flex source-box">
-            <span>来源:弘则研究</span>
-            <div class="season-change-box" v-if="resData&&resData.ChartInfo.ChartType===2">
+            <div :style="{flex:resData&&resData.ChartInfo.ChartType===2?1:2}"><span v-if="resData&&resData.ChartInfo.ChartType!==2">来源:{{resData&&resData.ChartInfo.ChartSource}}</span></div>
+            <div class="season-change-box" style="flex:1" v-if="resData&&resData.ChartInfo.ChartType===2">
                 <span :class="calendarType==='农历'&&'active'" @click="calendarTypeChange('农历')">农历</span>
                 <span :class="calendarType==='公历'&&'active'" @click="calendarTypeChange('公历')">公历</span>
             </div>
-            <span style="color:#E3B377" @click="showLimit=true">上下限设置</span>
+            <span style="color:#E3B377;flex:1;text-align:right" @click="showLimit=true">上下限设置</span>
         </div>
+        <div class="source-box" style="margin-top:5px" v-if="resData&&resData.ChartInfo.ChartType===2">来源:{{resData&&resData.ChartInfo.ChartSource}}</div>
 
         <!-- 日期类型 -->
-        <div class="date-type-box" v-if="resData&&resData.ChartInfo.ChartType===1">
+        <div class="date-type-box" v-if="resData&&sameOptionType.includes(resData.ChartInfo.ChartType)">
             <div 
                 :class="['item',item.value==dateType?'active':'']" 
                 v-for="item in dateTypeList" 
@@ -936,7 +1007,7 @@ const pageTouchmove=(e)=>{
         <!-- 最新值 -->
         <div class="latest-value-wrap" v-if="resData">
             <p style="margin-bottom:10px">最新数值</p>
-            <ul class="list" v-if="resData.ChartInfo.ChartType===1">
+            <ul class="list" v-if="sameOptionType.includes(resData.ChartInfo.ChartType)">
                 <li v-for="item in chartData.series" :key="item.name">
                     <p style="color:#333">{{moment(item.LatestDate).format('YYYY-MM-DD')}}</p>
                     <p :style="{color:item.color,flex:1}">{{item.name.length>20?item.name.replace(/<br>/g,''):item.name}}</p>
@@ -954,6 +1025,7 @@ const pageTouchmove=(e)=>{
 
         <!-- 上一张下一张图切换 -->
         <div 
+            v-if="$route.query.from!='share'"
             class="change-page-wrap" 
             :style="{left:pageBoxPosition.left+'px',top:pageBoxPosition.top+'px'}"
             @touchmove.stop="pageTouchmove"
@@ -1011,8 +1083,8 @@ const pageTouchmove=(e)=>{
             </div>
         </Popup>
     </div>
-    
-    
+    <!-- 无权限 -->
+    <noAuth v-if="noauth" :data="noAuthData"></noAuth>
 
 </template>
 
@@ -1054,7 +1126,7 @@ const pageTouchmove=(e)=>{
             float: right;
             width: 40px;
             height: 40px;
-            margin-left: 50px;
+            margin-left: 30px;
         }
     }
     .select-date-box-head{

+ 33 - 0
src/views/hzyb/chart/component/chartBox.vue

@@ -22,6 +22,39 @@ const chartDefaultOpts={
 			animation: {
 				duration: 1000
 			}
+		},
+		areaspline: {
+			lineWidth: 1,
+			marker: {
+					enabled: false,
+			},
+			// fillOpacity: 0.5,
+		},
+		column:{
+			pointPadding: 0.05,
+		},
+		scatter: {
+			turboThreshold: 0,
+			marker: {
+					symbol: 'circle',
+					radius: 5,
+					states: {
+							hover: {
+									enabled: true,
+							}
+					}
+			},
+			states: {
+				hover: {
+					marker: {
+						enabled: true
+					}
+				}
+			},
+			tooltip: {
+				headerFormat: '<span style="font-size: 10px">{point.key}</span><br>',
+				pointFormat: '<span style="color:{point.color}">●</span> {series.name}: <span style="font-weight: 600">	{point.y}</span>',
+			}
 		}
 	},
 	//范围选择器

+ 126 - 0
src/views/hzyb/chart/component/noAuth.vue

@@ -0,0 +1,126 @@
+<script setup>
+import { computed } from "vue";
+import {apiApplyPermission} from '@/api/hzyb/user'
+
+const props = defineProps({
+  data: Object,
+});
+
+const authType = computed(() => {
+    if(!props.data) return
+    if (props.data.type === "contact") {
+        handleAutoApply()
+        return 1;
+    }
+    if (props.data.type === "expired") {
+        return 2;
+    }
+    if (props.data.type === "apply" && !props.data.customer_info.has_apply) {
+        return 3;
+    }
+    if (props.data.type === "apply" && props.data.customer_info.has_apply) {
+        return 4;
+    }
+});
+
+const handleAutoApply=()=>{
+  if(!props.data.customer_info.has_apply){
+    if(props.data.customer_info.status=='冻结'||(props.data.customer_info.status=='试用'&&props.data.customer_info.is_suspend==1)){
+        apiApplyPermission({
+            company_name:props.data.customer_info.company_name,
+            real_name:props.data.customer_info.name,
+            source:3,
+            from_page:'图库详情'
+        }).then(res=>{
+            if(res.code===200){
+                console.log('主动申请成功');
+            }
+        }) 
+    }
+  }
+}
+
+// 点击申请
+const handleApply=()=>{
+    if(props.data.customer_info.status=='流失'){
+        apiApplyPermission({
+            company_name:props.data.customer_info.company_name,
+            real_name:props.data.customer_info.name,
+            source:3,
+            from_page:'图库详情'
+        }).then(res=>{
+            wx.miniProgram.navigateTo({url:'/pages-applyPermission/applyResult'})
+        })
+        return
+    }
+    wx.miniProgram.navigateTo({ url: '/pages-applyPermission/applyPermission?source=3&from_page=图库详情' })
+}
+
+const goBack=()=>{
+  wx.miniProgram.switchTab({url:'/pages/chart/chart'})
+}
+</script>
+
+<template>
+  <div class="chart-noauth-wrap">
+    <img class="img" src="https://hzstatic.hzinsights.com/static/icon/hzyb/activity_no_auth.png" alt="" v-if="authType!=4" />
+    <img class="img-wait" src="https://hzstatic.hzinsights.com/static/icon/hzyb/chart_wait.png" alt="" v-else />
+    <block v-if="authType == 1">
+      <div style="margin-bottom: 15px">您暂无权限查看图库</div>
+      <div>若想查看请联系对口销售</div>
+      <!-- <div>{{info.name}}:{{info.mobile}}</div> -->
+      <a :href="'tel:'+props.data.mobile" tag="div" class="global-btn-yellow-change btn" style="margin-top: 30px">联系销售</a>
+    </block>
+
+    <block v-if="authType == 2">
+      <div style="margin-bottom: 15px">您的权限已到期,暂时无法查看图库</div>
+      <div>若想继续查看请联系对口销售</div>
+      <!-- <div>{{info.name}}:{{info.mobile}}</div> -->
+      <a :href="'tel:'+props.data.mobile" tag="div" class="global-btn-yellow-change btn" style="margin-top: 30px">联系销售</a>
+    </block>
+
+    <block v-if="authType == 3">
+      <div style="margin-bottom: 15px">您暂无权限查看图库</div>
+      <div>若想查看可以申请开通</div>
+      <div class="global-btn-yellow-change btn" style="margin-top: 30px" @click="handleApply">立即申请</div>
+    </block>
+
+    <block v-if="authType == 4">
+      <div style="margin-bottom: 15px">您已提交申请</div>
+      <div>请等待销售人员与您联系</div>
+      <div class="global-btn-yellow-change btn" style="margin-top: 30px" @click="goBack">返回</div>
+    </block>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.chart-noauth-wrap {
+  padding-top: 50px;
+  text-align: center;
+  font-size: 32px;
+  .img {
+    width: 100%;
+    margin-bottom: 50px;
+  }
+  .img-wait {
+    margin-top: 200px;
+    width: 186px;
+    margin-bottom: 50px;
+  }
+  .global-btn-yellow-change{
+    background: linear-gradient(270deg, #EEC795 0%, #D9A360 100%);
+    border-radius: 35px;
+    color: #fff;
+    text-align: center;
+    line-height: 70px;
+  }
+  .btn{
+    width: 380px;
+    line-height: 7rpx;
+    margin-left: auto;
+    margin-right: auto;
+    margin-top: 40px;
+    display: block;
+  }
+}
+</style>

+ 114 - 0
src/views/hzyb/components/SharePoster.vue

@@ -0,0 +1,114 @@
+<script setup>
+import {ref} from 'vue'
+import {apiGetPoster} from '@/api/hzyb/common'
+
+const props=defineProps({
+    style:Object,
+    shareData:Object
+})
+
+let show=ref(false)
+let showPoster=ref(false)
+let posterImg=ref('')
+
+const handleCreatePoster=async ()=>{
+    show.value=true
+    const res=await apiGetPoster({
+        code_page:props.shareData.code_page,
+        code_scene:props.shareData.code_scene,
+        source:props.shareData.type,
+        pars:JSON.stringify(props.shareData.data)
+    })
+    if(res.code==200){
+        posterImg.value=res.data
+        show.value=false
+        showPoster.value=true
+    }else{
+        show.value=false
+    }
+}
+
+</script>
+
+
+<template>
+    <div class="share-poster-wrap" @touchmove.prevent>
+        <img @click="handleCreatePoster" class="chart-icon" src="@/assets/hzyb/share-poster-chart-icon.png" alt="" v-if="props.shareData.type=='chart_detail'">
+        <img v-else @click="handleCreatePoster" :style="props.style" class="share-icon" src="@/assets/hzyb/share-poster-icon.png"/>
+
+        <div class="poster-mask" v-if="show||showPoster" @click="showPoster=false" @touchmove.prevent></div>
+        <div class="loading-box" v-if="show">
+            <img class="load-img" src="@/assets/hzyb/loading.png"/>
+            <div>海报生成中...</div>
+        </div>
+        <img v-if="showPoster" class="poster-img" :src="posterImg" show-menu-by-longpress />
+    </div>
+</template>
+
+<style lang="scss" scoped>
+.share-poster-wrap{
+    .share-icon{
+        position: fixed;
+        bottom: 100px;
+        right: 34px;
+        z-index: 50;
+        width: 76px;
+        height: 76px;
+    }
+    .chart-icon{
+        float: right;
+        width: 40px;
+        height: 40px;
+        margin-left: 30px;
+    }
+    .poster-mask{
+        position: fixed;
+        left: 0;
+        top: 0;
+        right: 0;
+        bottom: 0;
+        background: rgba(0, 0, 0, 0.4);
+        z-index: 998;
+    }
+    .loading-box{
+        background-color: #fff;
+        position: fixed;
+        left: 50%;
+        top: 50%;
+        z-index: 999;
+        transform: translate(-50%,-50%);
+        width: 417px;
+        height: 261px;
+        text-align: center;
+        padding-top: 80px;
+        font-size: 32px;
+        font-weight: bold;
+        .load-img{
+            display: block;
+            margin-left: auto;
+            margin-right: auto;
+            width: 91px;
+            height: 91px;
+            animation: circle 1s linear infinite;
+        }
+        @keyframes circle {
+            0%{
+                transform: rotateZ(0);
+            }
+            100%{
+                transform: rotateZ(360deg);
+            }
+        }
+    }
+    .poster-img{
+        width: 90vw;
+        display: block;
+        position: fixed;
+        left: 50%;
+        top: 50%;
+        z-index: 999;
+        transform: translate(-50%,-50%);
+        border-radius: 16px;
+    }
+}
+</style>

+ 633 - 0
src/views/hzyb/report/ChapterDetail.vue

@@ -0,0 +1,633 @@
+<template>
+<van-pull-refresh v-model="loading" @refresh="onRefresh" style="min-height:100vh">
+  <div class="chapter-detail-page" v-if="info" :style="{paddingBottom:$store.state.hzyb.audioData.url&&'80px'}">
+    <div :class="['main-box',!info.auth_ok&&'main-box-noauth']">
+      <div class="title">【第{{info.report_chapter_item.stage}}期 | {{info.report_chapter_item.classify_name_first}}  | {{info.report_chapter_item.type_name}}】{{info.report_chapter_item.title}}</div>
+      <div class="flex time">
+        <span>FICC团队</span>
+        <span>{{formatTime(info.report_chapter_item.publish_time)}}</span>
+      </div>
+      <!-- 音频模块 -->
+      <AudioBox :audioData="audioData" v-if="info.report_chapter_item.video_url&&info.report_chapter_item.video_play_seconds>0"></AudioBox>
+      <div class="tips">
+        <span>注:请务必阅读</span>
+        <span style="color: #e3b377; margin-left: 20px" @click="showDisclaimers = true">免责声明</span>
+      </div>
+      <div class="rich-content">
+        <div v-html="info.report_chapter_item.content" v-if="info.auth_ok"></div>
+        <div v-html="info.report_chapter_item.content_sub" v-else ></div>
+      </div>
+      <!-- 指标数据模块 -->
+      <div class="ticker-wrap" v-if="tickerInfo">
+        <div class="top-title">{{tickerInfo.ticker_title.report_chapter_type_name}}数据表</div>
+        <div class="table-box">
+          <div class="table-row table-head">
+            <div class="table-item" v-for="item in tickerHead" :key="item.key">{{item.label}}</div>
+          </div>
+          <div class="table-row table-body" v-for="(tr,index) in tickerInfo.list" :key="tr.base_column_name">
+            <div :class="['table-item',index%2==0?'grey':'',tr[td.key]<0?'minus':'']" v-for="td in tickerHead" :key="td.key">{{tr[td.key]}}</div>
+          </div>
+        </div>
+        <div v-if="tickerInfo.ticker_title.report_chapter_type_id ===26" style="text-align:center;font-weight:bold">注:与新加坡TSR20相关数据均取展示日期前一交易日数据</div>
+      </div>
+      <!-- 无权限 -->
+      <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>
+        <div class="apply-box" v-else>
+          <div>您暂无权限查看报告 </div>
+          <div>若想查看请联系对口销售:{{info.permission_check.name}}</div>
+          <a class="btn" :href="'tel:'+info.permission_check.mobile" tag="div">立即联系</a>
+        </div>
+      </div>
+      
+    </div>
+    <!-- 章节详情底部快速切换 -->
+    <div class="chapter-list-wrap" v-if="fromPage=='reportdetail'">
+      <div class="top-text">更多</div>
+      <van-row gutter="10">
+        <van-col span="6" v-for="item in info.report_chapter_menu_list" :key="item.report_chapter_id">
+          <div :class="['item',item.report_chapter_id==chapterId&&'active']" @click="handleChapterChange(item)">
+            <img :src="item.report_chapter_type_thumb+'?t='+new Date().getTime()" mode="aspectFill"/>
+            <!-- <text>{{item.report_chapter_type_name}}</text> -->
+          </div>
+        </van-col>
+      </van-row>
+    </div>
+
+    <!-- 返回顶部 -->
+    <img v-if="showToTop&&info.auth_ok" @click="handleBackTop" class="back-top-img" src="@/assets/hzyb/report/back-top.png" mode="aspectFill"/>
+
+    <!-- 免责声明 -->
+    <van-popup :show="showDisclaimers" @close="showDisclaimers = false" round closeable>
+      <div class="disclaimers-box">
+        <div style="text-align: center; font-size: 16px; font-weight: bold; margin-bottom: 20px">免责声明</div>
+        <div style="margin-bottom: 10rpx">1、本报告仅供弘则弥道(上海)投资咨询有限公司正式签约的机构客户使用,不会仅因接收人/接受机构收到本报告而将其视为客户。</div>
+        <div style="margin-bottom: 10rpx"
+          >2、本报告根据国际和行业通行的准则,以合法渠道获得这些信息,尽可能保证可靠、准确和完整,但并不保证报告所述信息的准确性和完整性,也不保证本报告所包含的信息或建议在本报告发出后不会发生任何变更。本报告中所提供的信息仅供参考。</div
+        >
+        <div style="margin-bottom: 10rpx"
+          >3、报告中的内容不对投资者做出的最终操作建议做任何的担保,也没有任何形式的分享投资收益或者分担投资损失的书面或口头承诺。不作为客户在投资、法律、会计或税务等方面的最终操作建议,也不作为道义的、责任的和法律的依据或者凭证,无论是否已经明示或者暗示。</div
+        >
+        <div style="margin-bottom: 10rpx">4、在任何情况下,本公司不对客户/接受人/接受机构因使用报告中内容所引致的一切损失负责任,客户/接受人/接受机构需自行承担全部风险。</div>
+      </div>
+    </van-popup>
+
+    <!-- 申请提示弹窗 -->
+    <van-popup :show="pupData.show" @close="pupData.show=false" :close-on-click-overlay="false">
+        <div class="global-pup">
+            <div class="content">
+                <div v-html="pupData.content"></div>
+            </div>
+            <div class="flex bot">
+                <div @click="pupData.show=false">知道了</div>
+            </div>
+        </div>
+    </van-popup>
+
+    <!-- 分享海报 -->
+    <Teleport to="body">
+    <SharePoster
+      :style="{bottom:'125px'}" 
+      :shareData="{
+        type:'report_detail',
+        code_page:'pages-report/chapterDetail',
+        code_scene:code_scene,
+        data:posterParams
+      }" 
+      v-if="info.auth_ok"
+    ></SharePoster>
+    </Teleport>
+  </div>
+</van-pull-refresh>
+</template>
+
+<script>
+// 由于当时写在uni中 直接复制过来的 也不想改了就写成vue2形式吧
+import moment from 'moment'
+import 'moment/dist/locale/zh-cn'
+moment.locale('zh-cn')
+
+import {apiChapterDetail,apiChapterTickerValue} from '@/api/hzyb/report'
+import {apiApplyPermission} from '@/api/hzyb/user'
+import {Popup,Image as VanImage,PullRefresh,Col, Row} from 'vant'
+import AudioBox from './components/AudioBox.vue'
+import SharePoster from '../components/SharePoster.vue'
+export default {
+  components:{
+    [Popup.name]:Popup,
+    [VanImage.name]:VanImage,
+    [PullRefresh.name]:PullRefresh,
+    [Col.name]:Col,
+    [Row.name]:Row,
+    [PullRefresh.name]:PullRefresh,
+    AudioBox,
+    SharePoster
+  },
+  computed:{
+    code_scene(){
+      return JSON.stringify({
+        chapterId:this.chapterId
+      })
+    },
+    posterParams(){
+      return {
+        report_type:this.info.report_chapter_item.classify_name_first,
+        report_title:`【第${this.info.report_chapter_item.stage}期 | ${this.info.report_chapter_item.classify_name_first}  | ${this.info.report_chapter_item.type_name}】${this.info.report_chapter_item.title}`,
+        report_abstract:this.info.report_chapter_item.content
+      }
+    }
+  },
+  data() {
+    return {
+      showDisclaimers: false, //显示免责声明
+      chapterId:0,
+      fromPage:'',//如果是从首页(home)来的则隐藏底部切换
+      info:null,
+      audioData:{},//音频数据
+
+      tickerInfo:null,
+      tickerHead:[],
+
+      pupData:{
+				show:false,
+				content:'',//弹窗html字符串
+			},
+
+      loading:false,
+
+      showToTop:false
+
+    };
+  },
+  beforeCreate(){
+    if(this.$route.query.token){
+      localStorage.setItem('hzyb-token',this.$route.query.token)
+    }
+  },
+  created(options) {
+    this.chapterId=this.$route.query.chapterId
+    this.fromPage=this.$route.query.fromPage||''
+    this.getDetail()
+  },
+  mounted(){
+        $(document).on('click', '.rich-content img',function(event) {
+            let imgArray = [];
+            let curImageSrc = $(this).attr('src');
+            let oParent = $(this).parent();
+            if (curImageSrc && !oParent.attr('href')) {
+                $('.rich-content img').each(function(index, el) {
+                    let itemSrc = $(this).attr('src');
+                    imgArray.push(itemSrc);
+                });
+                wx.previewImage({current:curImageSrc,urls:imgArray});
+            }
+        })
+    window.addEventListener('scroll',this.handelPageScroll)
+  },
+  destroyed () {
+    window.removeEventListener('scroll',this.handelPageScroll)
+  },
+  methods: {
+    handelPageScroll(){
+      const top=document.documentElement.scrollTop||document.body.scrollTop
+      if(top>window.outerHeight){
+        this.showToTop=true
+      }else{
+        this.showToTop=false
+      }
+    },
+
+    async getDetail(){
+      const res=await apiChapterDetail({report_chapter_id:Number(this.chapterId)})
+      if(res.code===200){
+        this.info=res.data
+        this.audioData={
+          auth_ok:res.data.auth_ok,
+          video_name:res.data.report_chapter_item.video_name,
+          video_play_seconds:res.data.report_chapter_item.video_play_seconds,
+          video_url:res.data.report_chapter_item.video_url,
+          video_img:res.data.report_chapter_item.video_img
+        }
+        document.title=res.data.report_chapter_item.classify_name_first
+        if(res.data.auth_ok&&res.data.report_chapter_item.classify_name_first==='晨报'){
+          this.getTickerValue()
+        }
+
+        if(!res.data.auth_ok){
+          // 获取详情如果为联系销售根据判断条件是否主动申请一次
+          if(this.info.permission_check.type=='contact'&&!this.info.permission_check.customer_info.has_apply){
+              if(this.info.permission_check.customer_info.status=='冻结'||(this.info.permission_check.customer_info.status=='试用'&&this.info.permission_check.customer_info.is_suspend==1)){
+                  apiApplyPermission({
+                      company_name:this.info.permission_check.customer_info.company_name,
+                      real_name:this.info.permission_check.customer_info.name,
+                      source:4,
+                      from_page:'报告详情'
+                  }).then(res=>{
+                      if(res.code===200){
+                          console.log('主动申请成功');
+                      }
+                  }) 
+              }
+          }
+        }
+
+        //向小程序发送分享数据
+        wx.miniProgram.postMessage({ 
+          data: {
+            title:`FICC【${res.data.report_chapter_item.classify_name_first}】`,
+            chapterId:this.chapterId
+          } 
+        });
+      }
+    },
+
+    //获取晨报中指标数据
+    async getTickerValue(){
+      const res=await apiChapterTickerValue({report_chapter_id:Number(this.chapterId)})
+      if(res.code===200){
+        if(!res.data||!res.data.list) return
+        this.tickerInfo=res.data
+        if(res.data.ticker_title.report_chapter_type_id===17){
+          this.tickerHead=[
+            {
+              label:res.data.ticker_title.ticker_title,
+              key:'base_column_name'
+            },
+            {
+              label:'公布日期',
+              key:'date'
+            },
+            {
+              label:'最新值',
+              key:'ticker_value'
+            },
+            {
+              label:'上期值',
+              key:'last_value'
+            }
+          ]
+        }else{
+          this.tickerHead=[
+            {
+              label:res.data.ticker_title.ticker_title,
+              key:'base_column_name'
+            },
+            {
+              label:res.data.list[0].date,
+              key:'ticker_value'
+            },
+            {
+              label:'当日涨跌',
+              key:'dd_value'
+            },
+            {
+              label:'一周涨跌',
+              key:'ww_value'
+            },
+            {
+              label:'一月涨跌',
+              key:'mm_value'
+            }
+          ]
+        }
+      }
+    },
+
+    handleBackTop() {
+      document.body.scrollTop=document.documentElement.scrollTop=0
+    },
+
+    //格式化音频时间
+    formatVoiceTime(e){
+      let minus=parseInt(e/60)
+      let sec=parseInt(e%60)
+      return `${minus>9?minus:'0'+minus}分${sec>9?sec:'0'+sec}秒`
+    },
+
+    formatTime(time){
+      return moment(time).format('YYYY.MM.DD HH:mm:ss')
+    },
+
+    handleChapterChange(item){
+      this.chapterId=item.report_chapter_id
+      this.info=null
+      this.getDetail()
+      this.handleBackTop()
+    },
+
+    // 联系销售
+    // handleContact(){
+    //   uni.makePhoneCall({
+    //     phoneNumber: this.info.permission_check.mobile
+    //   });
+    // },
+
+    //点击申请
+    async handleGoApply(){
+      if(this.info.permission_check.type=='apply'){
+        if(this.info.permission_check.customer_info.has_apply){// 已经申请过
+          this.pupData.show=true
+					this.pupData.content=`<p>您已提交过申请,请耐心等待</p>`
+        }else{
+          if(!this.info.permission_check.customer_info.status||this.info.permission_check.customer_info.status!='流失'){
+            wx.miniProgram.redirectTo({
+              url:"/pages-applyPermission/applyPermission?source=4&from_page=报告详情"
+            })
+          }else{//主动调一次申请权限接口 
+            const res=await apiApplyPermission({
+              company_name:this.info.permission_check.customer_info.company_name,
+              real_name:this.info.permission_check.customer_info.name,
+              source:4,
+              from_page:'报告详情'
+            })
+            if(res.code===200){
+              this.pupData.show=true
+					    this.pupData.content=`<p>申请已提交</p><p>请等待销售人员与您联系</p>`
+              this.getDetail()
+            }
+          }
+        }
+                
+      }
+    },
+
+    //下拉刷新
+    onRefresh(){
+      this.getDetail()
+      setTimeout(() => {
+        this.loading=false
+      }, 1500);
+    }
+
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+/* 公共弹窗 */
+.global-pup{
+    background-color: #fff;
+    width: 90vw;
+    min-height: 200px;
+    font-size: 32px;
+    .content{
+        padding: 34px;
+        text-align: center;
+        min-height: 250px;
+        display: flex;
+        align-items: center;
+        text-align: center;
+        line-height: 1.7;
+        div{
+            flex: 1;
+        }
+    }
+    .bot{
+        border-top: 1px solid #dedede;
+        div{
+            line-height: 96px;
+            flex: 1;
+            text-align: center;
+            border-right: 1px solid #dedede;
+            color:#E3B377;
+        }
+        div:last-child {
+            border: none;
+        }
+    }
+}
+.flex{
+  display: flex;
+}
+.chapter-detail-page {
+    // padding-bottom: 50px;
+    .main-box{
+        padding: 34px;
+    }
+    .main-box-noauth{
+        height: 100vh;
+        overflow: hidden;
+    }
+    .title{
+        font-size: 46px;
+        font-weight: bold;
+        margin-bottom: 30px;
+        display: inline;
+        margin-left: -26px;
+    }
+    .time{
+        justify-content: space-between;
+        font-size: 30px;
+        margin-top: 30px;
+    }
+
+    .tips{
+        font-size: 34px;
+        margin-bottom: 51px;
+        &::before{
+            content: '';
+            width: 10px;
+            height: 50px;
+            display: inline-block;
+            background-color: #E3B377;
+            margin-right: 20px;
+            position: relative;
+            top: 10px;
+        }
+    }
+
+    .disclaimers-box{
+        width: 94vw;
+        padding: 32px;
+    }
+
+    .rich-content{
+        line-height: 1.8;
+        font-size: 36px;
+        :deep(img){
+            width: 100% !important;
+        }
+        :deep(span){
+            font-size: 36px !important;
+            line-height: 1.8 !important;
+        }
+        :deep(p){
+            font-size: 36px !important;
+            line-height: 1.8 !important;
+        }
+    }
+
+    .no-auth-wrap{
+      min-height: 200px;
+      background: linear-gradient(360deg, #FFFFFF 60%, rgba(255, 255, 255, 0) 88%);
+      // position: relative;
+      // top: -150px;
+      padding: 0 34px 50px 34px;
+      position: fixed;
+      left: 0;
+      right: 0;
+      bottom: 0;
+      z-index: 99;
+      text-align: center;
+      font-size: 32px;
+      color: #E3B377;
+      .apply-box{
+        padding-top: 250px;
+      }
+      .btn{
+        width: 100%;
+        margin-left: auto;
+        margin-right: auto;
+        line-height: 80px;
+        background-color: #E6B77D;
+        border-radius: 4px;
+        color: #fff;
+        margin-top: 100px;
+        display: block;
+      }
+    }
+
+    .back-top-img{
+        position: fixed;
+        z-index: 99;
+        width: 76px;
+        height: 76px;
+        right: 34px;
+        bottom: 150px;
+    }
+    .chapter-list-wrap {
+    background-color: #f5f6fa;
+    padding: 34px;
+    min-height: 300px;
+    .top-text {
+      text-align: center;
+      color: #666666;
+      margin-bottom: 30px;
+      &::before {
+        content: "";
+        width: 90px;
+        height: 1px;
+        background-color: #999;
+        display: inline-block;
+        vertical-align: middle;
+        margin-right: 10px;
+      }
+      &::after {
+        content: "";
+        width: 90px;
+        height: 1px;
+        background-color: #999;
+        display: inline-block;
+        vertical-align: middle;
+        margin-left: 10px;
+      }
+    }
+    .item {
+      background-color: #fff;
+      height: 156px;
+      margin-bottom: 20px;
+      text-align: center;
+      color: #C0CFDA;
+      font-size: 24px;
+      // padding-top: 20px;
+      border-radius: 8px;
+      overflow: hidden;
+      img{
+        width: 156px;
+        height: 156px;
+        display: block;
+        margin-left: auto;
+        margin-right: auto;
+        object-fit: cover;
+      }
+    }
+    .active{
+      border: 1px solid #E3B377;
+      position: relative;
+      &::before{
+        content: '';
+        display: block;
+        position: absolute;
+        left: 0;
+        top: 0;
+        width: 0;
+        height: 0;
+        border-top: 46px solid #E3B377;
+        border-right: 46px solid transparent;
+      } 
+    }
+    }
+
+  .ticker-wrap{
+    margin-top: 30px;
+    .top-title{
+      text-align: center;
+      font-size: 36px;
+      font-weight: bold;
+      vertical-align: middle;
+      &::before,&::after{
+        content: '';
+        display: inline-block;
+        width: 100px;
+        height: 4px;
+        background-color:rgb(204, 204, 204);
+        vertical-align: middle;
+        margin: 0 20px;
+      }
+
+    }
+    .table-box{
+      margin: 20px 0;
+      &::-webkit-scrollbar{
+        width: 0;
+      }
+      overflow: auto hidden;
+      .table-row{
+        display: flex;
+        width: 100%;
+      }
+      .table-item{
+        padding: 10px;
+        min-width: 200px;
+        max-width: 280px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+      }
+      .table-head{
+        color: #fff;
+        background-color: rgb(58, 76, 115);
+        .table-item{
+          &:first-child{
+            position: sticky;
+            left: 0;
+            z-index: 5;
+            border-right-color: rgb(58, 76, 115);
+          }
+          background-color: rgb(58, 76, 115);
+        }
+      }
+      .table-body{
+        .table-item{
+          background-color: #fff;
+          &:first-child{
+            position: sticky;
+            left: 0;
+            z-index: 5;
+          }
+        }
+        .grey{
+          background-color: #ddd;
+        }
+        .minus{
+          color: #006600;
+        }
+      }
+    }
+  }
+
+}
+</style>

+ 619 - 0
src/views/hzyb/report/Detail.vue

@@ -0,0 +1,619 @@
+<template>
+<van-pull-refresh v-model="loading" @refresh="onRefresh" style="min-height:100vh">
+    <div class="report-detail-page" v-if="info" :style="{paddingBottom:$store.state.hzyb.audioData.url&&'80px'}">
+        <!-- 晨报、周报章节 -->
+        <div class="chapter-list-wrap" v-if="['晨报','周报'].includes(info.report_info.classify_name_first)">
+            <div class="top-box" :style="'background-image:url(' + info.report_info.banner_url + ')'">
+                <div class="title">{{info.report_info.classify_name_first}}</div>
+                <div class="sub-title">{{info.report_info.title}}</div>
+                <div class="flex top-bot">
+                    <div class="flex time-box">
+                        <div class="day">{{formatChapterTime(info.report_info.publish_time,'day')}}</div>
+                        <div>
+                            <div>{{formatChapterTime(info.report_info.publish_time,'week')}}</div>
+                            <div>{{formatChapterTime(info.report_info.publish_time,'year-month')}}</div>
+                        </div>
+                    </div>
+                    <div class="num">第{{info.report_info.stage}}期</div>
+                </div>
+            </div>
+            <div class="list-box">
+                <div class="flex item" v-for="item in chapterList" :key="item.report_chapter_id" @click="goChapterDetail(item)">
+                    <van-image class="img" :src="item.report_chapter_type_thumb" mode="aspectFill" />
+                    <div class="con">
+                        <div class="title">
+                            {{item.report_chapter_type_name}} 
+                            <text class="tag" :style="{backgroundColor:getTagColor(tag)}" v-for="tag in item.trend.split(',')" :key="tag">{{tag}}</text>
+                        </div>
+                        <div class="van-multi-ellipsis--l2 sub-title">{{item.title}}</div>
+                        <div class="update-time">更新至:{{formatChapterTime(item.publish_time,'year-month-day')}}</div>
+                    </div>
+                </div>
+            </div>
+            <!-- 无权限 -->
+            <div class="no-auth-box" v-if="!info.auth_ok">
+                <img class="img" 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>
+                <div class="apply-box" v-else>
+                    <div>您暂无权限查看报告 </div>
+                    <div>若想查看请联系对口销售:{{info.permission_check.name}}</div>
+                    <a class="btn" :href="'tel:'+info.permission_check.mobile" tag="div">立即联系</a>
+                </div>
+            </div>
+        </div>
+
+        <!-- 报告详情 -->
+        <div :class="['main-box',!info.auth_ok&&'main-box-noauth']" v-else>
+            <div class="title">【第{{info.report_info.stage}}期|{{info.report_info.classify_name_second}}】{{info.report_info.title}}</div>
+            <div class="flex time">
+                <span>FICC团队</span>
+                <span>{{formatTime(info.report_info.publish_time)}}</span>
+            </div>
+            <!-- 音频模块 -->
+            <AudioBox :audioData="audioData" v-if="info.report_info.video_url&&info.report_info.video_play_seconds>0"></AudioBox>
+            <div class="tips">
+                <span>注:请务必阅读</span>
+                <span style="color:#E3B377;margin-left:20px" @click="showDisclaimers=true">免责声明</span>
+            </div>
+
+            <div class="rich-content">
+                <div v-html="info.report_info.content" v-if="info.auth_ok"></div>
+                <div v-html="info.report_info.content_sub" v-else></div>
+            </div>
+
+            <!-- 无权限 -->
+            <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>
+                <div class="apply-box" v-else>
+                    <div>您暂无权限查看报告 </div>
+                    <div>若想查看请联系对口销售:{{info.permission_check.name}}</div>
+                    <a class="btn" :href="'tel:'+info.permission_check.mobile" tag="div">立即联系</a>
+                </div>
+            </div>
+
+            <!-- 返回顶部 -->
+            <img v-if="showToTop&&info.auth_ok" @click="handleBackTop" class="back-top-img" src="@/assets/hzyb/report/back-top.png" mode="aspectFill"/>
+
+            <!-- 分享海报 -->
+            <Teleport to="body">
+            <SharePoster 
+                :style="{bottom:'125px'}" 
+                :shareData="{
+                    type:'report_detail',
+                    code_page:'pages-report/reportDetail',
+                    code_scene:code_scene,
+                    data:posterParams
+                }"
+                v-if="info.auth_ok"
+            ></SharePoster>
+            </Teleport>
+        </div>
+
+        <!-- 免责声明 -->
+        <van-popup :show="showDisclaimers" @close="showDisclaimers=false" round closeable>
+            <div class="disclaimers-box">
+                <div style="text-align:center;font-size:16px;font-weight:bold;margin-bottom:20px">免责声明</div>
+                <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>
+        </van-popup>
+
+        <!-- 申请提示弹窗 -->
+        <van-popup :show="pupData.show" @close="pupData.show=false" :close-on-click-overlay="false">
+            <div class="global-pup">
+                <div class="content">
+                    <div v-html="pupData.content"></div>
+                </div>
+                <div class="flex bot">
+                    <div @click="pupData.show=false">知道了</div>
+                </div>
+            </div>
+        </van-popup>
+    </div>
+    
+</van-pull-refresh>
+</template>
+
+<script>
+// 由于当时写在uni中 直接复制过来的 也不想改了就写成vue2形式吧
+import moment from 'moment'
+import 'moment/dist/locale/zh-cn'
+moment.locale('zh-cn')
+
+import {apiReportDetail} from '@/api/hzyb/report'
+import {apiApplyPermission} from '@/api/hzyb/user'
+import {Popup,Image as VanImage,PullRefresh} from 'vant'
+import AudioBox from './components/AudioBox.vue'
+import SharePoster from '../components/SharePoster.vue'
+export default {
+    components:{
+        [Popup.name]:Popup,
+        [VanImage.name]:VanImage,
+        [PullRefresh.name]:PullRefresh,
+        AudioBox,
+        SharePoster
+    },
+    computed:{
+        code_scene(){
+            return JSON.stringify({
+                reportId:this.reportId
+            })
+        },
+        posterParams(){
+            return {
+                report_type:this.info.report_info.classify_name_first,
+                report_title:`【第${this.info.report_info.stage}期 | ${this.info.report_info.classify_name_second}】${this.info.report_info.title}`,
+                report_abstract:this.info.report_info.content
+            }
+        }
+    },
+    data () {
+        return {
+            showDisclaimers:false,//显示免责声明
+            reportId:0,
+            info:null,
+            audioData:{},//音频数据
+            chapterList:[],
+            pupData:{
+				show:false,
+				content:'',//弹窗html字符串
+			},
+            loading:false,
+            showToTop:false
+        }
+    },
+    beforeCreate(){
+        if(this.$route.query.token){
+            localStorage.setItem('hzyb-token',this.$route.query.token)
+        }
+    },
+    created(options) {
+        this.reportId=this.$route.query.reportId
+        this.getDetail()
+    },
+    mounted(){
+        $(document).on('click', '.rich-content img',function(event) {
+            let imgArray = [];
+            let curImageSrc = $(this).attr('src');
+            let oParent = $(this).parent();
+            if (curImageSrc && !oParent.attr('href')) {
+                $('.rich-content img').each(function(index, el) {
+                    let itemSrc = $(this).attr('src');
+                    imgArray.push(itemSrc);
+                });
+                wx.previewImage({current:curImageSrc,urls:imgArray});
+            }
+        })
+        window.addEventListener('scroll',this.handelPageScroll)
+    },
+    destroyed () {
+        window.removeEventListener('scroll',this.handelPageScroll)
+    },
+    methods: {
+        // 页面滚动
+        handelPageScroll(){
+            const top=document.documentElement.scrollTop||document.body.scrollTop
+            if(top>window.outerHeight){
+                this.showToTop=true
+            }else{
+                this.showToTop=false
+            }
+        },
+        
+        //获取报告详情
+        async getDetail(){
+            const res=await apiReportDetail({report_id:Number(this.reportId)})
+            if(res.code===200){
+                this.info=res.data
+                this.audioData={
+                    auth_ok:res.data.auth_ok,
+                    video_name:res.data.report_info.video_name,
+                    video_play_seconds:res.data.report_info.video_play_seconds,
+                    video_url:res.data.report_info.video_url,
+                    video_img:res.data.report_info.video_img
+                }
+                this.chapterList=res.data.report_chapter_list
+                document.title = res.data.report_info.classify_name_first
+                if(!res.data.auth_ok){
+                    // 获取详情如果为联系销售根据判断条件是否主动申请一次
+                    if(this.info.permission_check.type=='contact'&&!this.info.permission_check.customer_info.has_apply){
+                        if(this.info.permission_check.customer_info.status=='冻结'||(this.info.permission_check.customer_info.status=='试用'&&this.info.permission_check.customer_info.is_suspend==1)){
+                            apiApplyPermission({
+                                company_name:this.info.permission_check.customer_info.company_name,
+                                real_name:this.info.permission_check.customer_info.name,
+                                source:4,
+                                from_page:'报告详情'
+                            }).then(res=>{
+                                if(res.code===200){
+                                    console.log('主动申请成功');
+                                }
+                            }) 
+                        }
+                    }
+                }
+                //向小程序发送分享数据
+                wx.miniProgram.postMessage({ 
+                    data: {
+                        title:`FICC【${res.data.report_info.classify_name_first}】`,
+                        reportId:this.reportId
+                    } 
+                });
+                
+            }
+        },
+        
+        //返回顶部
+        handleBackTop(){
+            document.body.scrollTop=document.documentElement.scrollTop=0
+        },
+
+        //跳转章节详情
+        goChapterDetail(item){
+            // this.$router.push({
+            //     path:'/hzyb/report/chapterdetail',
+            //     query:{
+            //         chapterId:item.report_chapter_id
+            //     }
+            // })
+            wx.miniProgram.navigateTo({
+                url:`/pages-report/chapterDetail?chapterId=${item.report_chapter_id}&fromPage=reportdetail`
+            })
+        },
+        
+        // 格式化时间
+        formatTime(time){
+            return moment(time).format('YYYY.MM.DD HH:mm:ss')
+        },
+
+        //格式化音频时间
+        formatVoiceTime(e){
+            let minus=parseInt(e/60)
+            let sec=parseInt(e%60)
+            return `${minus>9?minus:'0'+minus}分${sec>9?sec:'0'+sec}秒`
+        },
+
+        // 格式化章节列表时间
+        formatChapterTime(time,type){
+            if(type==='day'){
+                return moment(time).format('DD')
+            }
+            if(type==='week'){
+                return moment(time).format('dddd')
+            }
+            if(type==='year-month'){
+                return moment(time).format('YYYY-MM')
+            }
+            if(type==='year-month-day'){
+                return moment(time).format('YYYY-MM-DD')
+            }
+        },
+
+        // 联系销售
+        // handleContact(){
+        //     uni.makePhoneCall({
+        //         phoneNumber: this.info.permission_check.mobile
+        //     });
+        // },
+
+        //点击申请
+        async handleGoApply(){
+            if(this.info.permission_check.type=='apply'){
+                if(this.info.permission_check.customer_info.has_apply){// 已经申请过
+                    this.pupData.show=true
+					this.pupData.content=`<p>您已提交过申请,请耐心等待</p>`
+                }else{
+                    if(!this.info.permission_check.customer_info.status||this.info.permission_check.customer_info.status!='流失'){
+                        wx.miniProgram.redirectTo({
+                            url:"/pages-applyPermission/applyPermission?source=4&from_page=报告详情"
+                        })
+                    }else{//主动调一次申请权限接口 
+                        const res=await apiApplyPermission({
+                            company_name:this.info.permission_check.customer_info.company_name,
+                            real_name:this.info.permission_check.customer_info.name,
+                            source:4,
+                            from_page:'报告详情'
+                        })
+                        if(res.code===200){
+                            this.pupData.show=true
+					        this.pupData.content=`<p>申请已提交</p><p>请等待销售人员与您联系</p>`
+                            this.getDetail()
+                        }
+                    }
+                }
+                
+            }
+        },
+
+        onRefresh() {
+            this.getDetail()
+            setTimeout(() => {
+                this.loading=false
+            }, 1500);
+        },
+
+        // 设置tag颜色
+        getTagColor(str){
+            if( str.includes('多')||str.includes('强')||str.includes('反弹') ){
+                return "#DF6051";
+            }else if( str.includes('空')||str.includes('调整') ){
+                return "#6FC5B4";
+            }else{
+                return "#009fe6";
+            }
+        }
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+/* 公共弹窗 */
+.global-pup{
+    background-color: #fff;
+    width: 90vw;
+    min-height: 200px;
+    font-size: 32px;
+    .content{
+        padding: 34px;
+        text-align: center;
+        min-height: 250px;
+        display: flex;
+        align-items: center;
+        text-align: center;
+        line-height: 1.7;
+        div{
+            flex: 1;
+        }
+    }
+    .bot{
+        border-top: 1px solid #dedede;
+        div{
+            line-height: 96px;
+            flex: 1;
+            text-align: center;
+            border-right: 1px solid #dedede;
+            color:#E3B377;
+        }
+        div:last-child {
+            border: none;
+        }
+    }
+}
+.flex{
+    display: flex;
+}
+.report-detail-page{
+    padding-bottom: 50px;
+    .main-box{
+        padding: 34px;
+        .title{
+            display: inline;
+            margin-left: -26px;
+        }
+    }
+    .main-box-noauth{
+        height: calc(100vh - 50px);
+        overflow: hidden;
+    }
+    .title{
+        font-size: 46px;
+        font-weight: bold;
+        margin-bottom: 30px;
+    }
+    .time{
+        justify-content: space-between;
+        font-size: 30px;
+        margin-top: 30px;
+    }
+    .audio-wrap{
+        height: 160px;
+        background: #FAF7EE;
+        border-radius: 16px;
+        margin-top: 20px;
+        padding: 10px 31px;
+        margin-bottom: 31px;
+        align-items: center;
+        img{
+            width: 110px;
+            height: 110px;
+            display: block;
+            margin-right: 16px;
+        }
+    }
+
+    .tips{
+        font-size: 34px;
+        margin-bottom: 51px;
+        &::before{
+            content: '';
+            width: 10px;
+            height: 50px;
+            display: inline-block;
+            background-color: #E3B377;
+            margin-right: 20px;
+            position: relative;
+            top: 10px;
+        }
+    }
+
+    .disclaimers-box{
+        width: 94vw;
+        padding: 32px;
+    }
+
+    .rich-content{
+        line-height: 1.8;
+        font-size: 36px;
+        :deep(img){
+            width: 100% !important;
+        }
+        :deep(span){
+            font-size: 36px !important;
+            line-height: 1.8 !important;
+        }
+        :deep(p){
+            font-size: 36px !important;
+            line-height: 1.8 !important;
+        }
+    }
+
+    .no-auth-wrap{
+      min-height: 200px;
+      padding: 0 34px 50px 34px;
+      background: linear-gradient(360deg, #FFFFFF 60%, rgba(255, 255, 255, 0) 88%);
+    //   position: relative;
+    //   top: -150px;
+      position: fixed;
+      left: 0;
+      right: 0;
+      bottom: 0;
+      z-index: 99;
+      text-align: center;
+      font-size: 32px;
+      color: #E3B377;
+      .apply-box{
+        padding-top: 250px;
+      }
+      .btn{
+        width: 100%;
+        margin-left: auto;
+        margin-right: auto;
+        line-height: 80px;
+        background-color: #E6B77D;
+        border-radius: 4px;
+        color: #fff;
+        margin-top: 100px;
+        display: block;
+      }
+    }
+
+    .back-top-img{
+        position: fixed;
+        z-index: 99;
+        width: 76px;
+        height: 76px;
+        right: 34px;
+        bottom: 150px;
+    }
+
+    .chapter-list-wrap{
+        .top-box{
+            height: 418px;
+            background-color: rgba($color: #000000, $alpha: 0.7);
+            background-size: cover;
+            color: #fff;
+            position: relative;
+            .title{
+                text-align: center;
+                font-size: 34px;
+                font-weight: 600;
+                padding-top: 78px;
+            }
+            .sub-title{
+                font-size: 32px;
+                text-align: center;
+                width: 70%;
+                margin-left: auto;
+                margin-right: auto;
+            }
+            .top-bot{
+                position: absolute;
+                bottom: 70px;
+                left: 34px;
+                right: 34px;
+                justify-content: space-between;
+                align-items: flex-end;
+                .time-box{
+                    align-items: center;
+                    font-size: 24px;
+                    .day{
+                        font-size: 32px;
+                        border-right: 1px solid #fff;
+                        padding-right: 15px;
+                        margin-right: 15px;
+                    }
+                }
+                
+            }
+        }
+        .list-box{
+            margin-top: -50px;
+            border-top-left-radius: 40px;
+            border-top-right-radius: 40px;
+            min-height: 100px;
+            background-color: #fff;
+            position: relative;
+            z-index: 2;
+            .item{
+                padding: 30px 34px;
+                border-bottom: 1px solid #E5E5E5;
+                .img{
+                    width: 104px;
+                    height: 104px;
+                    // background-color: #f5f5f5;
+                    flex-shrink: 0;
+                    margin-right: 20px;
+                }
+                .con{
+                    flex: 1;
+                    position: relative;
+                    .title{
+                        font-size: 28px;
+                        color: #57768D;
+                        font-weight: bold;
+                        margin-bottom: 5px;
+                        .tag{
+                            font-size: 20px;
+                            color: #fff;
+                            font-weight: normal;
+                            display: inline-block;
+                            background-color: #1E88E5;
+                            line-height: 37px;
+                            padding: 0 6px;
+                            border-radius: 4px;
+                            margin-left: 10px;
+                        }
+                    }
+                    .sub-title{
+                        color: #999;
+                    }
+                    .update-time{
+                        position: absolute;
+                        top: 0;
+                        right: 0;
+                        color: #D4D4D4;
+                        font-size: 20px;
+                    }
+                }
+            }
+        }
+        .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>

+ 69 - 0
src/views/hzyb/report/components/AudioBox.vue

@@ -0,0 +1,69 @@
+<script setup>
+import {reactive, ref} from 'vue'
+import { Slider } from 'vant';
+import { useStore } from "vuex";
+
+const store=useStore()
+
+const props = defineProps({
+  audioData: Object,
+});
+
+const formatVoiceTime = (e) => {
+  let minus = parseInt(e / 60);
+  let sec = parseInt(e % 60);
+  return `${minus > 9 ? minus : "0" + minus}分${sec > 9 ? sec : "0" + sec}秒`;
+};
+
+const audioIconPlay=new URL('../../../../assets/hzyb/report/audio-play.png', import.meta.url).href
+const audioIconPause=new URL('../../../../assets/hzyb/report/audio-pause.png', import.meta.url).href
+
+
+const handleClickAudio=()=>{
+    if(store.state.hzyb.audioData.url==props.audioData.video_url){
+      if(store.state.hzyb.audioData.paused){
+        store.state.hzyb.audioData.INS.play()
+        store.commit('hzyb/showAudioPop')
+      }else{
+        store.state.hzyb.audioData.INS.pause()
+      }
+    }else{
+        store.commit('hzyb/addAudio',props.audioData)
+    }
+}
+
+
+</script>
+
+<template>
+  <div class="flex audio-wrap">
+    <img style="opacity: 0.3" src="@/assets/hzyb/report/audio-pause.png" mode="aspectFill" v-if="!audioData.auth_ok" />
+    <img :src="$store.state.hzyb.audioData.url==audioData.video_url&&!$store.state.hzyb.audioData.paused?audioIconPlay:audioIconPause" @click="handleClickAudio" v-else />
+    <div style="flex:1;overflow:hidden">
+      <div class="van-multi-ellipsis--l2">{{ audioData.video_name }}</div>
+      <div style="color: #999999">{{ formatVoiceTime(audioData.video_play_seconds) }}</div>
+    </div>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.flex{
+    display: flex;
+}
+.audio-wrap {
+  height: 160px;
+  background: #faf7ee;
+  border-radius: 16px;
+  margin-top: 20px;
+  padding: 10px 31px;
+  margin-bottom: 31px;
+  align-items: center;
+  img {
+    width: 110px;
+    height: 110px;
+    display: block;
+    margin-right: 16px;
+    flex-shrink: 0;
+  }
+}
+</style>