bding 6 mesi fa
parent
commit
125c6b695b

+ 5 - 0
src/api/cygx/api.js

@@ -45,6 +45,11 @@ export const RaiApi = {
   appointmentExpert: (params) => {
     return post("/article/applyAppointmentExpert", params);
   },
+
+  // 获取ficc 报告
+  getFiccYbReportDetails: (params) => {
+    return get("/ficc_report/detail", params, 0);
+  },
 };
 export const FreeButton = {
   /*获取是否展示免费试用按钮接口*/

+ 2 - 0
src/api/cygx/http.js

@@ -17,6 +17,8 @@ _axios.interceptors.request.use(
   function (config) {
     // Do something before request is sent
     let auth = localStorage.getItem("access_token") || "";
+    console.log(auth,'------');
+    
     if (auth) {
       config.headers.Authorization = auth;
     }

+ 5 - 0
src/router/cygx/index.js

@@ -53,4 +53,9 @@ export const cygxRoutes = [
       },
     ],
   },
+  {
+    path: "/ficcReportDtl",
+    name: "FiccReportDtl",
+    component: () => import("@/views/cygx/FICCReport/Detail.vue"),
+  },
 ];

+ 624 - 0
src/views/cygx/FICCReport/Detail.vue

@@ -0,0 +1,624 @@
+<template>
+  <van-pull-refresh v-model="loading" disabled style="min-height: 100vh">
+    <div class="report-detail-page" @click="closeAttention" v-if="info" :style="{ paddingBottom: $store.state.hzyb.audioData.url && '80px' }">
+      <!-- 报告详情 -->
+      <div :class="['main-box', !info.auth_ok && 'main-box-noauth']">
+        <!-- <div class="title">【第{{info.report_info.stage}}期|{{info.report_info.classify_name_second}}】{{info.report_info.title}}</div> -->
+        <div :style="{ backgroundColor: info.report_info.canvas_color || '' }">
+          <!-- 无版头板尾显示标题 -->
+          <template v-if="!info.report_info.head_img && !info.report_info.end_img">
+            <div class="title">{{ title }}</div>
+            <div class="flex time">
+              <span>{{ info.report_info.author }}</span>
+              <span>{{ formatTime(info.report_info.publish_time) }}</span>
+            </div>
+          </template>
+
+          <!-- 拼接版头 -->
+          <div class="html-head-img-box" v-if="info.auth_ok && info.report_info.head_img">
+            <img :src="info.report_info.head_img" alt="" style="display: block; width: 100%" />
+            <div
+              class="head-layout-item"
+              v-for="item in headImgStyle"
+              :key="item.value"
+              :style="{
+                fontFamily: item.family,
+                fontSize: item.size * 2 + 'px',
+                fontWeight: item.weight,
+                textAlign: item.align,
+                color: item.color,
+                width: item.width,
+                height: item.height,
+                left: item.left,
+                top: item.top,
+              }"
+            >
+              {{ layoutBaseInfo[item.value] }}
+            </div>
+          </div>
+          <div class="flex tips">
+            <div style="flex: 1">
+              <div class="abstract" v-if="info.report_info.abstract">摘要:{{ info.report_info.abstract }}</div>
+              <div>
+                <span>注:请务必阅读</span>
+                <span style="color: #e3b377; margin-left: 20px" @click="showDisclaimers = true">免责声明</span>
+              </div>
+            </div>
+          </div>
+          <div v-if="isBinding" id="report-rich-content" class="rich-content" style="position: relative" ref="richConBox">
+            <!-- 单人报告 -->
+            <template v-if="info.auth_ok">
+              <div v-if="!info.report_info.has_chapter">
+                <ul>
+                  <li v-for="item in realContent" :key="item" v-html="item"></li>
+                </ul>
+              </div>
+
+              <!-- 展示拼接的章节报告 -->
+              <template v-if="info.report_info.has_chapter && info.report_detail_show_type === 1">
+                <div class="chapter-concat-item" v-for="chapter in info.report_chapter_list" :key="chapter.report_chapter_id">
+                  <div class="chapter-title">
+                    <h3 class="chapter-title-text">{{ chapter.title }}</h3>
+                  </div>
+                  <div class="html-cont" v-html="chapter.content"></div>
+                </div>
+              </template>
+            </template>
+
+            <div v-html="info.report_info.content_sub" v-else></div>
+            <!-- 隐藏的水印
+            <div class="hide-watermark-box" v-if="userInfo">
+              <div v-for="item in 20" :key="item">{{ userInfo.mobile }}</div>
+            </div> -->
+          </div>
+          <template v-else>
+            <div v-if="info.report_info.content_sub" v-html="info.report_info.content_sub.slice(0, 200)"></div>
+            <div class="please-login" @click="pleaseGoLogin">请登录后查看更多内容</div>
+          </template>
+          <!-- 拼接版尾 -->
+          <div class="html-end-img-box" v-if="info.auth_ok && info.report_info.end_img">
+            <img :src="info.report_info.end_img" alt="" style="display: block; width: 100%" />
+            <div
+              class="head-layout-item"
+              v-for="item in endImgStyle"
+              :key="item.value"
+              :style="{
+                fontFamily: item.family,
+                fontSize: item.size * 2 + 'px',
+                fontWeight: item.weight,
+                textAlign: item.align,
+                color: item.color,
+                width: item.width,
+                height: item.height,
+                left: item.left,
+                top: item.top,
+              }"
+            >
+              {{ layoutBaseInfo[item.value] }}
+            </div>
+          </div>
+        </div>
+
+        <!-- 右侧悬浮操作栏 -->
+        <div class="right-fix-box">
+          <!-- 返回顶部 -->
+          <div class="item back-top-img">
+            <img v-show="showToTop && info.auth_ok" @click="handleBackTop" class="back-top-img" src="@/assets/hzyb/report/back-top.png" />
+          </div>
+        </div>
+      </div>
+
+      <!-- 免责声明 -->
+      <Disclaimer v-model:show="showDisclaimers" :disclaimer="info.report_info.disclaimer" />
+    </div>
+  </van-pull-refresh>
+</template>
+
+<script>
+// 由于当时写在uni中 直接复制过来的 也不想改了就写成vue2形式吧
+import moment from "moment";
+import "moment/dist/locale/zh-cn";
+moment.locale("zh-cn");
+
+import { apiReportDetail, apiReportPPtImgs, apiPublicBannerMark, apiPublicBannerList } from "@/api/hzyb/report";
+import { RaiApi } from "@/api/cygx/api.js";
+import { Popup, Image as VanImage, PullRefresh, Dialog, Toast, Swipe, SwipeItem } from "vant";
+import _ from "lodash";
+import Disclaimer from "./Disclaimer.vue";
+
+import { addTokenToIframe } from "../../hzyb/utils/common";
+
+export default {
+  components: {
+    [Popup.name]: Popup,
+    [VanImage.name]: VanImage,
+    [PullRefresh.name]: PullRefresh,
+    [Swipe.name]: Swipe,
+    [SwipeItem.name]: SwipeItem,
+    [Dialog.name]: Dialog,
+    Disclaimer,
+  },
+  computed: {
+    code_scene() {
+      return JSON.stringify({
+        reportId: this.reportId,
+      });
+    },
+    posterParams() {
+      return {
+        report_type: this.info.report_info.classify_name_first,
+        report_title: this.title,
+        report_abstract: this.info.report_info.content,
+      };
+    },
+  },
+  data() {
+    return {
+      showDisclaimers: false, //显示免责声明
+      reportId: 0,
+      info: null,
+      title: "", //标题数据
+      audioData: {}, //音频数据
+      chapterList: [],
+      pupData: {
+        show: false,
+        content: "", //弹窗html字符串
+      },
+      loading: false,
+      showToTop: false,
+
+      totalContent: [],
+      realContent: [],
+      page_no: 0,
+      pageSize: 20, //默认初始加载20个p标签
+      total_page: 0,
+
+      hasPPt: false, //是否有ppt
+
+      userInfo: null,
+      shareData: {}, //分享的数据传给ppt页
+
+      showAttention: false, //是否显示配置播放清单提示
+      isReportPublishCancel: false, //报告取消发布
+      bannerDataList: [],
+
+      headImgStyle: null, //版头style
+      endImgStyle: null, //版尾style
+      layoutBaseInfo: {
+        研报标题: "",
+        研报作者: "",
+        创建时间: "",
+      },
+      isBinding: true,
+    };
+  },
+  created(options) {
+    this.reportId = this.$route.query.id;
+    let access_token = this.$route.query.token || "";
+    this.isBinding = this.$route.query.isBinding == "true" ? true : false;
+    localStorage.setItem("access_token", access_token);
+    this.getDetail();
+  },
+  mounted() {
+    $(document).on("click", ".rich-content img", function (event) {
+      let imgArray = [];
+      let curImageSrc = $(this).attr("src");
+      let oParent = $(this).parent();
+      if (curImageSrc && !oParent.attr("href")) {
+        $(".rich-content img").each(function (index, el) {
+          let itemSrc = $(this).attr("src");
+          imgArray.push(itemSrc);
+        });
+        wx.previewImage({ current: curImageSrc, urls: imgArray });
+      }
+    });
+    window.addEventListener("scroll", this.loadMoreHandle);
+  },
+  destroyed() {
+    window.removeEventListener("scroll", this.loadMoreHandle);
+  },
+  methods: {
+    // 跳转登录页面
+    pleaseGoLogin() {
+      Dialog.alert({
+        message: "即将前往登录页面,请确认是否继续",
+        showCancelButton: true,
+        confirmButtonColor: "#376cbb",
+      }).then((res) => {
+        if (res == "confirm") {
+          wx.miniProgram.navigateTo({
+            url: "/pageMy/login/login",
+          });
+        }
+      });
+    },
+    //获取报告详情
+    async getDetail() {
+      const res = await RaiApi.getFiccYbReportDetails({ ReportId: Number(this.reportId) });
+      if (res.Ret === 200) {
+        this.info = res.Data;
+        this.headImgStyle = this.info.report_info.head_style ? JSON.parse(this.info.report_info.head_style) : [];
+        this.endImgStyle = this.info.report_info.end_style ? JSON.parse(this.info.report_info.end_style) : [];
+        this.layoutBaseInfo["研报标题"] = this.info.report_info.title;
+        this.layoutBaseInfo["研报作者"] = this.info.report_info.author;
+        // 已发布已通过的报告才显示发布时间
+        this.layoutBaseInfo["创建时间"] = moment(this.info.report_info.publish_time).format("YYYY.MM.DD HH:mm");
+        this.audioData = {
+          auth_ok: this.info.auth_ok,
+          video_name: this.info.report_info.video_name || `${this.info.report_info.title}(${moment(this.info.report_info.publish_time).format("MMDD")})`,
+          video_play_seconds: this.info.report_info.video_play_seconds,
+          video_url: this.info.report_info.video_url,
+          video_img: this.info.report_info.video_img,
+        };
+        this.chapterList = this.info.report_chapter_list;
+        document.title = this.info.report_info.classify_name_first || "";
+        //非章节报告处理内容分页
+        !this.info.report_info.has_chapter && this.splitContentHandle(this.info.report_info.content);
+
+        // 处理报告标题数据
+        // if(!this.info.report_info.has_chapter){
+        const time = moment(this.info.report_info.publish_time).format("MMDD");
+        if (this.info.report_info.classify_name_second == this.info.report_info.title) {
+          this.title = `【第${this.info.report_info.stage}期】${this.info.report_info.title}(${time})`;
+        } else {
+          this.title = `【第${this.info.report_info.stage}期|${this.info.report_info.classify_name_second}】${this.info.report_info.title}(${time})`;
+        }
+        // }
+      }
+    },
+    /*内容分割*/
+    splitContentHandle(content) {
+      content = addTokenToIframe(content, this.reportId, 0);
+      const arr = content.split("</p>");
+      this.totalContent = arr.map((_) => _ + "</p>");
+      this.realContent = this.totalContent.slice(0, this.pageSize);
+      this.total_page = parseInt(this.totalContent.length / this.pageSize) + 1;
+      this.formatSmartStyle();
+    },
+    //添加水印
+    waterMark(text, target) {
+      if (!target) return;
+      const canvas = document.createElement("canvas");
+      const ctx = canvas.getContext("2d");
+      ctx.font = "18px Arial";
+      ctx.rotate((-45 * Math.PI) / 200);
+      ctx.fillStyle = "#F1F1F1";
+      ctx.fillText(text, 30, 200);
+      ctx.fillText(text, -40, 100);
+
+      // 将canvas的内容转换为base64编码
+      const data = canvas.toDataURL("image/png");
+
+      target.style.background = "url(" + data + ") repeat";
+    },
+
+    // 智能布局内容排版全部变成1个1行的顺排
+    formatSmartStyle() {
+      this.$nextTick(() => {
+        $(".report-drag-item-wrap_child-wrap").css({
+          "flex-wrap": "wrap",
+        });
+        $(".report-drag-item-wrap_child-wrap").children().css({
+          flex: "none",
+          width: "100%",
+        });
+      });
+    },
+
+    /* 加载下一页内容 */
+    loadContent() {
+      this.realContent = this.realContent.concat(this.totalContent.slice(this.page_no * this.pageSize, (this.page_no + 1) * this.pageSize));
+      this.formatSmartStyle();
+    },
+
+    loadMoreHandle: _.throttle(function () {
+      const scrollTop = document.documentElement.scrollTop || document.body.scrollTop; // 滚动的高度
+
+      if (scrollTop > window.outerHeight - 150) {
+        this.showToTop = true;
+      } else {
+        this.showToTop = false;
+      }
+
+      if (this.page_no >= this.total_page) return;
+
+      const clientHeight = document.documentElement.clientHeight || document.body.clientHeight; // 可视高度
+      const scrollHeight = document.body.scrollHeight; // 总高度
+      const bufferHeight = 400;
+
+      if (scrollHeight - scrollTop - clientHeight < bufferHeight + 100) {
+        this.page_no = this.page_no + 1;
+        this.loadContent();
+      }
+    }, 300),
+
+    //返回顶部
+    handleBackTop() {
+      document.body.scrollTop = document.documentElement.scrollTop = 0;
+    },
+
+    // 格式化时间
+    formatTime(time) {
+      return moment(time).format("YYYY.MM.DD HH:mm:ss");
+    },
+
+    //格式化音频时间
+    formatVoiceTime(e) {
+      let minus = parseInt(e / 60);
+      let sec = parseInt(e % 60);
+      return `${minus > 9 ? minus : "0" + minus}分${sec > 9 ? sec : "0" + sec}秒`;
+    },
+
+    // 格式化章节列表时间
+    formatChapterTime(time, type) {
+      if (type === "day") {
+        return moment(time).format("DD");
+      }
+      if (type === "week") {
+        return moment(time).format("dddd");
+      }
+      if (type === "year-month") {
+        return moment(time).format("YYYY-MM");
+      }
+      if (type === "year-month-day") {
+        return moment(time).format("YYYY-MM-DD");
+      }
+    },
+
+    onRefresh() {
+      this.getDetail();
+      setTimeout(() => {
+        this.loading = false;
+      }, 1500);
+    },
+
+    // 设置tag颜色
+    getTagColor(str) {
+      if (str.includes("多") || str.includes("强") || str.includes("反弹")) {
+        return "#DF6051";
+      } else if (str.includes("空") || str.includes("调整")) {
+        return "#6FC5B4";
+      } else {
+        return "#009fe6";
+      }
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+/* 公共弹窗 */
+.global-pup {
+  background-color: #fff;
+  width: 90vw;
+  min-height: 200px;
+  font-size: 32px;
+  .content {
+    padding: 34px;
+    text-align: center;
+    min-height: 250px;
+    display: flex;
+    align-items: center;
+    text-align: center;
+    line-height: 1.7;
+    div {
+      flex: 1;
+    }
+  }
+  .bot {
+    border-top: 1px solid #dedede;
+    div {
+      line-height: 96px;
+      flex: 1;
+      text-align: center;
+      border-right: 1px solid #dedede;
+      color: #e3b377;
+    }
+    div:last-child {
+      border: none;
+    }
+  }
+}
+.flex {
+  display: flex;
+}
+.report-detail-page {
+  /* padding-bottom: 50px; */
+  .main-box {
+    padding: 34px;
+    .title {
+      display: inline;
+      margin-left: -26px;
+    }
+  }
+  .main-box-noauth {
+    height: calc(100vh - 50px);
+    overflow: hidden;
+  }
+  .title {
+    font-size: 40px;
+    font-weight: bold;
+    margin-bottom: 30px;
+  }
+  .time {
+    justify-content: space-between;
+    font-size: 30px;
+    margin-top: 30px;
+  }
+  .audio-wrap {
+    height: 160px;
+    background: #faf7ee;
+    border-radius: 16px;
+    margin-top: 20px;
+    padding: 10px 31px;
+    margin-bottom: 31px;
+    align-items: center;
+    img {
+      width: 110px;
+      height: 110px;
+      display: block;
+      margin-right: 16px;
+    }
+  }
+
+  .tips {
+    margin-top: 15px;
+    font-size: 34px;
+    margin-bottom: 51px;
+    position: relative;
+    &::before {
+      content: "";
+      width: 10px;
+      // height: 100%;
+      display: inline-block;
+      background-color: #e3b377;
+      margin-right: 20px;
+      // position: relative;
+      // top: 10px;
+    }
+    .abstract {
+      font-size: 34px;
+      margin-bottom: 20px;
+      line-height: 1.5;
+    }
+  }
+
+  .disclaimers-box {
+    width: 94vw;
+    padding: 32px;
+  }
+
+  .rich-content {
+    line-height: 1.8;
+    font-size: 36px;
+    :deep(img) {
+      width: 100% !important;
+    }
+    :deep(span) {
+      font-size: 36px !important;
+      line-height: 1.8 !important;
+      background-color: rgba(255, 255, 255, 0) !important;
+    }
+    :deep(p) {
+      font-size: 36px !important;
+      line-height: 1.8 !important;
+      background-color: rgba(255, 255, 255, 0) !important;
+    }
+    :deep(ul) {
+      font-size: 36px !important;
+      line-height: 1.8 !important;
+      background-color: rgba(255, 255, 255, 0) !important;
+    }
+    :deep(ol) {
+      font-size: 36px !important;
+      line-height: 1.8 !important;
+      background-color: rgba(255, 255, 255, 0) !important;
+    }
+    :deep(iframe) {
+      width: 100% !important;
+    }
+    :deep(li) {
+      font-size: 36px !important;
+      line-height: 1.8 !important;
+      background-color: rgba(255, 255, 255, 0) !important;
+      list-style: inherit !important;
+      list-style-position: inside !important;
+    }
+    :deep(span.fr-emoticon) {
+      width: 36px !important;
+      height: 36px !important;
+      background-repeat: no-repeat !important;
+      background-size: cover !important;
+      display: inline-block !important;
+      vertical-align: middle !important;
+    }
+  }
+
+  .no-auth-wrap {
+    min-height: 200px;
+    padding: 0 34px 50px 34px;
+    background: linear-gradient(360deg, #ffffff 60%, rgba(255, 255, 255, 0) 88%);
+    //   position: relative;
+    //   top: -150px;
+    position: fixed;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    z-index: 99;
+    text-align: center;
+    font-size: 32px;
+    color: #e3b377;
+    .apply-box {
+      padding-top: 250px;
+    }
+    .btn {
+      width: 100%;
+      margin-left: auto;
+      margin-right: auto;
+      line-height: 80px;
+      background-color: #e6b77d;
+      border-radius: 4px;
+      color: #fff;
+      margin-top: 100px;
+      display: block;
+    }
+  }
+
+  .right-fix-box {
+    position: fixed;
+    z-index: 99;
+    right: 34px;
+    bottom: 130px;
+    .back-top-img {
+      width: 100px;
+      height: 100px;
+      display: block;
+    }
+  }
+}
+
+.html-head-img-box,
+.html-end-img-box {
+  margin-bottom: 10px;
+  position: relative;
+  overflow: hidden;
+  .head-layout-item {
+    position: absolute;
+    overflow: hidden;
+    box-sizing: border-box;
+  }
+}
+.chapter-concat-item {
+  padding: 20px 0;
+  .chapter-title {
+    display: flex;
+    align-items: center;
+    font-size: 30px;
+    .type {
+      height: fit-content;
+      display: inline-block;
+      color: #fff;
+      padding: 10px 20px;
+      background-color: #e6a23c;
+      border-radius: 8px;
+      margin-right: 20px;
+    }
+    .chapter-title-text {
+      font-size: 30px;
+    }
+  }
+}
+.please-login {
+  margin: 50px auto 150px;
+  width: 556px;
+  height: 64px;
+  color: #fff;
+  font-size: 24px;
+  font-weight: 600;
+  background-color: #376cbb;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  border-radius: 9px;
+}
+</style>

+ 36 - 0
src/views/cygx/FICCReport/Disclaimer.vue

@@ -0,0 +1,36 @@
+<script setup>
+import { ref } from "vue";
+import { apiBaseConfig } from "@/api/hzyb/common";
+import { Popup } from "vant";
+
+const props = defineProps({
+  disclaimer: {
+    type: String,
+  },
+  show: {
+    type: Boolean,
+  },
+});
+
+const $emit = defineEmits();
+
+const closeDlg = () => {
+  $emit("update:show", false);
+};
+</script>
+
+<template>
+  <Popup :show="props.show" @close="closeDlg" round closeable>
+    <div class="disclaimers-box">
+      <div style="text-align: center; font-size: 16px; font-weight: bold; margin-bottom: 20px">免责声明</div>
+      <div v-html="props.disclaimer"></div>
+    </div>
+  </Popup>
+</template>
+
+<style lang="scss" scoped>
+.disclaimers-box {
+  width: 94vw;
+  padding: 32px;
+}
+</style>