소스 검색

Merge branch 'master' into xqc_htgj

bding 2 년 전
부모
커밋
3af10187c7

+ 1 - 1
.env.development

@@ -3,7 +3,7 @@ VITE_APP_OUTDIR="raiwechat_link_h5"
 
 VITE_APP_CYGX_BASEAPIURL="http://8.136.199.33:8500/api"
 
-VITE_APP_HZYB_BASEAPIURL="http://8.136.199.33:8612/api"
+VITE_APP_HZYB_BASEAPIURL="https://ybpctest.hzinsights.com/api"
 
 VITE_APP_HZSL_BASEAPIURL="http://8.136.199.33:8608/api"
 

+ 1 - 1
.env.test

@@ -3,7 +3,7 @@ VITE_APP_OUTDIR="raiwechat_link_h5"
 
 VITE_APP_CYGX_BASEAPIURL="http://8.136.199.33:8500/api"
 
-VITE_APP_HZYB_BASEAPIURL="http://8.136.199.33:8612/api"
+VITE_APP_HZYB_BASEAPIURL="https://ybpctest.hzinsights.com/api"
 
 VITE_APP_HZSL_BASEAPIURL="http://8.136.199.33:8608/api"
 

+ 60 - 0
src/api/hzyb/chart.js

@@ -51,4 +51,64 @@ export const apiChartSave=params=>{
  */
 export const apiChartRefresh=params=>{
     return post('/my_chart/refreshChartInfo',params)
+}
+
+/**
+ * 小程序中我的图库中查看详情
+ * @param ChartInfoId
+ */
+export const apiMyChartDetail=params=>{
+    return get('/my_chart/detail',params)
+}
+
+/**
+ * 图表是否收藏了
+ * @param unique_code
+ * @param authorization
+ */
+export const apiChartIsCollect=params=>{
+    return get('/my_chart/is_collect',params)
+}
+
+/**
+ * 收藏图表
+ * unique_code:string,
+    authorization:string,
+    report_id:number,
+    report_chapter_id:number
+ */
+
+export const apiChartCollect=params=>{
+    return post('/my_chart/collect',params)
+}
+
+/**
+ * 取消收藏
+ */
+export const apiChartCollectCancel=params=>{
+    return post('/my_chart/collect_cancel',params)
+}
+
+/**
+ * 我的图表中我的分类
+ */
+export const apiMyChartClassifyList=()=>{
+    return get('/my_chart_classify/list',{})
+}
+
+/**
+ * 我的图表关联分类
+ * @param my_chart_id
+ * @param classify_id
+ */
+export const apiMyChartRelateClassify=params=>{
+    return post('/my_chart/relate_classify',params)
+}
+
+/**
+ * 新增我的图库分类
+ * @param classify_name
+ */
+export const apiMyChartClassifyAdd=params=>{
+    return post('/my_chart_classify/add',params)
 }

+ 2 - 2
src/api/hzyb/http.js

@@ -11,7 +11,7 @@ import CryptoJS from './crypto'
 // 请求数
 let LOADINGCOUNT = 0;
 let LOADING;
-console.log(import.meta.env.VITE_APP_HZYB_BASEAPIURL);
+// console.log(import.meta.env);
 let config = {
   baseURL: import.meta.env.VITE_APP_HZYB_BASEAPIURL,
   timeout: 10*60 * 1000, // Timeout
@@ -62,7 +62,7 @@ _axios.interceptors.response.use(
     }else{
       data=response.data
     }
-    console.log(data);
+    // console.log(data);
     if(![200,403].includes(data.code)){
       setTimeout(() => {
         Toast(data.msg)

BIN
src/assets/hzyb/chart/transf.png


+ 45 - 17
src/views/hzyb/chart/Detail.vue

@@ -2,13 +2,14 @@
 import chartBox from './component/chartBox.vue'
 import noAuth from './component/noAuth.vue'
 import sharePoster from '../components/SharePoster.vue'
+import collectBox from './component/collectBox.vue'
 import { Popup, Toast,Picker } from 'vant';
 import {ref,onMounted, reactive, watch,computed} from 'vue'
 import {useRoute, useRouter,onBeforeRouteUpdate} from 'vue-router'
 import moment from 'moment'
 import _ from 'lodash';
 import Highcharts from 'highcharts/highstock';
-import {apiChartInfo,apiChartList,apiChartSave,apiChartBeforeAndNext,apiChartRefresh} from '@/api/hzyb/chart.js'
+import {apiChartInfo,apiChartList,apiChartSave,apiChartBeforeAndNext,apiChartRefresh,apiMyChartDetail} from '@/api/hzyb/chart.js'
 const router=useRouter()
 const route=useRoute()
 document.title='图表详情'
@@ -213,17 +214,25 @@ let noAuthData=ref(null)
 const getChartInfo=async (type)=>{
     // resData.value=null
     loading.value=true
-    const res=await apiChartInfo({
-        ChartInfoId:ChartInfoId,
-        DateType:dateType.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,
-        Authorization:route.query.token,
-        MyChartClassifyId:Number(route.query.MyChartClassifyId)
-    })
+    let res=null
+    // 如果是从我的图库中来的
+    if(route.query.source=='ybxcx_my_chart'){
+        res=await apiMyChartDetail({
+            ChartInfoId:ChartInfoId,
+        })
+    }else{
+        res=await apiChartInfo({
+            ChartInfoId:ChartInfoId,
+            DateType:dateType.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,
+            Authorization:route.query.token,
+            MyChartClassifyId:Number(route.query.MyChartClassifyId)
+        })
+    }
     loading.value=false
     if(res.code===200){
         resData.value=res.data
@@ -1502,7 +1511,7 @@ const posterParams=computed(()=>{
 <template>
     <div class="chart-detail" v-if="!loading&&!noauth">
         <div class="chart-title">{{resData.ChartInfo.ChartName}}</div>
-        <div class="top-box">
+        <div class="top-box" v-if="$route.query.source!=='ybxcx_my_chart'">
             <div class="flex calendar-box" style="float:left" @click="handleShowDate" v-if="resData.ChartInfo.ChartType !== 7">
                 <img src="../../../assets/hzyb/chart/calendar.png" alt="">
                 <span class="date">{{startDate||'开始日期'}}</span>
@@ -1524,9 +1533,18 @@ const posterParams=computed(()=>{
             <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>
+        
+        <collectBox 
+            v-if="$route.query.source=='ybxcx_my_chart'"
+            :code="resData.ChartInfo.UniqueCode"
+            :myChartInfo="resData.MyChartInfo"
+        />
 
         <chartBox :options='chartData' v-if="!loading"></chartBox>
-        
+
+        <div class="source-box" style="margin-top:5px" v-if="$route.query.source=='ybxcx_my_chart'">来源:{{resData&&resData.ChartInfo.ChartSource}}</div>
+
+        <template v-if="$route.query.source!=='ybxcx_my_chart'">
         <div class="flex source-box">
             <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">
@@ -1574,10 +1592,11 @@ const posterParams=computed(()=>{
                 </li>
             </ul>
         </div>
+        </template>
 
         <!-- 上一张下一张图切换 -->
         <div 
-            v-if="$route.query.from!='share'"
+            v-if="$route.query.from!='share'&&$route.query.source!=='ybxcx_my_chart'"
             class="change-page-wrap" 
             :style="{left:pageBoxPosition.left+'px',top:pageBoxPosition.top+'px'}"
             @touchmove.stop="pageTouchmove"
@@ -1650,6 +1669,9 @@ const posterParams=computed(()=>{
 <style lang="scss" scoped>
 ::v-deep(.highcharts-axis-title) {
     font-size: 20px;
+    @media (min-width: 768px){
+        font-size: 16px;
+    }
 }
 .chart-detail{
     .flex{
@@ -1661,6 +1683,10 @@ const posterParams=computed(()=>{
         font-weight: bold;
         color: #1F243A;
         letter-spacing: 2px;
+        @media (min-width: 768px){
+            padding: 0px 0 20px 0;
+            font-size: 18px;
+        }
     }
     .top-box{
         padding: 20px 34px 40px 34px;
@@ -1737,6 +1763,10 @@ const posterParams=computed(()=>{
                 background-color: #E3B377;
             }
         }
+        @media (min-width: 768px){
+            padding: 0;
+            font-size: 16px;
+        }
     }
 
     .date-type-box{
@@ -1853,7 +1883,5 @@ const posterParams=computed(()=>{
         }
 
     }
-
-
 }
 </style>

+ 22 - 1
src/views/hzyb/chart/component/chartBox.vue

@@ -235,5 +235,26 @@ watch(
         margin-right: 34px;
     }
 }
-
+@media (min-width: 768px){
+	.chart-wrap{
+		margin-top: 30px;
+		.chart-top-labels{
+			padding: 0;
+			max-height: 200px;
+			.item{
+				font-size: 16px;
+				margin-right: 30px;
+				margin-bottom: 10px;
+				cursor: pointer;
+				.color{
+					width: 30px;
+					height: 4px;
+				}
+			}
+		}
+		.chart-box{
+			height: 500px;
+		}
+	}
+}
 </style>

+ 294 - 0
src/views/hzyb/chart/component/collectBox.vue

@@ -0,0 +1,294 @@
+<script setup>
+import {apiChartIsCollect,apiChartCollectCancel,apiChartCollect,apiMyChartClassifyList,apiMyChartRelateClassify,apiMyChartClassifyAdd} from '@/api/hzyb/chart'
+import { reactive, ref, watch } from 'vue'
+import { useRoute } from 'vue-router'
+import { Toast, Popup,Dialog } from 'vant'
+const VanDialog = Dialog.Component;
+
+const route=useRoute()
+
+const props = defineProps({
+  code: String,
+  myChartInfo:Object
+})
+
+watch(
+    ()=>props.code,
+    (n)=>{
+        if(n){
+            getIsCollect()
+        }
+    },
+    {
+        immediate:true
+    }
+)
+
+let isCollect=ref(false)
+async function getIsCollect(){
+    const res=await apiChartIsCollect({
+        unique_code:props.code,
+        authorization:route.query.token
+    })
+    if(res.code==200){
+        isCollect.value=res.data
+    }
+}
+
+function handleCollectStatusChange(){
+    if(isCollect.value){
+        collectChartCancel()
+    }else{
+        collectChart()
+    }
+}
+
+// 收藏
+async function collectChart(){
+    const res=await apiChartCollect({
+        unique_code:props.code,
+        authorization:route.query.token,
+        report_id:props.myChartInfo.report_id,
+        report_chapter_id:props.myChartInfo.report_chapter_id
+    })
+    if(res.code===200){
+        Toast('收藏成功')
+        isCollect.value=true
+        props.myChartInfo.my_chart_id=res.data
+    }
+}
+
+//取消收藏
+async function collectChartCancel(){
+    const res=await apiChartCollectCancel({
+        unique_code:props.code,
+        authorization:route.query.token
+    })
+    if(res.code===200){
+        Toast('取消收藏成功')
+        isCollect.value=false
+    }
+}
+
+let showTrans=ref(false)
+function handleShowTrans(type){
+    if(!isCollect.value){
+        Toast('您已经取消收藏,不可操作转移')
+        return
+    }
+    if(type==='mobile'){
+        showTrans.value=true
+    }else{
+        // pc端转移
+        window.parent.postMessage({
+            opt:'pcShowTransClassify',
+            myChartId:props.myChartInfo.my_chart_id,
+            classifyId:props.myChartInfo.my_chart_classify_id||0
+        },"*")
+    }
+    transData.selectId=props.myChartInfo.my_chart_classify_id||0
+    getClassify()
+}
+
+//获取分类数据
+let transData=reactive({
+    list:[],
+    selectId:0
+})
+async function getClassify(){
+    const res=await apiMyChartClassifyList()
+    if(res.code===200){
+        transData.list=res.data||[]
+    }
+}
+
+//添加分类
+let showAdd=ref(false)
+let inputClassifyVal=ref('')
+async function handleConfirmAdd(){
+    if(!inputClassifyVal.value){
+        Toast('请输入分类名称')
+        return
+    }
+    const res=await apiMyChartClassifyAdd({
+        classify_name:inputClassifyVal.value
+    })
+    if(res.code===200){
+        Toast.success('新增成功')
+        showAdd.value=false
+        inputClassifyVal.value=''
+    }
+}
+
+
+// 确定转移
+async function handleTrans(){
+    if(transData.list.length===0){
+        showAdd.value=true
+        showTrans.value=false
+        return
+    }
+    if(!transData.selectId){
+        Toast('请选择分类')
+        return
+    }
+    const res=await apiMyChartRelateClassify({
+        my_chart_id:props.myChartInfo.my_chart_id,
+        classify_id:transData.selectId
+    })  
+    if(res.code===200){
+        Toast('设置成功')
+        props.myChartInfo.my_chart_classify_id=transData.selectId
+        showTrans.value=false
+    }else{
+        Toast(res.msg)
+    }
+}
+
+window.addEventListener('message',e=>{
+    // 监听转移了分类
+    if(e.data.opt=="updateClassifyId"){
+        props.myChartInfo.my_chart_classify_id=e.data.id
+    }
+})
+
+
+</script>
+
+<template>
+    <div class="collect-box">
+        <span 
+            @click="handleCollectStatusChange"
+            :style="{color:isCollect?'#999999':'#E3B377'}"
+        >{{isCollect?'取消收藏':'收藏'}}</span>
+        <span class="trans" @click="handleShowTrans('mobile')">设置分类</span>
+        <span class="trans-pc" @click="handleShowTrans('pc')">设置分类</span>
+    </div>
+
+    <!-- 转移弹窗移动端 -->
+    <Popup
+        v-model:show="showTrans"
+        position="bottom"
+        closeable
+    >   
+        <div class="mobile-trans-box">
+            <div class="label">设置分类</div>
+            <div v-if="transData.list.length==0" style="line-height:250px;text-align:center">暂无分类,请先添加分类!</div>
+            <div class="list" v-else>
+                <div 
+                    :class="['item',item.my_chart_classify_id==transData.selectId?'active':'']" 
+                    v-for="item in transData.list" 
+                    :key="item.my_chart_classify_id"
+                    @click="transData.selectId=item.my_chart_classify_id"
+                >{{item.my_chart_classify_name}}</div>
+            </div>
+            <div class="btn" @click="handleTrans">确定</div>
+        </div>
+    </Popup>
+
+    <!-- 添加分类弹窗 -->
+    <van-dialog 
+        v-model:show="showAdd" 
+        title="添加分类" 
+        show-cancel-button
+        confirm-button-text="确定"
+        @cancel="showAdd=false"
+        @confirm="handleConfirmAdd"
+    >
+        <input class="add-input" v-model="inputClassifyVal" maxlength="10" type="text" placeholder="请输入分类名称">
+        <p style="color:#999;padding-left:10%;margin-bottom:40rpx;font-size:12px">注:字数控制在10个字以内!</p>
+    </van-dialog>
+</template>
+
+<style lang="scss" scoped>
+.collect-box{
+    padding: 20px 34px;
+    span{
+        margin-right: 60px;
+        vertical-align: middle;
+    }
+    .trans{
+        color: #E3B377;
+        &::before{
+            content: '';
+            display: inline-block;
+            width: 26px;
+            height: 26px;
+            background-image: url('@/assets/hzyb/chart/transf.png');
+            background-size: cover;
+            vertical-align: middle;
+            margin-right: 5px;
+        }
+    }
+    .trans-pc{
+        display: none;
+    }
+}
+@media (min-width: 768px){
+    .collect-box{
+        padding: 0;
+        font-size: 16px;
+        span{
+            cursor: pointer;
+            margin-right: 30px;
+        }
+    }
+    .trans{
+        display: none;
+    }
+    .trans-pc{
+        display: inline-block !important;
+        color: #E3B377;
+        &::before{
+            content: '';
+            display: inline-block;
+            width: 18px;
+            height: 18px;
+            background-image: url('@/assets/hzyb/chart/transf.png');
+            background-size: cover;
+            vertical-align: middle;
+            margin-right: 5px;
+        }
+    }
+}
+
+.mobile-trans-box{
+    padding-top: 27px;
+    .label{
+        text-align: center;
+        font-size: 32px;
+        font-weight: 500;
+        padding-bottom: 40px;
+    }
+    .list{
+        height: 40vh;
+        overflow-y: auto;
+        padding: 0 34px;
+        .item{
+            padding: 24px;
+            border-bottom: 1px solid #ededed;
+        }
+        .active{
+            color: #E3B377;
+        }
+    }
+    .btn{
+        background-color: #333;
+        color: #E3B377;
+        text-align: center;
+        line-height: 80px;
+        letter-spacing: 4px;
+    }
+}
+
+
+.add-input{
+    display: block;
+    width: 80%;
+    background: #F7F8FA;
+    border-radius: 8px;
+    padding: 20px;
+    margin: 30px auto 10px auto;
+    border: none;
+}
+</style>

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

@@ -140,6 +140,7 @@
 import moment from 'moment'
 import 'moment/dist/locale/zh-cn'
 moment.locale('zh-cn')
+import {addTokenToIframe} from '../utils/common'
 
 import {apiChapterDetail,apiChapterTickerValue,apiRddpShareImg,apiReportPPtImgs} from '@/api/hzyb/report'
 import {apiApplyPermission,apiUserInfo,apiSetCollect,apiCancelCollect} from '@/api/hzyb/user'
@@ -386,6 +387,7 @@ export default {
 
     /*内容分割*/
     splitContentHandle(content) {
+        content=addTokenToIframe(content,this.info.report_chapter_item.report_id,this.info.report_chapter_item.report_chapter_id)
         const arr = content.split('</p>');
         this.totalContent = arr.map(_ => _+'</p>');
         this.realContent = this.totalContent.slice(0,this.pageSize)

+ 35 - 6
src/views/hzyb/report/Detail.vue

@@ -18,8 +18,10 @@
                 </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="flex item" v-for="(item,index) in chapterList" :key="item.report_chapter_id" @click="goChapterDetail(item)">
+                    <div class="img-box">
+                        <van-image class="img" :src="item.report_chapter_type_thumb" mode="aspectFill" />
+                    </div>
                     <div class="con">
                         <div class="title">
                             {{item.report_chapter_type_name}} 
@@ -57,6 +59,7 @@
             <AudioBox :audioData="audioData" v-if="info.report_info.video_url&&info.report_info.video_play_seconds>0"></AudioBox>
             <div class="flex tips">
                 <div>
+                    <div v-if="info.road_video_id">点击<span style="color: #e3b377;" @click="goVideoPage">查看视频</span></div>
                     <div class="abstract" v-if="info.report_info.abstract">摘要:{{info.report_info.abstract}}</div>
                     <div>
                         <span>注:请务必阅读</span>
@@ -64,7 +67,6 @@
                     </div>
                 </div>
             </div>
-
             <div id="report-rich-content" class="rich-content" style="position: relative;" ref="richConBox">
                 <div v-if="info.auth_ok">
                     <ul>
@@ -157,6 +159,7 @@
 import moment from 'moment'
 import 'moment/dist/locale/zh-cn'
 moment.locale('zh-cn')
+import {addTokenToIframe} from '../utils/common'
 
 import {apiReportDetail,apiRddpShareImg,apiReportPPtImgs} from '@/api/hzyb/report'
 import {apiApplyPermission,apiUserInfo,apiSetCollect,apiCancelCollect} from '@/api/hzyb/user'
@@ -167,6 +170,7 @@ import _ from 'lodash';
 import LeaveMessage from '../components/leaveMessage/index.vue'
 import collectIcon from '@/assets/hzyb/collect-icon.png'
 import collectIcons from '@/assets/hzyb/collect-icon-s.png'
+
 export default {
     components:{
         [Popup.name]:Popup,
@@ -287,6 +291,15 @@ export default {
                 this.hasPPt=true
             }
         },
+
+        //跳转线上路演
+        goVideoPage(){
+          wx.miniProgram.navigateTo(
+            {
+              url:`/pages-roadShow/video/list?videoId=${this.info.road_video_id}&chart_permission_id=${-1}&fromPage=report`
+            }
+          )
+        },
         
         //获取报告详情
         async getDetail(){
@@ -430,6 +443,7 @@ export default {
 
         /*内容分割*/
         splitContentHandle(content) {
+            content=addTokenToIframe(content,this.reportId,0)
             const arr = content.split('</p>');
             this.totalContent = arr.map(_ => _+'</p>');
             this.realContent = this.totalContent.slice(0,this.pageSize)
@@ -812,13 +826,28 @@ export default {
             .item{
                 padding: 30px 34px;
                 border-bottom: 1px solid #E5E5E5;
-                .img{
+                .img-box{
                     width: 104px;
                     height: 104px;
-                    // background-color: #f5f5f5;
-                    flex-shrink: 0;
+                    box-sizing: border-box;
+                    border-radius: 8px;
+                    border: solid 2.5px #E5E5E5;
+                    display: flex;
+                    align-items: center;
+                    justify-content: center;
                     margin-right: 20px;
+                    .img{
+                        width: 60px;
+                        height: 60px;
+                    }
                 }
+                // .img{
+                //     width: 104px;
+                //     height: 104px;
+                //     // background-color: #f5f5f5;
+                //     flex-shrink: 0;
+                //     // margin-right: 20px;
+                // }
                 .con{
                     flex: 1;
                     position: relative;

+ 17 - 0
src/views/hzyb/utils/common.js

@@ -0,0 +1,17 @@
+// 公共工具方法
+
+/**
+ * 将报告详情字符串中的iframe加token,reportId参数
+ * @param str 报告详情
+ * @param reportId 
+ * @param chapterId
+ * @returns 
+ */
+export const addTokenToIframe=(str,reportId,chapterId=0)=>{
+    const token=localStorage.getItem('hzyb-token')||''
+    if(import.meta.env.MODE==='product'){
+        return str.replace(/src="https:\/\/chartlib.hzinsights.com\/chartshow\?/g,`src="https://chartlib.hzinsights.com/chartshow?token=${token}&reportId=${reportId}&chapterId=${chapterId}&source=ybxcx&`)
+    }else{
+        return str.replace(/src="https:\/\/charttest.hzinsights.com\/chartshow\?/g,`src="https://charttest.hzinsights.com/chartshow?token=${token}&reportId=${reportId}&chapterId=${chapterId}&source=ybxcx&`)
+    }
+}