Browse Source

Merge branch 'debug' of http://8.136.199.33:3000/jwyu/hongze_yb_pc into debug

Karsa 2 years ago
parent
commit
8a357084b3

+ 8 - 0
src/api/report.js

@@ -204,4 +204,12 @@ export const apiReportHotCommentList=params=>{
  */
 export const apiDelMyComment=params=>{
     return post('/comment/del',params)
+}
+
+/**
+ * 日度点评分享图片
+ * @param title
+ */
+export const apiRddpShareImg=params=>{
+    return post('/report/detail/rddp_share_img',params)
 }

+ 32 - 0
src/api/sandBox.js

@@ -0,0 +1,32 @@
+/**
+ * 沙盘推演模块
+ */
+ import {get,post} from './http'
+
+ /**
+  * 有权限的二级分类以及下面的沙盘图数量
+  */
+ export const apiSandBoxPermission=()=>{
+     return get('/sandbox/permission_count')
+ }
+
+ /**
+  * 沙盘图列表
+  * @param  page_size 一页的数据量
+  * @param  current_index 页数
+  * @param  keyword 搜索关键词
+  * @param  chart_permission_id 二级分类Id
+  * @param  is_high_light 是否高亮  true | false
+  */
+  export const apiSandBoxList=(params)=>{
+    return get('/sandbox/list',params)
+}
+
+/**
+ * 沙盘图详情
+ * @param sandbox_id 沙盘ID
+ */
+ export const apiSandTableDetail = (params) => {
+    return get("/sandbox/detail", params);
+};
+ 

+ 1 - 1
src/api/user.js

@@ -16,7 +16,7 @@ export const apiUserInfo=()=>{
  * @param company_name 公司名
  * @param permission 选择的权限
  * @param real_name 姓名
- * @param source 来源:我的1、活动2、图库3、研报4
+ * @param source 来源:我的1、活动2、图库3、研报4、沙盘推演7
  * @param source_agent 来源平台:1:小程序、2:小程序(pc)、3:公众号、4:官网web(pc)
  * @param from_page 来源页面: '活动列表'、'活动详情'等
  */

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


+ 7 - 0
src/layout/component/Aside.vue

@@ -37,6 +37,13 @@ const menuList = reactive([
     children: null,
   },
   {
+  MenuId: 4,
+  name: "沙盘推演",
+  path: "/sandBox/list",
+  icon_path: new URL('../../assets/leftNav/sandBox-s.png', import.meta.url).href,
+  children: null,
+},
+{
     MenuId: 5,
     name: "视频社区",
     path: "/video/list",

+ 22 - 1
src/router/index.js

@@ -224,7 +224,28 @@ const routes=[
       }
     ]
   },
-
+  // 沙盘推演模块
+  {
+    path:'/sandBox',
+    name:"sandBox",
+    component: () => import("@/layout/Index.vue"),
+    redirect:'/sandBox/list',
+    meta:{
+      title:"沙盘推演"
+    },
+    children:[
+      {
+        path:"list",
+        name:"sandBoxList",
+        component:()=>import('@/views/sandBox/List.vue'),
+        meta: {
+          title: "沙盘推演",
+          keepAlive:true,
+          isRoot:true
+        }
+      }
+    ]
+  },
   // 用户模块
   {
     path:'/user',

+ 13 - 2
src/views/report/Detail.vue

@@ -6,7 +6,7 @@ import 'moment/dist/locale/zh-cn'
 import AudioBox from './components/AudioBox.vue'
 import SharePoster from '@/components/SharePoster.vue'
 import Comment from '@/components/Comment.vue'
-import {apiReportDetail,apiReportMoreRecmd,apiReportDetailBanner} from '@/api/report'
+import {apiReportDetail,apiReportMoreRecmd,apiReportDetailBanner,apiRddpShareImg} from '@/api/report'
 import {apiGetWechatQRCode} from '@/api/common'
 import { useRoute , onBeforeRouteUpdate,useRouter} from 'vue-router';
 import { useStore } from 'vuex';
@@ -67,6 +67,7 @@ const getReportDetail=async ()=>{
         //向小程序发送分享数据
         //处理分享标题
         let shareTitle=''
+        let shareImg=''
         const shareTime=moment(res.data.report_info.publish_time).format('MMDD')
         if(['晨报','周报'].includes(res.data.report_info.classify_name_first)){
             shareTitle=`【${res.data.report_info.classify_name_first}】${res.data.report_info.title}(${shareTime})`
@@ -83,13 +84,23 @@ const getReportDetail=async ()=>{
                 shareTitle=`【${res.data.report_info.classify_name_second}】${res.data.report_info.title}(${shareTime})`
             }
         }
+        // 日度点评
+        if(res.data.report_info.classify_name_first==='日度点评'){
+            shareTitle=res.data.report_info.abstract||'FICC日度点评'
+            const rddpImgRes=await apiRddpShareImg({
+                title:`【第${res.data.report_info.stage}期】${res.data.report_info.title}(${shareTime})`
+            })
+            if(rddpImgRes.code===200){
+                shareImg=rddpImgRes.data
+            }
+        }
         const postData={
             path:'/pages-report/reportDetail',
             params:{
                 reportId:reportId.value
             },
             title:shareTitle,
-            shareImg:''
+            shareImg:shareImg
         }
         wx.miniProgram.postMessage({ data: postData })
         

+ 574 - 0
src/views/sandBox/List.vue

@@ -0,0 +1,574 @@
+<template>
+    <template v-if="sandBox.noAuthor ==1 && sandBox.isRequestFinished">
+        <div class="sandbox-noAuthor">
+            <template v-if="!sandBox.applyer.hasApply">
+                <img :src="$store.state.globalImgUrls.activityNoAuth" />
+                <span style="margin-top: 34px;">您在暂无权限查看沙盘推演</span>
+                <span style="margin-top: 10px;">若想查看可以申请开通</span>
+                <div class="apply-button" @click="toApply">立即申请</div>
+            </template>
+            <template v-else>
+                <img :src="$store.state.globalImgUrls.activityNoAuth" />
+                <span style="margin-top: 34px;">您已提交过申请</span>
+                <span style="margin-top: 10px;">请等待销售人员与您联系</span>
+                <div class="apply-button" @click="$router.back()">返回</div>
+            </template>
+        </div>
+    </template>
+    <template v-if="sandBox.noAuthor ==2 && sandBox.isRequestFinished">
+        <view class="sandbox-noAuthor">
+            <img :src="$store.state.globalImgUrls.activityNoAuth" />
+            <span style="margin-top: 34px;">您在暂无权限查看沙盘推演</span>
+            <span style="margin: 10px 0 4px 0;">若想查看请联系对口销售</span>
+            <div>
+                <span>{{sandBox.salesData.name}}:</span>
+                <span class="sales-mobile" @click="callToSales">{{sandBox.salesData.phone}}</span>
+            </div>
+        </view>
+    </template>
+    <div class="sandBox-contain" v-if="sandBox.noAuthor ==0 && sandBox.isRequestFinished">
+        <div class="classify-box">
+            <div class="firstClassify-box">
+                <div :class="['firstClassfy-item',item.id==sandBox.selectedFirstId?'firstClassfy-actice':'']" 
+                v-for="item in sandBox.classifyList" :key="item.id" @click="selectFirstClassify(item)">
+                    <span>{{item.classify_name}}</span>
+                </div>
+            </div>
+            <div class="secondClassify-box">
+                <el-tabs v-model="sandBox.selectedSecondId" @tab-click="selectSecondClassify">
+                    <el-tab-pane 
+                        :label="item.chart_permission_name" 
+                        :name="item.chart_permission_id"
+                        v-for="item in sandBox.secondClassifyList" 
+                        :key="item.chart_permission_id"
+                    ></el-tab-pane>
+                </el-tabs>
+            </div>
+        </div>
+        <div class="sandBox-noData" v-if="!sandBox.list">
+            <img :src="$store.state.globalImgUrls.activityNoAuth" alt="暂无数据" />
+            <span>暂无数据</span>
+        </div>
+        <div class="sandBox-content">
+            <div class="sandBox-item" v-for="(item,index) in sandBox.list" :key="item.sandbox_id">
+                <span>{{item.name}}</span>
+                <div class="sandBox-image">
+                    <img :src="item.pic_url" :alt="item.name" @click="previewImage(index)"/>
+                    <div class="sandBox-source">来源:弘则研究</div>
+                </div>
+            </div>
+            <template v-if="sandBox.list">
+                <div class="loading-more" @click="loadingMore" v-show="sandBox.isRequestFinished && sandBox.list.length < sandBox.total">加载更多</div>
+                <div class="more-loading" v-show="!sandBox.isRequestFinished">加载中······</div>
+                <div class="more-loading no-more" v-show="sandBox.isRequestFinished && sandBox.list.length >= sandBox.total && sandBox.total!=0">没有更多了~</div>
+            </template>
+        </div>
+    </div>
+    
+    <!-- 图片预览 -->
+    <el-image-viewer
+        v-if="showPreViewImg"
+        :initial-index="preViewImgIndex"
+        @close="cancelPreview"
+        :url-list="previewImageList"
+    />
+</template>
+<script setup>
+import {h, reactive,computed,ref} from 'vue'
+import {useRouter,onBeforeRouteUpdate,useRoute} from "vue-router"
+import {apiSandBoxPermission,apiSandBoxList,apiSandTableDetail} from "../../api/sandBox"
+import {apiReportIndexPageAuthList} from "../../api/report"
+import {apiApplyPermission} from "../../api/user"
+import { ElMessageBox } from 'element-plus'
+const router = useRouter()
+const route = useRoute()
+
+// -----------------------------------------------------数据
+let sandBox = reactive({
+    list:[],
+    classifyList:[],
+    // 请求参数
+    sandBoxParams:{
+        page_size:5,
+        curr_page:1,
+        chart_permission_id:0
+    },
+    // 沙盘图ID 手机小程序单个分享
+    sandbox_id:"",
+    total:0,
+    // 二级分类列表
+    secondClassifyList:[],
+    selectedFirstId:0,
+    selectedSecondId:0,
+    // 所有有权限的二级分类以及下面的沙盘图数
+    classifyDataList:[],
+    // 没有权限  1:立即申请 2:联系销售
+    noAuthor:0,
+    // 销售信息
+    salesData:{
+        phone:'',
+        name:''
+    },
+    // 申请权限时的用户信息
+    applyer:{
+        name:'',
+        company:'',
+        // 是否已经申请
+        hasApply:false,
+        // 状态
+        status:''
+    },
+    // 请求是否完成
+    isRequestFinished:false
+})
+// 是否预览图片
+let showPreViewImg = ref(false)
+// 预览图片索引
+let preViewImgIndex = ref(0)
+
+// ------------------------------------------------------计算属性
+// 预览图片的路径
+const previewImageList = computed(()=>{
+    return sandBox.list.map(item=> item.pic_url)
+})
+
+// ------------------------------------------------------方法
+// 获取沙盘图数据
+const getSandBoxList=()=>{
+    apiSandBoxList(sandBox.sandBoxParams).then(({data,code})=>{
+        // 403 无权限
+        if(code == 403){
+            sandBox.applyer.name = data.customer_info.name
+            sandBox.applyer.company = data.customer_info.company_name
+            sandBox.applyer.hasApply = data.customer_info.has_apply
+            sandBox.applyer.status = data.customer_info.status
+            if(data.type == 'apply'){
+                // 申请
+                sandBox.noAuthor =1
+            }else{
+                // 联系销售
+                sandBox.noAuthor =2
+                sandBox.salesData.name=data.name
+                sandBox.salesData.phone=data.mobile
+            }
+            return 
+        }
+        if(sandBox.sandBoxParams.curr_page == 1){
+            sandBox.list = data.list
+            sandBox.total = data.paging.totals
+        }else{
+            sandBox.list = [...sandBox.list, ...data.list]
+        }
+        sandBox.noAuthor=0
+    }).finally(()=>{
+        sandBox.isRequestFinished=true
+    })
+}
+
+// 获取单个沙盘图
+const getSandTableDetail=()=>{
+    sandBox.isRequestFinished=false
+    apiSandTableDetail({sandbox_id:sandBox.sandbox_id}).then(({data,code})=>{
+        // 403 无权限
+        if(code == 403){
+            sandBox.applyer.name = data.customer_info.name
+            sandBox.applyer.company = data.customer_info.company_name
+            sandBox.applyer.hasApply = data.customer_info.has_apply
+            sandBox.applyer.status = data.customer_info.status
+            if(data.type == 'apply'){
+                // 申请
+                sandBox.noAuthor =1
+            }else{
+                // 联系销售
+                sandBox.noAuthor =2
+                sandBox.salesData.name=data.name
+                sandBox.salesData.phone=data.mobile
+            }
+            return 
+        }
+        sandBox.list = [data]
+        sandBox.noAuthor=0
+    }).finally(()=>{
+        sandBox.isRequestFinished=true
+    })
+}
+
+//预览图片
+const previewImage=(i)=>{
+    preViewImgIndex.value = i
+    showPreViewImg.value=true
+    // 不让外层的页面可以滚动
+    $('body').css("overflow","hidden")
+}
+
+// 取消预览图片
+const cancelPreview = ()=>{
+    // 恢复外层的页面滚动
+    $('body').css("overflow","visible")
+    showPreViewImg.value=false
+
+}
+
+//加载更多
+const loadingMore = ()=>{
+    sandBox.sandBoxParams.curr_page++
+    getSandBoxList()
+}
+
+//联系销售
+const callToSales=()=>{
+    if(!sandBox.applyer.hasApply){
+        toApply('auto')
+    }
+    window.location.href=`tel:${sandBox.salesData.phone}`
+}
+
+//申请权限
+const toApply = (type='')=>{
+    if(type=='auto'){
+        apiApplyPermission({
+            company_name:sandBox.applyer.company,
+            real_name:sandBox.applyer.name,
+            source:7,
+            from_page:'沙盘推演',
+        }).then(res=>{
+            console.log('自动申请成功');
+        })
+    }else{
+        if(sandBox.applyer.hasApply){
+            ElMessageBox({
+                title:'温馨提醒',
+                message:h('p','您已提交过申请,请耐心等待'),
+                center: true,
+                dangerouslyUseHTMLString: true,
+                confirmButtonText:'知道了',
+                confirmButtonClass:'self-elmessage-confirm-btn'
+            })
+            return 
+        }
+        if(sandBox.applyer.status==='流失'){
+            apiApplyPermission({
+                company_name:sandBox.applyer.company,
+                real_name:sandBox.applyer.name,
+                source:7,
+                from_page:'沙盘推演',
+            }).then(res=>{
+                router.replace('/apply/result')
+            })
+        }else{
+            router.push({
+                path:'/apply/permission',
+                query:{
+                    source:7,
+                    fromPage:'沙盘推演',
+                    token:localStorage.getItem('token')||''
+                }
+            })
+        }
+    }
+}
+
+// 获取分类列表 过滤无权限的分类
+const getClassifyList= ()=>{
+    apiReportIndexPageAuthList().then( async ({data:{permission_list}})=>{
+        // 过滤掉'更多报告' 和 没有权限的分类
+        sandBox.classifyList = permission_list.filter(item => item.sort!=100000)
+        sandBox.classifyList.forEach(item=>{
+            item.list=item.list.filter(it=>it.auth_ok)
+        })
+        sandBox.classifyList=sandBox.classifyList.filter(item=>item.list.length!=0)
+        let classifyData= await apiSandBoxPermission()
+         sandBox.classifyDataList = classifyData.data
+         if(sandBox.selectedFirstId == 0){
+            // 一级分类ID 和 二级分类ID 没有,不是通过分享进来的,或者路由参数中没有一级Id和二级Id
+            // 找出第一个有数据的二级分类
+            U:for (const item of sandBox.classifyList) {
+                for (const it of item.list) {
+                    for (const classify of sandBox.classifyDataList) {
+                        if(classify.chart_permission_id==it.chart_permission_id){
+                            if(classify.total>0){
+                                sandBox.selectedFirstId = item.id
+                                sandBox.secondClassifyList = item.list
+                                sandBox.selectedSecondId = it.chart_permission_id
+                                break U
+                            }
+                            break
+                        }
+                    }
+                }
+            }
+            sandBox.sandBoxParams.chart_permission_id = sandBox.selectedSecondId
+         }else{
+            for (const item of sandBox.classifyList) {
+                if(item.id == sandBox.selectedFirstId){
+                    // 根据selectedFirstId找出需要展示的二级分类列表
+                    sandBox.secondClassifyList = item.list
+                    break
+                }
+            }
+         }
+        if(sandBox.sandbox_id){
+            getSandTableDetail()
+        }else{
+            getSandBoxList()
+        }
+    })
+}
+// 切换一级分类
+const selectFirstClassify = (item)=>{
+    if(sandBox.selectedFirstId === item.id) return 
+    sandBox.selectedFirstId = item.id
+    sandBox.secondClassifyList = item.list
+    sandBox.selectedSecondId = item.list[0].chart_permission_id
+    U:for (const it of item.list) {
+        for (const classify of sandBox.classifyDataList) {
+            if(classify.chart_permission_id==it.chart_permission_id){
+                if(classify.total>0){
+                    sandBox.selectedSecondId = it.chart_permission_id
+                    break U
+                }
+                break
+            }
+        }
+    }
+    sandBox.sandBoxParams.chart_permission_id = sandBox.selectedSecondId
+    sandBox.sandBoxParams.curr_page=1
+    sandBox.list=[]
+    getSandBoxList()
+}
+// 切换二级分类
+const selectSecondClassify = (e)=>{
+    let {props:{name}} = e
+    if(sandBox.selectedSecondId == name) return 
+    sandBox.sandBoxParams.chart_permission_id = sandBox.selectedSecondId = name
+    sandBox.sandBoxParams.curr_page=1
+    sandBox.list=[]
+    getSandBoxList()
+}
+
+// ---------------------------------------------------------created
+// 路由参数  分享
+// 需要是数字类型
+sandBox.sandBoxParams.chart_permission_id = sandBox.selectedSecondId = parseInt(route.query.chart_permission_id)  || 0 //二级分类ID 分享
+sandBox.selectedFirstId = route.query.firstClassifyId || 0 //一级分类ID 分享
+sandBox.sandbox_id = route.query.sandbox_id // 沙盘图ID 
+getClassifyList()
+
+
+</script>
+<style lang="scss" scoped>
+    .sandbox-noAuthor{
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        margin-top: 50px;
+        img{
+            height: 360px;
+        }
+        span{
+            font-family: 'PingFang SC';
+            font-style: normal;
+            font-weight: 400;
+            font-size: 28rpx;
+            color: #999999;
+        }
+        .sales-mobile{
+            color: #E3B377;
+            cursor: pointer;
+        }
+        .apply-button{
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            background: #E6B77D;
+            width: 218px;
+            border: none;
+            height: 40px;
+            border-radius: 41px;
+            margin-top: 30px;
+            font-family: 'PingFang SC';
+            font-style: normal;
+            font-weight: 500;
+            font-size: 16px;
+            color: #FFFFFF;
+            cursor: pointer;
+        }
+    }
+    .sandBox-contain{
+        margin-top: 130px;
+        .classify-box{
+            padding: 30px 0 12px 0;
+            box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.04);
+            position: fixed;
+            z-index: 50;
+            background: #FFFFFF;
+            top: 60px;
+            width: 100%;
+            .firstClassify-box{
+                display: flex;
+                align-items: center;
+                .firstClassfy-item{
+                    width: 140px;
+                    height: 40px;
+                    box-sizing: border-box;
+                    background: #F6F6F6;
+                    border-radius: 20px;
+                    display: flex;
+                    align-items: center;
+                    justify-content: center;
+                    margin-right: 30px;
+                    cursor: pointer;
+                    span{
+                        font-family: 'PingFang SC';
+                        font-style: normal;
+                        font-weight: 400;
+                        font-size: 16px;
+                        color: #333333;
+                    }
+                }
+                .firstClassfy-actice{
+                    background: #FFFBF5;
+                    border: 1px solid #F3A52F;
+                    box-shadow: 0px 6px 7px #FFF7EB;
+                    border-radius: 20px;
+                    span{
+                        color: #F3A52F;
+                    }
+                }
+                // 小屏适配 
+                @media screen and (max-width: 1350px){
+                    .firstClassfy-item{
+                        width: 90px;
+                        height: 30px;
+                        border-radius: 20px;
+                        margin-right: 15px;
+                        span{
+                            font-size: 14px;
+                        }
+                    }
+                }
+            }
+            .secondClassify-box{
+                margin-top: 30px;
+                :deep(.el-tabs__header){
+                margin-bottom: 0;
+                }
+                :deep(.el-tabs__active-bar){
+                display: none;
+                }
+                :deep(.el-tabs__nav-wrap::after){
+                    display: none;
+                }
+                :deep(.el-tabs__item.is-active){
+                    color: #F3A52F;
+                }
+                :deep(.el-tabs__item){
+                    font-size: 16px;
+                    &:hover{
+                        color: #F3A52F;
+                    }
+                }
+                :deep(.el-tabs__nav-next){
+                    width: 20px;
+                    height: 20px;
+                    background-image: url('@/assets/icon-more.png');
+                    background-size: cover;
+                    top: 10px;
+                    .el-icon{
+                        display: none;
+                    }
+                }
+                :deep(.el-tabs__nav-prev){
+                    width: 20px;
+                    height: 20px;
+                    background-image: url('@/assets/icon-more.png');
+                    background-size: cover;
+                    top: 10px;
+                    transform: rotate(180deg);
+                    .el-icon{
+                        display: none;
+                    }
+                }
+                :deep(.el-tabs__nav-wrap.is-scrollable){
+                    padding: 0 25px;
+                }
+            }
+        }
+        .sandBox-noData{
+            display: flex;
+            flex-direction: column;
+            align-items: center;
+            justify-content: center;
+            margin-top: 50px;
+            img{
+                height: 360px;
+            }
+            span{
+                margin-top: 30px;
+                font-family: 'PingFang SC';
+                font-style: normal;
+                font-weight: 400;
+                font-size: 16px;
+                color: #333333;
+            }
+        }
+        .sandBox-content{
+            .sandBox-item{
+                padding: 30px 0;
+                position: relative;
+                span{
+                    font-family: 'PingFang SC';
+                    font-style: normal;
+                    font-weight: 600;
+                    font-size: 16px;
+                    color: #333333;
+                }
+                .sandBox-image{
+                    margin-top: 20px;
+                    width: 100%;
+                    max-height: 558px;
+                    border: 2px solid #ECECEC;
+                    overflow: auto;
+                    padding-bottom: 24px;
+                    img{
+                        cursor: pointer;
+                    }
+                    .sandBox-source{
+                        font-size: 20px;
+                        font-family: PingFang SC-Regular, PingFang SC;
+                        font-weight: 400;
+                        color: #666666;
+                        -webkit-background-clip: text;
+                        background-clip: text;
+                        position: absolute;
+                        bottom: 54px;
+                        right: 30px;
+                    }
+                }
+            }
+            .loading-more{
+                margin: 20px auto;  
+                width: 112px;
+                height: 30px;
+                background: #FFFFFF;
+                border-radius: 20px;
+                border: 1px solid #F3A52F;
+                color: #F3A52F;
+                font-size: 14px;
+                text-align: center;
+                display: flex;
+                justify-content: center;
+                align-items: center;
+                cursor: pointer;
+            }
+            .more-loading{
+                margin: 20px auto;  
+                width: 112px;
+                height: 30px;
+                font-size: 16px;
+                font-family: 'PingFang SC';
+                color: #666666;
+            }
+        }
+    }
+</style>

+ 1 - 1
src/views/video/List.vue

@@ -296,7 +296,7 @@ onActivated(()=>{
             video{
                 width: 100%;
                 height: 200px;
-                object-fit: cover;
+                object-fit: contain;
                 margin: 19px 0;
             }
             .poster-img{