Karsa 3 жил өмнө
parent
commit
5818962ded

+ 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);

BIN
src/assets/hzyb/loading.png


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


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


+ 62 - 9
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';
@@ -156,6 +158,8 @@ const chartItemStyleArr = ref([
     { label: '散点图', key: 5 ,value: 'scatter'}
 ])//组合图配置时可选类型
 
+let noauth=ref(false)
+let noAuthData=ref(null)
 // 如果type:init 则是初始化获取数据 
 const getChartInfo=async (type)=>{
     // resData.value=null
@@ -195,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')
@@ -702,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})
@@ -914,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">
@@ -927,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>
@@ -934,13 +985,14 @@ 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&&sameOptionType.includes(resData.ChartInfo.ChartType)">
@@ -973,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"
@@ -1030,8 +1083,8 @@ const pageTouchmove=(e)=>{
             </div>
         </Popup>
     </div>
-    
-    
+    <!-- 无权限 -->
+    <noAuth v-if="noauth" :data="noAuthData"></noAuth>
 
 </template>
 
@@ -1073,7 +1126,7 @@ const pageTouchmove=(e)=>{
             float: right;
             width: 40px;
             height: 40px;
-            margin-left: 50px;
+            margin-left: 30px;
         }
     }
     .select-date-box-head{

+ 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>

+ 38 - 7
src/views/hzyb/report/ChapterDetail.vue

@@ -50,8 +50,8 @@
       <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" mode="aspectFill"/>
-            <text>{{item.report_chapter_type_name}}</text>
+            <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>
@@ -86,6 +86,20 @@
             </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>
@@ -100,6 +114,7 @@ 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,
@@ -108,7 +123,22 @@ export default {
     [Col.name]:Col,
     [Row.name]:Row,
     [PullRefresh.name]:PullRefresh,
-    AudioBox
+    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 {
@@ -496,20 +526,21 @@ export default {
     }
     .item {
       background-color: #fff;
-      height: 160px;
+      height: 156px;
       margin-bottom: 20px;
       text-align: center;
       color: #C0CFDA;
       font-size: 24px;
-      padding-top: 20px;
+      // padding-top: 20px;
       border-radius: 8px;
       overflow: hidden;
       img{
-        width: 88px;
-        height: 88px;
+        width: 156px;
+        height: 156px;
         display: block;
         margin-left: auto;
         margin-right: auto;
+        object-fit: cover;
       }
     }
     .active{

+ 32 - 1
src/views/hzyb/report/Detail.vue

@@ -79,6 +79,20 @@
 
             <!-- 返回顶部 -->
             <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>
 
         <!-- 免责声明 -->
@@ -104,6 +118,7 @@
             </div>
         </van-popup>
     </div>
+    
 </van-pull-refresh>
 </template>
 
@@ -117,12 +132,28 @@ 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
+        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 {