hbchen il y a 2 ans
Parent
commit
29545cd269

+ 1 - 0
.gitignore

@@ -15,6 +15,7 @@ testDir
 *.local
 *.local
 package-lock.json
 package-lock.json
 hongze_yb_pc
 hongze_yb_pc
+hongze_yb_pc.zip
 
 
 # Editor directories and files
 # Editor directories and files
 .vscode/*
 .vscode/*

BIN
hongze_yb_pc.zip


+ 7 - 0
src/api/common.js

@@ -133,4 +133,11 @@ export const apiReadOneNotice=params=>{
  */
  */
  export const apiDelOneNotice=params=>{
  export const apiDelOneNotice=params=>{
     return post('/message/delete',params)
     return post('/message/delete',params)
+}
+
+/**
+ * 公告FICC品种权限数据
+ */
+export const apiFICCPermissionList=()=>{
+    return get('/company/permission/tree',{})
 }
 }

+ 26 - 0
src/api/priceDriven.js

@@ -0,0 +1,26 @@
+/* 价格驱动 */
+
+import {get,post} from './http'
+
+/**
+ * 菜单
+ */
+export const tabList = parmas=>{
+  return get('/price_driven/tab',parmas)
+}
+
+/**
+ * 价格驱动详情
+ * @param {chart_permission_id} params 
+ * @returns 
+ */
+export const priceDrivenDetail = params => {
+  return get('/price_driven/detail',params)
+}
+
+/**
+ * 埋点 price_driven_id source_agent 1-小程序 2-小程序PC 3-公众号 4-Web官网
+ */
+export const priceDrivenLog = params => {
+  return post('/price_driven/visit_log',params)
+}

+ 8 - 0
src/api/report.js

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

+ 16 - 0
src/api/video.js

@@ -0,0 +1,16 @@
+/**
+ * 视频社区模块
+ */
+ import {get,post} from './http'
+
+/**
+ * 视频列表
+ * @param page_index
+ * @param page_size
+ * @param keywords
+ * @param video_id
+ * @param chart_permission_id
+ */
+ export const apiVideoList=params=>{
+    return get('/community/video/list',params)
+}

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


BIN
src/assets/pricedriven/new_ico.png


BIN
src/assets/pricedriven/nodata.png


BIN
src/assets/video-play-btn.png


+ 1 - 0
src/components/Audio.vue

@@ -65,6 +65,7 @@ const handleDragTime=(e)=>{
 
 
 // 关闭弹窗
 // 关闭弹窗
 const closeAudioPop=()=>{
 const closeAudioPop=()=>{
+    store.commit('closeAudio')
     store.commit('closeAudioPop')
     store.commit('closeAudioPop')
 }
 }
 
 

+ 28 - 7
src/components/SharePoster.vue

@@ -32,12 +32,33 @@ const handleCreatePoster=async ()=>{
 }
 }
 
 
 const onLongPressImg=()=>{
 const onLongPressImg=()=>{
-    const a=document.createElement('a')
-    a.setAttribute("download",'名字')
-    a.style.display = "none"
-    a.href=posterImg.value+'?response-content-type=application/octet-stream'
-    document.body.appendChild(a);
-    a.click()
+    // const a=document.createElement('a')
+    // a.setAttribute("download",'名字')
+    // a.style.display = "none"
+    // a.href=posterImg.value+'?response-content-type=application/octet-stream'
+    // document.body.appendChild(a);
+    // a.click()
+
+    let img=new Image()
+    img.setAttribute('crossOrigin', 'anonymous');
+    img.src=posterImg.value
+    img.onload=()=>{
+        let canvas = document.createElement("canvas");
+        canvas.width = img.width;
+        canvas.height = img.height;
+        let context = canvas.getContext('2d');
+        context.drawImage(img, 0, 0, img.width, img.height);
+        let dataURL = canvas.toDataURL("image/png", 1);
+        const a=document.createElement('a')
+        a.setAttribute("download",'海报')
+        a.style.display = "none"
+        a.href=dataURL
+        document.body.appendChild(a);
+        a.click()
+    }
+    img.onerror=(e)=>{
+        console.log('图片加载失败',e);
+    }
 }
 }
 
 
 onLongPress(imgDom, onLongPressImg)
 onLongPress(imgDom, onLongPressImg)
@@ -60,7 +81,7 @@ onLongPress(imgDom, onLongPressImg)
             <img class="load-img" src="@/assets/loading.png"/>
             <img class="load-img" src="@/assets/loading.png"/>
             <div>海报生成中...</div>
             <div>海报生成中...</div>
         </div>
         </div>
-        <img v-if="showPoster" ref="imgDom" class="poster-img" :src="posterImg" @longpress="" />
+        <img v-if="showPoster" ref="imgDom" class="poster-img" :src="posterImg" />
     </div>
     </div>
 </template>
 </template>
 
 

+ 15 - 8
src/layout/component/Aside.vue

@@ -22,13 +22,13 @@ const menuList = reactive([
     icon_path: new URL('../../assets/leftNav/report-s.png', import.meta.url).href,
     icon_path: new URL('../../assets/leftNav/report-s.png', import.meta.url).href,
     children: null,
     children: null,
   },
   },
-  // {
-  //   MenuId: 1,
-  //   name: "ETA图库",
-  //   path: "/chart/list",
-  //   icon_path: new URL('../../assets/leftNav/chart-s.png', import.meta.url).href,
-  //   children: null,
-  // },
+  {
+    MenuId: 2,
+    name: "价格驱动",
+    path: "/pricedriven",
+    icon_path: new URL('../../assets/leftNav/chart-s.png', import.meta.url).href,
+    children: null,
+  },
   {
   {
     MenuId: 3,
     MenuId: 3,
     name: "活动",
     name: "活动",
@@ -42,7 +42,14 @@ const menuList = reactive([
   path: "/sandBox/list",
   path: "/sandBox/list",
   icon_path: new URL('../../assets/leftNav/sandBox-s.png', import.meta.url).href,
   icon_path: new URL('../../assets/leftNav/sandBox-s.png', import.meta.url).href,
   children: null,
   children: null,
-}
+},
+{
+    MenuId: 5,
+    name: "视频社区",
+    path: "/video/list",
+    icon_path: new URL('../../assets/leftNav/video-s.png', import.meta.url).href,
+    children: null,
+  }
 ]);
 ]);
 </script>
 </script>
 
 

+ 43 - 0
src/router/index.js

@@ -269,6 +269,49 @@ const routes=[
     ]
     ]
   },
   },
 
 
+  //价格驱动
+  {
+    path: '/pricedriven',
+    name: "priceDriven",
+    component: () => import("@/layout/Index.vue"),
+    meta: {
+      title:"价格驱动"
+    },
+    children: [
+      {
+        path: "/pricedriven",
+        name: "priceDrivenDeteail",
+        component: () => import("@/views/priceDriven/detail.vue"),
+        meta: {
+          title: "价格驱动",
+          keepAlive:false,
+          isRoot:true
+        },
+      },
+    ]  
+  },
+  //视频社区模块
+  {
+    path:'/video',
+    name:"Video",
+    component: () => import("@/layout/Index.vue"),
+    meta:{
+      title:"视频社区"
+    },
+    children:[
+      {
+        path:"list",
+        name:"VideoList",
+        component:()=>import('@/views/video/List.vue'),
+        meta: {
+          title: "视频社区",
+          keepAlive:true,
+          isRoot:true
+        }
+      }
+    ]
+  },
+
   {
   {
     path: '/:pathMatch(.*)',
     path: '/:pathMatch(.*)',
     name: 'error',
     name: 'error',

+ 5 - 0
src/style/global.scss

@@ -1,4 +1,8 @@
 // 全局样式
 // 全局样式
+// @font-face {
+//   font-family: 'PingFang';
+//   src: url('https://hzstatic.hzinsights.com/static/font/PingFangRegular.ttf');
+// }
 html,
 html,
 body,
 body,
 #app {
 #app {
@@ -6,6 +10,7 @@ body,
   height: 100%;
   height: 100%;
   font-size: 16px;
   font-size: 16px;
   color: #333;
   color: #333;
+  // font-family: 'PingFang';
   // min-width: 1024px;
   // min-width: 1024px;
 }
 }
 
 

+ 14 - 1
src/views/activity/Detail.vue

@@ -79,9 +79,22 @@ getDetail();
 // 处理分享数据
 // 处理分享数据
 const handleShareMsg=()=>{
 const handleShareMsg=()=>{
     //向小程序发送消息
     //向小程序发送消息
+
+    // let title=''
+    //     if(this.info.firstActivityTypeId==1){
+    //         title=this.info.reportName.split('】')[1]||this.info.activityName
+    //         if(this.info.is_new_report==1){
+    //             title=this.info.reportName
+    //         }
+    //     }else{
+    //         title=this.info.activityName
+    //     }
     let title=''
     let title=''
     if(info.value.firstActivityTypeId==1){
     if(info.value.firstActivityTypeId==1){
         title=info.value.reportName.split('】')[1]||info.value.activityName
         title=info.value.reportName.split('】')[1]||info.value.activityName
+        if(info.value.is_new_report==1){
+            title=info.value.reportName
+        }
     }else{
     }else{
         title=info.value.activityName
         title=info.value.activityName
     }
     }
@@ -327,7 +340,7 @@ const posterParams=computed(()=>{
             <div class="active-time"> 活动时间:{{ formatActivityTime(info.startTime, info.endTime) }}</div>
             <div class="active-time"> 活动时间:{{ formatActivityTime(info.startTime, info.endTime) }}</div>
         </div>
         </div>
         <div class="flex report-name">
         <div class="flex report-name">
-            <span>{{ info.reportName ? info.reportName.split("】")[1] : info.activityName }}</span>
+            <span>{{ info.is_new_report==1?info.reportName:info.reportName?info.reportName.split('】')[1]:info.activityName }}</span>
             <div class="global-main-btn" v-if="info.reportLink" @click="goDetail">查看相关报告</div>
             <div class="global-main-btn" v-if="info.reportLink" @click="goDetail">查看相关报告</div>
         </div>
         </div>
         <!-- 音频模块 -->
         <!-- 音频模块 -->

+ 612 - 0
src/views/priceDriven/detail.vue

@@ -0,0 +1,612 @@
+<script setup>
+import { ref, onMounted, computed, nextTick, onUnmounted } from "vue";
+import { ElMessageBox } from "element-plus";
+import {
+  ArrowDown,
+  ArrowUp,
+  CaretBottom,
+  CaretTop,
+} from "@element-plus/icons-vue";
+import { useRoute, useRouter } from "vue-router";
+import { useStore } from 'vuex';
+import moment from "moment";
+import * as priceApi from "@/api/priceDriven.js";
+import { apiGetWechatQRCode } from "@/api/common";
+import { apiApplyPermission } from "@/api/user";
+import SharePoster from '@/components/SharePoster.vue'
+
+const store=useStore()
+const router = useRouter();
+const route = useRoute();
+localStorage.setItem("hzyb-token", route.query.token);
+
+const noAuthInfo = ref(null); //无权限信息
+/* 分类 */
+const varietiesList = ref([]);
+const classifyList = ref([]);
+const select_classify_first = ref(""); //选中的品种
+const select_classify_sub = ref(""); //选中的分类
+const select_classify_subtitle = ref(""); //选中分类名称
+const isSlideClassify = ref(false);
+/* 获取分类 */
+const getClassify = async () => {
+  const { code, data } = await priceApi.tabList();
+
+  if (code === 200) {
+    const { permission_list } = data;
+    permission_list.forEach(_ => {
+      _.isShow = _.list ? _.list.some(sub_item => sub_item.pirce_driven_state) : false
+    })
+    varietiesList.value = permission_list.filter(_ => _.isShow);
+
+    // 分享进入的默认品种
+    if (route.query.default_classify_first) {
+      let index = varietiesList.value.findIndex(
+        (_) => _.id === route.query.default_classify_first
+      );
+      index === -1 ? errorLinkHandle() : changeClassify(varietiesList.value[index],'share');
+    } else {
+      changeClassify(varietiesList.value[0]);
+    }
+  } else if (code === 403) {
+    noAuthInfo.value = data;
+  }
+};
+getClassify();
+/* 选择一级分类 */
+const changeClassify = (item,type='') => {
+  const { id, list } = item;
+  select_classify_first.value = id;
+  classifyList.value = list.filter(_ => _.pirce_driven_state);
+  isSlideClassify.value = false;
+
+  //分享进入的默认品种
+  if (type === 'share') {
+    let index = classifyList.value.findIndex(
+      (_) => _.chart_permission_id === route.query.default_classify_sub
+    );
+    index === -1 ? errorLinkHandle() : changeSubClassify(classifyList.value[index]);
+  } else {
+    changeSubClassify(classifyList.value[0]);
+  }
+};
+/* 选择二级分类 */
+const changeSubClassify = ({ chart_permission_id, chart_permission_name }) => {
+  select_classify_sub.value = chart_permission_id;
+  select_classify_subtitle.value = chart_permission_name;
+  document.body.scrollTop = document.documentElement.scrollTop = 0;
+  getDetail();
+};
+/* 过期link处理 */
+const errorLinkHandle = () => {
+  Toast('该价格驱动不存在')
+
+  setTimeout(() => {
+    wx.miniProgram.switchTab({ 
+      url:"/pages/report/report"
+    });
+  },1000)
+}
+
+//详情信息
+const showData = ref(false);
+const headerWidth = ref("");
+const info = ref({});
+/* 获取详情 */
+const getDetail = async () => {
+  showData.value = false;
+  const { code, data } = await priceApi.priceDrivenDetail({
+    chart_permission_id: select_classify_sub.value,
+  });
+
+  if (code !== 200) return;
+  showData.value = true;
+  info.value = data;
+  
+  nextTick(() => {
+    resetHeaderWidthHandle();
+  });
+
+  //向小程序发送分享数据
+  wx.miniProgram.postMessage({
+    data: {
+      title: `${select_classify_subtitle}价格驱动`,
+      path:'/pages/pricedriven/pricedriven',
+      params:{
+        default_classify_first: select_classify_first.value,
+        default_classify_sub: select_classify_sub.value,
+      }
+    },
+  });
+  info.value.price_driven_id && visitPriceDrivenLog();
+};
+const visitPriceDrivenLog = async() => {
+  await priceApi.priceDrivenLog({
+    price_driven_id: info.value.price_driven_id,
+    source_agent: store.state.platform === 'web' ? 4 : 2
+  })
+}
+
+//点击申请
+const handleGoApply = async () => {
+  if (noAuthInfo.value.customer_info.has_apply) {
+    const htmlStr = `<p>您已提交过申请,请耐心等待</p>`;
+    ElMessageBox({
+      title: "温馨提醒",
+      message: htmlStr,
+      center: true,
+      dangerouslyUseHTMLString: true,
+      confirmButtonText: "知道了",
+      confirmButtonClass: "self-elmessage-confirm-btn",
+    });
+  } else {
+    if (
+      !noAuthInfo.value.customer_info.status ||
+      noAuthInfo.value.customer_info.status !== "流失"
+    ) {
+      router.push({
+        path: "/apply/permission",
+        query: {
+          source: 6,
+          fromPage: "价格驱动",
+        },
+      });
+    } else {
+      //主动调一次申请权限接口
+      const res = await apiApplyPermission({
+        company_name: noAuthInfo.value.customer_info.company_name,
+        real_name: noAuthInfo.value.customer_info.name,
+        source: 6,
+        from_page: "价格驱动",
+      });
+      if (res.code !== 200) return;
+      const htmlStr = `<p>申请已提交</p><p>请等待销售人员与您联系</p>`;
+      ElMessageBox({
+        title: "温馨提醒",
+        message: htmlStr,
+        center: true,
+        dangerouslyUseHTMLString: true,
+        confirmButtonText: "知道了",
+        confirmButtonClass: "self-elmessage-confirm-btn",
+      });
+    }
+  }
+};
+
+
+/* 分享海报参数 */
+const code_scene = computed(() =>
+  JSON.stringify({
+    default_classify_first: select_classify_first.value,
+    default_classify_sub: select_classify_sub.value,
+  })
+);
+const posterParams = computed(() => ({
+  list_title: `${select_classify_subtitle.value}价格驱动`,
+  core_driven_type: info.value.core_driven_type ? "空" : "多",
+  main_variable: info.value.main_variable,
+  update_time: moment(info.value.modify_time).format("YYYY-MM-DD dd"),
+  core_driven_content: info.value.core_driven_content,
+}));
+console.log(moment(info.value.modify_time).format("YYYY-MM-DD ddd"));
+
+// 小程序码
+let qrCode = ref("");
+const getQrCodeHandle = async () => {
+  const res = await apiGetWechatQRCode({
+    CodeScene: JSON.stringify({
+      default_classify_first: select_classify_first.value,
+      default_classify_sub: select_classify_sub.value,
+    }),
+    CodePage:'pages/pricedriven/pricedriven'
+    // CodePage: "pages-report/reportDetail",
+  });
+  if (res.code === 200) {
+    qrCode.value = res.data;
+  }
+};
+getQrCodeHandle();
+
+
+/* 重绘固定头宽度 */
+const resetHeaderWidthHandle = () => {
+  headerWidth.value = document.getElementsByClassName("content-box")[0].offsetWidth;
+}
+
+let preViewImgs = ref([]);
+let preViewImgIndex = ref(0);
+let showPreViewImg = ref(false);
+onMounted(() => {
+  $(document).on("click", ".rich-section img", function (event) {
+    let imgArray = [];
+    let curImageSrc = $(this).attr("src");
+    let oParent = $(this).parent();
+    if (curImageSrc && !oParent.attr("href")) {
+      if (preViewImgs.value.length === 0) {
+        $(".rich-section img").each(function (index, el) {
+          let itemSrc = $(this).attr("src");
+          imgArray.push(itemSrc);
+        });
+        preViewImgs.value = imgArray;
+      }
+      preViewImgIndex.value = preViewImgs.value.indexOf(curImageSrc) || 0;
+      showPreViewImg.value = true;
+    }
+  });
+
+  window.addEventListener('resize',resetHeaderWidthHandle)
+});
+
+onUnmounted(() => {
+  window.removeEventListener('resize',resetHeaderWidthHandle)
+})
+</script>
+
+<template>
+  <div class="pricedriven-page hasrightaside-box">
+    <div class="content-box">
+      <div
+        class="classify-cont"
+        v-if="varietiesList.length"
+        :style="`width:${headerWidth}px`"
+      >
+        <ul class="classsify-frist">
+          <li
+            :class="[
+              'classify-frist-item',
+              { act: select_classify_first === item.id },
+            ]"
+            v-for="(item, index) in varietiesList"
+            :key="item.classify_name"
+            @click="changeClassify(item, index)"
+          >
+            {{ item.classify_name }}
+          </li>
+        </ul>
+        <ul
+          class="classsify-sub"
+          :style="isSlideClassify ? 'height: auto' : 'height: 25px'"
+        >
+          <li
+            :class="[
+              'classify-sub-item',
+              { act: select_classify_sub === item.chart_permission_id },
+            ]"
+            v-for="item in classifyList.slice(0,6)"
+            :key="item.chart_permission_id"
+            @click="changeSubClassify(item)"
+          >
+            {{ item.chart_permission_name }}
+          </li>
+
+          <el-popover
+            :width="500"
+            trigger="click"
+          >
+            <template #reference>
+              <img v-if="classifyList.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 == select_classify_sub&&'active']" 
+                    v-for="item in classifyList.slice(6)" 
+                    :key="item.chart_permission_id"
+                    @click="changeSubClassify(item)"
+                >{{item.chart_permission_name}}</div>
+              </div>
+            </template>
+          </el-popover>
+          <!-- <div
+            class="slide"
+            v-if="!isSlideClassify"
+            @click="isSlideClassify = !isSlideClassify"
+          >
+            展开 <el-icon><ArrowDown /></el-icon>
+          </div>
+          <div class="slide" v-else @click="isSlideClassify = !isSlideClassify">
+            收起 <el-icon><ArrowUp /></el-icon>
+          </div> -->
+        </ul>
+      </div>
+
+      <template v-if="showData">
+        <!-- 内容 -->
+        <div class="richtext-container" v-if="info.core_content">
+          <div class="section">
+            <h3>更新时间:</h3>
+            <p class="time">
+              {{ moment(info.modify_time).format('YYYY年MM月DD日 ddd') }}
+              <img
+                src="@/assets/pricedriven/new_ico.png"
+                alt=""
+                class="new_tag"
+                v-if="
+                  moment(info.modify_time).format('YYYY-MM-DD') ===
+                  moment().format('YYYY-MM-DD')
+                "
+              />
+            </p>
+          </div>
+          <div class="section">
+            <h3>关键变量:</h3>
+            <p>{{ info.main_variable }}</p>
+          </div>
+          <div class="section">
+            <h3 class="flex">
+              核心驱动:
+              <div :class="['tag flex', info.core_driven_type ? 'down' : 'up']">
+                <span style="margin-right: 5px">
+                  {{ info.core_driven_type ? "空" : "多" }}</span
+                >
+                <el-icon v-if="info.core_driven_type"><CaretBottom /></el-icon>
+                <el-icon v-else><CaretTop /></el-icon>
+              </div>
+            </h3>
+            <p
+              :class="info.core_driven_type ? 'down' : 'up'"
+              style="padding: 20px 17px"
+            >
+              {{ info.core_driven_content }}
+            </p>
+          </div>
+          <div class="rich-section">
+            <h3>核心内容:</h3>
+            <div v-html="info.core_content"></div>
+          </div>
+
+          <!-- 生成海报 -->
+          <Teleport to="body">
+            <SharePoster
+              :shareData="{
+                type: 'pricedriven',
+                code_page: 'pages/pricedriven/pricedriven',
+                code_scene: code_scene,
+                data: posterParams,
+              }"
+              v-if="info && info.core_content"
+            ></SharePoster>
+          </Teleport>
+        </div>
+
+        <!-- 无数据 -->
+        <div class="no-auth-wrap nodata" v-else>
+          <div class="apply-box">
+            <img
+              src="@/assets/pricedriven/nodata.png"
+              alt=""
+              class="nodata-img"
+            />
+            <div>暂无数据</div>
+          </div>
+        </div>
+      </template>
+
+      <!-- 无权限 -->
+      <div class="no-auth-wrap" v-if="noAuthInfo">
+        <div class="apply-box" v-if="noAuthInfo.type == 'apply'">
+          <img
+            src="@/assets/pricedriven/nodata.png"
+            alt=""
+            class="nodata-img"
+          />
+          <div>您暂无权限查看价格驱动,若想查看请申请开通</div>
+          <div class="global-main-btn btn" @click="handleGoApply">立即申请</div>
+        </div>
+        <div class="apply-box" v-else>
+          <img
+            src="@/assets/pricedriven/nodata.png"
+            alt=""
+            class="nodata-img"
+          />
+          <div style="margin-bottom: 10px;">您暂无权限查看价格驱动</div>
+          <div>若想查看请联系对口销售</div>
+          <div>{{ noAuthInfo.name }}:<span style="color: #e3b377">{{ noAuthInfo.mobile }}</span>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="right-aside-box" v-if="!noAuthInfo">
+      <div class="fix-top">
+        <div class="share-box">
+          <div class="label">分享</div>
+          <el-popover
+            :width="200"
+            popper-style="box-shadow: rgb(14 18 22 / 35%) 0px 10px 38px -10px, rgb(14 18 22 / 20%) 0px 10px 20px -15px; padding: 20px;"
+          >
+            <template #reference><div class="icon"></div></template>
+
+            <template #default>
+              <img
+                :src="qrCode"
+                class="share-xcx-img"
+                alt=""
+                style="width: 150px; display: block; margin: 0 auto"
+              />
+            </template>
+          </el-popover>
+        </div>
+      </div>
+    </div>
+
+    <!-- 图片预览 -->
+    <el-image-viewer
+      v-if="showPreViewImg"
+      :initial-index="preViewImgIndex"
+      @close="showPreViewImg = false"
+      :url-list="preViewImgs"
+    />
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.pricedriven-page {
+  display: flex;
+  .classify-cont {
+    box-shadow: 0px 2px 0px rgba(0, 0, 0, 0.04);
+    padding: 30px 20px 12px;
+    position: fixed;
+    top: 60px;
+    z-index: 9;
+    background: #fff;
+    .classsify-frist {
+      display: flex;
+      align-items: center;
+      .classify-frist-item {
+        width: 140px;
+        height: 40px;
+        text-align: center;
+        line-height: 40px;
+        background: #f5f5f5;
+        border-radius: 40px;
+        margin-right: 30px;
+        border: 1px solid transparent;
+        cursor: pointer;
+        &:last-child {
+          margin-right: 0;
+        }
+        &.act,
+        &:hover {
+          background: #fdf8f2;
+          color: #e3b377;
+          border-color: #f3a52f;
+        }
+      }
+      @media screen and (max-width: 1350px) {
+        .classify-frist-item {
+          width: 90px;
+          height: 30px;
+          line-height: 30px;
+          margin-right: 15px;
+          font-size: 14px;
+        }
+      }
+    }
+    .classsify-sub {
+      margin-top: 30px;
+      display: flex;
+      flex-wrap: wrap;
+      align-items: center;
+      position: relative;
+      height: 25px;
+      overflow-y: hidden;
+      .classify-sub-item {
+        flex-shrink: 0;
+        position: relative;
+        margin: 5px 30px 4px 0;
+        cursor: pointer;
+        &.act {
+          color: #e3b377;
+        }
+      }
+      .slide {
+        position: absolute;
+        right: 0;
+        top: 3px;
+        cursor: pointer;
+      }
+    }
+  }
+  .richtext-container {
+    margin-top: 130px;
+    .section {
+      padding: 20px;
+      border-bottom: 2px solid #f1f1f1;
+      > h3 {
+        font-size: 16px;
+      }
+      > p {
+        color: #666;
+      }
+      .time {
+        display: flex;
+        align-items: center;
+        .new_tag {
+          width: 24px;
+          height: 24px;
+          margin-left: 10px;
+        }
+      }
+      .tag {
+        font-size: 14px;
+        padding: 0 4px;
+        border: 1px solid transparent;
+        border-radius: 4px;
+        margin-left: 20px;
+        align-items: center;
+      }
+      .up {
+        background: #feefef;
+        color: #d64c4c;
+      }
+      .down {
+        background: #ebfff0;
+        color: #4fc08d;
+      }
+    }
+    .rich-section {
+      padding: 20px;
+      ::v-deep(img) {
+        width: 100%;
+      }
+      ::v-deep(span) {
+        font-size: 18px;
+        line-height: 1.8;
+      }
+      ::v-deep(p) {
+        font-size: 18px;
+        line-height: 1.8;
+      }
+    }
+  }
+  .right-aside-box {
+    z-index: 99;
+  }
+  .no-auth-wrap {
+    text-align: center;
+    padding: 20px 0;
+    color: #666;
+    &.nodata {
+      margin-top: 130px;
+    }
+    img{
+        width: 400px;
+    }
+    .btn{
+        width: 218px;
+        margin-top: 10px;
+        margin-left: auto;
+        margin-right: auto;
+    }
+  }
+
+}
+.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;
+  }
+}
+</style>
+<style lang="scss">
+  p[data-f-id="pbf"] {
+    display: none !important;
+  }
+</style>

+ 32 - 24
src/views/report/ChapterDetail.vue

@@ -124,12 +124,14 @@ const getChapterReportDetail=async ()=>{
         }
         }
 
 
         //向小程序发送分享数据
         //向小程序发送分享数据
+        //处理分享标题
+        const shareTitle=`【${res.data.report_chapter_item.classify_name_first} | ${res.data.report_chapter_item.type_name}】${res.data.report_chapter_item.title}(${moment(res.data.report_chapter_item.publish_time).format('MMDD')})`
         const postData={
         const postData={
             path:'/pages-report/chapterDetail',
             path:'/pages-report/chapterDetail',
             params:{
             params:{
                 chapterId:chapterId.value
                 chapterId:chapterId.value
             },
             },
-            title:`FICC【${res.data.report_chapter_item.classify_name_first}】`,
+            title:shareTitle,
             shareImg:''
             shareImg:''
         }
         }
         wx.miniProgram.postMessage({ data: postData })
         wx.miniProgram.postMessage({ data: postData })
@@ -292,7 +294,7 @@ const code_scene=computed(()=>{
 const posterParams=computed(()=>{
 const posterParams=computed(()=>{
     return {
     return {
         report_type:info.value.report_chapter_item.classify_name_first,
         report_type:info.value.report_chapter_item.classify_name_first,
-        report_title:`【第${info.value.report_chapter_item.stage}期 | ${info.value.report_chapter_item.classify_name_first}  | ${info.value.report_chapter_item.type_name}】${info.value.report_chapter_item.title}`,
+        report_title:`【第${info.value.report_chapter_item.stage}期 | ${info.value.report_chapter_item.classify_name_first} | ${info.value.report_chapter_item.type_name}】${info.value.report_chapter_item.title}(${moment(info.value.report_chapter_item.publish_time).format('MMDD')})`,
         report_abstract:info.value.report_chapter_item.content
         report_abstract:info.value.report_chapter_item.content
     }
     }
 })
 })
@@ -304,17 +306,22 @@ const posterParams=computed(()=>{
         <div class="hasrightaside-box">
         <div class="hasrightaside-box">
             <div class="content-box">
             <div class="content-box">
                 <div class="report-box">
                 <div class="report-box">
-                    <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="title">【第{{info.report_chapter_item.stage}}期 | {{info.report_chapter_item.classify_name_first}}  | {{info.report_chapter_item.type_name}}】{{info.report_chapter_item.title}}({{moment(info.report_chapter_item.publish_time).format('MMDD')}})</div>
                     <div class="time">
                     <div class="time">
                         <span>FICC团队</span>
                         <span>FICC团队</span>
                         <span>{{moment(info.report_chapter_item.publish_time).format('YYYY.MM.DD HH:mm')}}</span>
                         <span>{{moment(info.report_chapter_item.publish_time).format('YYYY.MM.DD HH:mm')}}</span>
                     </div>
                     </div>
-                    <div class="tips">
-                        <span>注:请务必阅读</span>
-                        <span style="color:#F3A52F;margin-left:20px;cursor: pointer;" @click="showDisclaimers=true">免责声明</span>
+                    <div class="flex tips">
+                        <div>
+                            <div class="abstract" v-if="info.report_chapter_item.abstract">摘要:{{info.report_chapter_item.abstract}}</div>
+                            <div>
+                                <span>*注:请务必阅读</span>
+                                <span style="color:#F3A52F;margin-left:20px;cursor: pointer;" @click="showDisclaimers=true">免责声明</span>
+                            </div>
+                        </div>
                     </div>
                     </div>
                     <AudioBox :data="audioData" v-if="info.report_chapter_item.video_url&&info.report_chapter_item.video_play_seconds>0"></AudioBox>
                     <AudioBox :data="audioData" v-if="info.report_chapter_item.video_url&&info.report_chapter_item.video_play_seconds>0"></AudioBox>
-                    <div class="abstract" v-if="info.report_chapter_item.abstract">摘要:{{info.report_chapter_item.abstract}}</div>
+                    <!-- <div class="abstract" v-if="info.report_chapter_item.abstract">摘要:{{info.report_chapter_item.abstract}}</div> -->
                     <div class="rich-content">
                     <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" v-if="info.auth_ok"></div>
                         <div v-html="info.report_chapter_item.content_sub" v-else ></div>
                         <div v-html="info.report_chapter_item.content_sub" v-else ></div>
@@ -470,30 +477,31 @@ const posterParams=computed(()=>{
             &::before{
             &::before{
                 content: '';
                 content: '';
                 width: 6px;
                 width: 6px;
-                height: 30px;
+                // height: 30px;
                 display: inline-block;
                 display: inline-block;
                 background-color: #F3A52F;
                 background-color: #F3A52F;
                 margin-right: 10px;
                 margin-right: 10px;
-                position: relative;
-                top: 10px;
+                // position: relative;
+                // top: 10px;
             }
             }
         }
         }
         .abstract{
         .abstract{
             font-size: 18px;
             font-size: 18px;
-            font-weight: bold;
-            margin-top: 20px;
-            display: flex;
-            align-items: center;
-            &::before{
-                flex-shrink: 0;
-                content: '';
-                display: block;
-                width: 6px;
-                min-height: 30px;
-                background-color: #F3A52F;
-                margin-right: 10px;
-                position: relative;
-            }
+            // font-weight: bold;
+            margin-bottom: 20px;
+            // margin-top: 20px;
+            // display: flex;
+            // align-items: center;
+            // &::before{
+            //     flex-shrink: 0;
+            //     content: '';
+            //     display: block;
+            //     width: 6px;
+            //     min-height: 30px;
+            //     background-color: #F3A52F;
+            //     margin-right: 10px;
+            //     position: relative;
+            // }
         }
         }
         .rich-content{
         .rich-content{
             margin-top: 30px;
             margin-top: 30px;

+ 75 - 26
src/views/report/Detail.vue

@@ -6,7 +6,7 @@ import 'moment/dist/locale/zh-cn'
 import AudioBox from './components/AudioBox.vue'
 import AudioBox from './components/AudioBox.vue'
 import SharePoster from '@/components/SharePoster.vue'
 import SharePoster from '@/components/SharePoster.vue'
 import Comment from '@/components/Comment.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 {apiGetWechatQRCode} from '@/api/common'
 import { useRoute , onBeforeRouteUpdate,useRouter} from 'vue-router';
 import { useRoute , onBeforeRouteUpdate,useRouter} from 'vue-router';
 import { useStore } from 'vuex';
 import { useStore } from 'vuex';
@@ -65,13 +65,42 @@ 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})`
+        }else{
+            // 专栏类报告
+            if(res.data.report_show_type==2){
+                const abstract=res.data.report_info.abstract?`:${res.data.report_info.abstract}`:''
+                if(res.data.report_info.classify_name_second==res.data.report_info.title){
+                    shareTitle=`${res.data.report_info.title}(${shareTime})${abstract}`
+                }else{
+                    shareTitle=`【${res.data.report_info.classify_name_second}】${res.data.report_info.title}(${shareTime})`
+                }
+            }else{
+                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={
         const postData={
             path:'/pages-report/reportDetail',
             path:'/pages-report/reportDetail',
             params:{
             params:{
                 reportId:reportId.value
                 reportId:reportId.value
             },
             },
-            title:`FICC【${res.data.report_info.classify_name_first}】`,
-            shareImg:''
+            title:shareTitle,
+            shareImg:shareImg
         }
         }
         wx.miniProgram.postMessage({ data: postData })
         wx.miniProgram.postMessage({ data: postData })
         
         
@@ -260,11 +289,24 @@ const code_scene=computed(()=>{
 const posterParams=computed(()=>{
 const posterParams=computed(()=>{
     return {
     return {
         report_type:info.value.report_info.classify_name_first,
         report_type:info.value.report_info.classify_name_first,
-        report_title:`【第${info.value.report_info.stage}期 | ${info.value.report_info.classify_name_second}】${info.value.report_info.title}`,
+        // report_title:`【第${info.value.report_info.stage}期 | ${info.value.report_info.classify_name_second}】${info.value.report_info.title}`,
+        report_title:formatTitle(info.value.report_info),
         report_abstract:info.value.report_info.content
         report_abstract:info.value.report_info.content
     }
     }
 })
 })
 
 
+// 报告标题
+const formatTitle=(e)=>{
+    let t=moment(e.publish_time).format('MMDD')
+    let title=''
+    if(e.classify_name_second==e.title){
+        title=`【第${e.stage}期】${e.title}(${t})`
+    }else{
+        title=`【第${e.stage}期 | ${e.classify_name_second}】${e.title}(${t})`
+    }
+    return title
+}
+
 </script>
 </script>
 
 
 <template>
 <template>
@@ -312,18 +354,24 @@ const posterParams=computed(()=>{
                 </div>
                 </div>
                 <!-- 报告详情 -->
                 <!-- 报告详情 -->
                 <div class="report-box" v-else>
                 <div class="report-box" v-else>
-                    <div class="title">【第{{info.report_info.stage}}期|{{info.report_info.classify_name_second}}】{{info.report_info.title}}</div>
+                    <!-- <div class="title">【第{{info.report_info.stage}}期|{{info.report_info.classify_name_second}}】{{info.report_info.title}}</div> -->
+                    <div class="title">{{formatTitle(info.report_info)}}</div>
                     <div class="time">
                     <div class="time">
                         <span>FICC团队</span>
                         <span>FICC团队</span>
                         <span>{{moment(info.report_info.publish_time).format('YYYY.MM.DD HH:mm')}}</span>
                         <span>{{moment(info.report_info.publish_time).format('YYYY.MM.DD HH:mm')}}</span>
                     </div>
                     </div>
-                    <div class="tips">
-                        <span>注:请务必阅读</span>
-                        <span style="color:#F3A52F;margin-left:20px;cursor: pointer;" @click="showDisclaimers=true">免责声明</span>
+                    <div class="flex tips">
+                        <div>
+                            <div class="abstract" v-if="info.report_info.abstract">摘要:{{info.report_info.abstract}}</div>
+                            <div>
+                                <span>*注:请务必阅读</span>
+                                <span style="color:#F3A52F;margin-left:20px;cursor: pointer;" @click="showDisclaimers=true">免责声明</span>
+                            </div>
+                        </div>
                     </div>
                     </div>
                     <!-- 音频模块 -->
                     <!-- 音频模块 -->
                     <AudioBox :data="audioData" v-if="info.report_info.video_url&&info.report_info.video_play_seconds>0"></AudioBox>
                     <AudioBox :data="audioData" v-if="info.report_info.video_url&&info.report_info.video_play_seconds>0"></AudioBox>
-                    <div class="abstract" v-if="info.report_info.abstract">摘要:{{info.report_info.abstract}}</div>
+                    <!-- <div class="abstract" v-if="info.report_info.abstract">摘要:{{info.report_info.abstract}}</div> -->
 
 
                     <div class="rich-content">
                     <div class="rich-content">
                         <div v-html="info.report_info.content" v-if="info.auth_ok"></div>
                         <div v-html="info.report_info.content" v-if="info.auth_ok"></div>
@@ -468,30 +516,31 @@ const posterParams=computed(()=>{
             &::before{
             &::before{
                 content: '';
                 content: '';
                 width: 6px;
                 width: 6px;
-                height: 30px;
+                // height: 30px;
                 display: inline-block;
                 display: inline-block;
                 background-color: #F3A52F;
                 background-color: #F3A52F;
                 margin-right: 10px;
                 margin-right: 10px;
-                position: relative;
-                top: 10px;
+                // position: relative;
+                // top: 10px;
             }
             }
         }
         }
         .abstract{
         .abstract{
             font-size: 18px;
             font-size: 18px;
-            font-weight: bold;
-            margin-top: 20px;
-            display: flex;
-            align-items: center;
-            &::before{
-                flex-shrink: 0;
-                content: '';
-                display: block;
-                width: 6px;
-                min-height: 30px;
-                background-color: #F3A52F;
-                margin-right: 10px;
-                position: relative;
-            }
+            // font-weight: bold;
+            margin-bottom: 20px;
+            // margin-top: 20px;
+            // display: flex;
+            // align-items: center;
+            // &::before{
+            //     flex-shrink: 0;
+            //     content: '';
+            //     display: block;
+            //     width: 6px;
+            //     min-height: 30px;
+            //     background-color: #F3A52F;
+            //     margin-right: 10px;
+            //     position: relative;
+            // }
         }
         }
         .rich-content{
         .rich-content{
             margin-top: 30px;
             margin-top: 30px;

+ 111 - 66
src/views/report/Index.vue

@@ -122,16 +122,18 @@ const getReportList = async () => {
 const clickFirstType = (item) => {
 const clickFirstType = (item) => {
   selectFirstType.value = item.classify_name
   selectFirstType.value = item.classify_name
   subTypeList.value = item.list
   subTypeList.value = item.list
-  clickSubType({props:{label:item.list[0].chart_permission_name,name:item.list[0].chart_permission_id}})
+  // clickSubType({props:{label:item.list[0].chart_permission_name,name:item.list[0].chart_permission_id}})
+  clickSubType(item.list[0])
 }
 }
 //点击二级分类
 //点击二级分类
-const clickSubType = ({props}) => {
-  let item=null
-  subTypeList.value.forEach(_item=>{
-    if(_item.chart_permission_id==props.name){
-      item=_item
-    }
-  })
+// const clickSubType = ({props}) => {
+  // let item=null
+  // subTypeList.value.forEach(_item=>{
+  //   if(_item.chart_permission_id==props.name){
+  //     item=_item
+  //   }
+  // })
+const clickSubType = (item) => {
   selectSubType.value = item.chart_permission_id
   selectSubType.value = item.chart_permission_id
   reportState.list = []
   reportState.list = []
   reportState.page = 1
   reportState.page = 1
@@ -279,20 +281,38 @@ onActivated(()=>{
           <div class="see-more" @click="handleGoMoreClassify">查看更多</div>
           <div class="see-more" @click="handleGoMoreClassify">查看更多</div>
         </div>
         </div>
         <div class="sub-nav">
         <div class="sub-nav">
-            <!-- <span 
+            <span 
               :class="['sub-item', item.chart_permission_id == selectSubType && 'sub-active']" 
               :class="['sub-item', item.chart_permission_id == selectSubType && 'sub-active']" 
-              v-for="item in subTypeList" 
+              v-for="item in subTypeList.slice(0,6)" 
               :key="item.chart_permission_id" 
               :key="item.chart_permission_id" 
               @click="clickSubType(item)"
               @click="clickSubType(item)"
-            >{{ item.chart_permission_name }}</span> -->
-          <el-tabs v-model="selectSubType" class="tabs-wrap" @tab-click="clickSubType">
+            >{{ item.chart_permission_name }}</span>
+            <el-popover
+              :width="500"
+              trigger="click"
+            >
+              <template #reference>
+                <img v-if="subTypeList.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 == selectSubType&&'active']" 
+                      v-for="item in subTypeList.slice(6)" 
+                      :key="item.chart_permission_id"
+                      @click="clickSubType(item)"
+                  >{{item.chart_permission_name}}</div>
+                </div>
+              </template>
+            </el-popover>
+          <!-- <el-tabs v-model="selectSubType" class="tabs-wrap" @tab-click="clickSubType">
             <el-tab-pane 
             <el-tab-pane 
                 :label="item.chart_permission_name" 
                 :label="item.chart_permission_name" 
                 :name="item.chart_permission_id"
                 :name="item.chart_permission_id"
                 v-for="item in subTypeList" 
                 v-for="item in subTypeList" 
                 :key="item.chart_permission_id"
                 :key="item.chart_permission_id"
             ></el-tab-pane>
             ></el-tab-pane>
-          </el-tabs>
+          </el-tabs> -->
         </div>
         </div>
       </div>
       </div>
       <!-- 报告列表 -->
       <!-- 报告列表 -->
@@ -355,6 +375,30 @@ onActivated(()=>{
 </template>
 </template>
 
 
 <style lang="scss" scoped>
 <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;
+          }
+}
+
 .el-backtop{
 .el-backtop{
   z-index: 1000;
   z-index: 1000;
 }
 }
@@ -444,66 +488,67 @@ onActivated(()=>{
       .sub-nav {
       .sub-nav {
         margin-top: 30px;
         margin-top: 30px;
         // overflow-x: auto;
         // overflow-x: auto;
-        // overflow-y: hidden;
+        overflow-y: hidden;
         // &::-webkit-scrollbar {
         // &::-webkit-scrollbar {
         //   display: none;
         //   display: none;
         // }
         // }
-        width: calc(100vw - 500px);
-        // .sub-item {
-        //   flex-shrink: 0;
-        //   margin-right: 30px;
-        //   font-size: 16px;
-        //   color: #666666;
-        //   cursor: pointer;
-        // }
-        // .sub-active {
-        //   color: #F3A52F;
-        // }
-        :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;
-            // height: 22px;
-            &: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;
-            }
+        // width: calc(100vw - 500px);
+        .sub-item {
+          flex-shrink: 0;
+          margin-right: 30px;
+          font-size: 16px;
+          color: #666666;
+          cursor: pointer;
         }
         }
-        :deep(.el-tabs__nav-wrap.is-scrollable){
-            padding: 0 25px;
+        .sub-active {
+          color: #F3A52F;
         }
         }
+        // :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;
+        //     // height: 22px;
+        //     &: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;
+        // }
 
 
       }
       }
+      
     }
     }
 
 
     .report-list-wrap {
     .report-list-wrap {

+ 15 - 4
src/views/report/List.vue

@@ -252,6 +252,8 @@ const posterParams=computed(()=>{
                     </div>  
                     </div>  
                 </div>
                 </div>
             </div>
             </div>
+            <div class="last-add-item"></div>
+            <div class="last-add-item"></div>
         </div>
         </div>
         </SelfList>
         </SelfList>
     </div>
     </div>
@@ -314,13 +316,22 @@ const posterParams=computed(()=>{
     .list-wrap{
     .list-wrap{
         flex-wrap: wrap;
         flex-wrap: wrap;
         justify-content: center;
         justify-content: center;
-        &::after{
-            content:'';
-            display: block;
+        // &::after{
+        //     content:'';
+        //     display: block;
+        //     height:0;
+        //     flex-shrink: 0;
+        //     width: 380px;
+        //     margin-bottom: 20px;
+        //     margin-left: 10px;
+        //     margin-right: 10px;
+        // }
+
+        // 末尾补充的两个元素 为了整体能居中
+        .last-add-item{
             height:0;
             height:0;
             flex-shrink: 0;
             flex-shrink: 0;
             width: 380px;
             width: 380px;
-            margin-bottom: 20px;
             margin-left: 10px;
             margin-left: 10px;
             margin-right: 10px;
             margin-right: 10px;
         }
         }

+ 329 - 0
src/views/video/List.vue

@@ -0,0 +1,329 @@
+<script setup>
+import {ref,reactive,onMounted,onActivated} from 'vue'
+import { useElementSize } from '@vueuse/core'
+
+import {apiFICCPermissionList,apiGetWechatQRCode} from '@/api/common'
+import {apiVideoList} from '@/api/video'
+
+import SelfList from '@/components/SelfList.vue'
+
+
+//监听列表页面版心宽度
+const listPageEl=ref('')
+const {width}=useElementSize(listPageEl)
+
+// 获取品种权限数据
+let permissionState=reactive({
+    firstNavList:[],
+    sFirst:'',
+    secNavList:[],
+    sSecond:0//选择的品种id 
+})
+const getFICCPermissionList=async ()=>{
+    const res=await apiFICCPermissionList()
+    if(res.code===200){
+        permissionState.firstNavList=res.data
+        handelChangeFirstNav(res.data[0])
+    }
+}
+getFICCPermissionList()
+
+//点击一级分类
+const handelChangeFirstNav=(item)=>{
+    permissionState.sFirst=item.ClassifyName
+    permissionState.secNavList=item.Items
+    handleChangeSecNav(item.Items[0])
+}
+
+//点击二级分类
+const handleChangeSecNav=(item)=>{
+    permissionState.sSecond=item.PermissionId
+    refreshList()
+}
+
+//获取视频列表数据
+let listState = reactive({
+    loading:false,
+    finished:false,
+    page:1,
+    list:[],
+})
+const getVideoList=async ()=>{
+    listState.loading=true
+    const res=await apiVideoList({
+        page_index:Number(listState.page),
+        page_size:20,
+        video_id:0,
+        chart_permission_id:Number(permissionState.sSecond)
+    })
+    listState.loading=false
+    if(res.code===200){
+        let arr=res.data||[]
+        listState.list=[...listState.list,...arr]
+        if(arr.length===0||arr.length<20){
+            listState.finished=true
+        }
+    }
+}
+getVideoList()
+
+//刷新列表
+const refreshList=()=>{
+    listState.finished=false
+    listState.page=1
+    listState.list=[]
+    curVideoId.value=0
+    getVideoList()
+}
+
+// 加载下一页
+const onLoad=()=>{
+    listState.page++
+    getVideoList()
+}
+
+//当前正在播放哪个
+let curVideoId=ref(0)
+const handelClickPlay=(item)=>{
+    curVideoId.value=item.community_video_id
+}
+
+
+//获取视频单个对应的小程序二维码
+const handelGetQRCodeImg=async (item)=>{
+    const res=await apiGetWechatQRCode({
+        CodeScene:JSON.stringify({videoId:item.community_video_id}),
+        CodePage:'pages/video/videoList'
+    })
+    if(res.code===200){
+        item.QRCodeImg=res.data
+    }
+}
+
+onMounted(() => {
+  //向小程序发送消息
+  let postData = {
+    path: "/pages/video/videoList",
+    params:{},
+    title: "FICC视频社区",
+    shareImg:''
+  };
+  wx.miniProgram.postMessage({ data: postData });
+});
+
+onActivated(()=>{
+    //向小程序发送消息
+    let postData = {
+        path: "/pages/video/videoList",
+        params:{},
+        title: "FICC视频社区",
+        shareImg:''
+    };
+    wx.miniProgram.postMessage({ data: postData });
+})
+
+</script>
+
+<template>
+    <div class="video-list-page" ref="listPageEl">
+        <div class="top-nav-box" :style="{width:width+'px'}">
+            <div class="first-nav-box">
+                <span 
+                    v-for="item in permissionState.firstNavList" 
+                    :key="item.ClassifyName"
+                    :class="item.ClassifyName==permissionState.sFirst?'active':''"
+                    @click="handelChangeFirstNav(item)"
+                >{{item.ClassifyName}}</span>
+            </div>
+            <div class="sec-nav-box">
+                <span
+                    :class="['sec-item',item.PermissionId==permissionState.sSecond?'active':'']"
+                    v-for="item in permissionState.secNavList.slice(0,6)"
+                    :key="item.PermissionId"
+                    @click="handleChangeSecNav(item)"
+                >{{item.PermissionName}}</span>
+                <el-popover
+                    :width="500"
+                    trigger="click"
+                >
+                    <template #reference>
+                        <img v-if="permissionState.secNavList.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.PermissionId == permissionState.sSecond&&'active']" 
+                                v-for="item in permissionState.secNavList.slice(6)" 
+                                :key="item.PermissionId"
+                                @click="handleChangeSecNav(item)"
+                            >{{item.PermissionName}}</div>
+                        </div>
+                    </template>
+                </el-popover>
+            </div>
+        </div>
+        <SelfList 
+            :finished="listState.finished" 
+            :isEmpty="listState.list.length===0&&listState.finished"
+            :loading="listState.loading"
+            @listOnload="onLoad"
+        >
+            <div class="flex list-wrap">
+                <div class="video-item" v-for="item in listState.list" :key="item.community_video_id">
+                    <el-popover
+                        :width="200"
+                        trigger="click"
+                    >
+                        <template #reference>
+                            <div class="icon-wechat" @click="handelGetQRCodeImg(item)"></div>
+                        </template>
+                        <template #default>
+                            <img style="width:100%" :src="item.QRCodeImg" alt="">
+                        </template>
+                    </el-popover>
+                    <div class="title">{{item.title}}</div>
+                    <video 
+                        :src="item.video_url" 
+                        controls
+                        :poster="item.cover_img_url"
+                        controlslist="nodownload"
+                        disablePictureInPicture
+                        autoplay
+                        v-if="item.community_video_id==curVideoId"
+                    ></video>
+                    <div v-else class="poster-img" :style="'background-image:url('+item.cover_img_url+')'" @click="handelClickPlay(item)"></div>
+                    <div class="time">发布时间:{{item.publish_time}}</div>
+                </div>
+            </div>
+        </SelfList>
+    </div>
+</template>
+
+<style lang="scss" scoped>
+.icon-wechat{
+    cursor: pointer;
+    width: 24px;
+    height: 24px;
+    background-image: url('@/assets/icon-wechat.png');
+    background-size: cover;
+    position: absolute;
+    top: 30px;
+    right: 30px;
+}
+.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;
+    }
+}
+.video-list-page{
+    .top-nav-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;
+        .first-nav-box{
+            span{
+                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;
+            }
+            .active{
+                background-color: #FFFBF5;
+                box-shadow: 0px 6px 7px 1px #FFF7EB;
+                color: #F3A52F;
+                border: 1px solid #F3A52F;
+            }
+        }
+        .sec-nav-box{
+            margin-top: 30px;
+            .sec-item{
+                color: #666;
+                margin-right: 30px;
+                cursor: pointer;
+                display: inline-block;
+            }
+            .active{
+                color: #F3A52F;
+            }
+        }
+    }
+
+    .list-wrap{
+        padding-top: 150px;
+        border-left: 1px solid #E2E2E2;
+        border-right: 1px solid #E2E2E2;
+        flex-wrap: wrap;
+        .video-item{
+            width: 50%;
+            padding: 30px;
+            border-bottom: 1px solid #E2E2E2;
+            position: relative;
+            &:nth-of-type(odd){
+                border-right: 1px solid #E2E2E2;
+            }
+            .title{
+                font-size: 16px;
+                color: #666;
+            }
+            video{
+                width: 100%;
+                height: 200px;
+                object-fit: contain;
+                margin: 19px 0;
+            }
+            .poster-img{
+                width: 100%;
+                height: 200px;
+                margin: 19px 0;
+                position: relative;
+                background-size: cover;
+                cursor: pointer;
+                &::after{
+                    content:'';
+                    display: block;
+                    position: absolute;
+                    width: 80px;
+                    height: 80px;
+                    top: 50%;
+                    left: 50%;
+                    transform: translate(-50%,-50%);
+                    background-image: url('@/assets/video-play-btn.png');
+                    background-size: cover;
+                }
+            }
+            .time{
+                color: #999;
+                font-size: 14px;
+            }
+        }
+    }
+}
+</style>