Преглед изворни кода

Merge branch 'yb7.0_PC_chb'

hbchen пре 2 година
родитељ
комит
8b07c31554

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

+ 2 - 0
src/main.js

@@ -14,6 +14,8 @@ if(import.meta.env.MODE==='test'){
     const vConsole = new VConsole();
 }
 
+console.log('测试下新发布平台');
+
 const app = createApp(App)
 app.directive('drag', drag)
 

+ 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:false,
+          isRoot:true
+        }
+      }
+    ]
+  },
   // 用户模块
   {
     path:'/user',

+ 0 - 1
src/store/index.js

@@ -7,7 +7,6 @@ if(window.__wxjs_environment === 'miniprogram'){
   platform='xcx'
 }
 const breadcrumb=sessionStorage.getItem('breadcrumb')?JSON.parse(sessionStorage.getItem('breadcrumb')):[{name:'',path:location.pathname||''}]
-
 export default createStore({
   state: {
     platform:platform,//所处平台 web/xcx

+ 0 - 12
src/views/report/Detail.vue

@@ -478,18 +478,6 @@ const formatTitle=(e)=>{
             <div style="margin-bottom:10px">4、在任何情况下,本公司不对客户/接受人/接受机构因使用报告中内容所引致的一切损失负责任,客户/接受人/接受机构需自行承担全部风险。</div>
         </div>
     </el-dialog>
-    <!-- 生成海报 -->
-    <Teleport to="body">
-        <SharePoster  
-            :shareData="{
-                type:'report_detail',
-                code_page:'pages-report/reportDetail',
-                code_scene:code_scene,
-                data:posterParams
-            }"
-            v-if="info&&info.auth_ok"
-        ></SharePoster>
-    </Teleport>
 </template>
 
 <style lang="scss" scoped>

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

@@ -0,0 +1,608 @@
+<template>
+    <template v-if="sandBox.noAuthor ==1 && sandBox.isRequestFinished">
+        <div class="sandbox-noAuthor">
+            <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 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="sec-nav-box">
+                <span
+                    :class="['sec-item',item.chart_permission_id==sandBox.selectedSecondId?'active':'']"
+                    v-for="item in sandBox.secondClassifyList.slice(0,6)"
+                    :key="item.chart_permission_id"
+                    @click="selectSecondClassify(item)"
+                >{{item.chart_permission_name}}</span>
+                <el-popover
+                    :width="500"
+                    trigger="click"
+                >
+                    <template #reference>
+                        <img v-if="sandBox.secondClassifyList.length>6" style="width:16px;transform: rotate(90deg);cursor: pointer" src="@/assets/icon-more.png" alt="">
+                    </template>
+                    <template #default>
+                        <div class="flex top-nav-filter-box">
+                            <div 
+                                :class="['item',item.chart_permission_id == sandBox.selectedSecondId&&'active']" 
+                                v-for="item in sandBox.secondClassifyList.slice(6)" 
+                                :key="item.chart_permission_id"
+                                @click="selectSecondClassify(item)"
+                            >{{item.chart_permission_name}}</div>
+                        </div>
+                    </template>
+                </el-popover>
+            </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>
+            </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,onMounted,onActivated} 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=>{
+                sandBox.applyer.hasApply=true
+                const htmlStr = `<p>申请已提交</p><p>请等待销售人员与您联系</p>`;
+                ElMessageBox({
+                    title: "温馨提醒",
+                    message: htmlStr,
+                    center: true,
+                    dangerouslyUseHTMLString: true,
+                    confirmButtonText: "知道了",
+                    confirmButtonClass: "self-elmessage-confirm-btn",
+                });
+            })
+        }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
+        try {
+            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
+                    }
+                }
+            }
+        } catch (error) {
+            console.log(error);
+        }
+
+        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 = (item)=>{
+    console.log(item);
+    if(sandBox.selectedSecondId == item.chart_permission_id) return 
+    sandBox.sandBoxParams.chart_permission_id = sandBox.selectedSecondId = item.chart_permission_id
+    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()
+
+onMounted(() => {
+  //向小程序发送消息
+  let postData = {
+    path: "/pages-sandTable/sandTable",
+    params:{
+        firstClassifyId:sandBox.selectedFirstId,
+        chart_permission_id:sandBox.selectedSecondId
+    },
+    title: "沙盘推演",
+    shareImg:''
+  };
+  wx.miniProgram.postMessage({ data: postData });
+});
+
+onActivated(()=>{
+    //向小程序发送消息
+    let postData = {
+        path: "/pages-sandTable/sandTable",
+        params:{
+            firstClassifyId:sandBox.selectedFirstId,
+            chart_permission_id:sandBox.selectedSecondId
+        },
+        title: "沙盘推演",
+        shareImg:''
+    };
+    wx.miniProgram.postMessage({ data: postData });
+})
+
+</script>
+<style lang="scss" scoped>
+.top-nav-filter-box{
+    flex-wrap: wrap;
+    .item{
+        margin: 5px 10px;
+        width: 113px;
+        height: 40px;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        background-color: #f6f6f6;
+        border-radius: 4px;
+        font-size: 16px;
+        cursor: pointer;
+        :hover{
+            color: #fff;
+            background-color: #F3A52F;
+        }
+    }
+    .active{
+        color: #fff;
+        background-color: #F3A52F;
+    }
+}
+    .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 30px 12px 30px;
+            background: #FFFFFF;
+            box-shadow: 0px 4px 8px 1px rgba(0, 0, 0, 0.04);
+            position: fixed;
+            top: 60px;
+            width: 100%;
+            max-width: 1240px;
+            z-index: 10;
+            .firstClassify-box{
+                .firstClassfy-item{
+                    display: inline-block;
+                    width: 140px;
+                    line-height: 40px;
+                    text-align: center;
+                    border-radius: 20px;
+                    background-color: #F6F6F6;
+                    font-size: 16px;
+                    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;
+                    }
+                }
+            }
+            .sec-nav-box{
+                margin-top: 30px;
+                .sec-item{
+                    color: #666;
+                    margin-right: 30px;
+                    cursor: pointer;
+                    display: inline-block;
+                }
+                .active{
+                    color: #F3A52F;
+                }
+            }
+        }
+        .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;
+                    display:flex;
+                    justify-content:center;
+                    align-items:center;
+                    img{
+                        cursor: pointer;
+                        max-width:100%;
+                    }
+                    .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>