Ver Fonte

报告PCPC

db há 2 anos atrás
pai
commit
4f63364a7a

+ 1 - 1
postcss.config.js

@@ -11,7 +11,7 @@ module.exports = {
       minPixelValue: 1, // 最小的转换数值,如果为1的话,只有大于1的值会被转换
       mediaQuery: false, // 媒体查询里的单位是否需要转换单位
       replace: true, // 是否直接更换属性值,而不添加备用属性
-      exclude: /node_modules/, // 忽略某些文件夹下的文件或特定文件
+      exclude: [/node_modules/, /cygxPc/], // 忽略某些文件夹下的文件或特定文件
       include: undefined, // 如果设置了include,那将只有匹配到的文件才会被转换,例如只转换 'src/mobile' 下的文件 (include: /\/src\/mobile\//)
       landscape: false, // 是否添加根据 landscapeWidth 生成的媒体查询条件 @media (orientation: landscape)
       landscapeUnit: "vw", // 横屏时使用的单位

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

@@ -2,11 +2,6 @@
 import axios from "axios";
 import {Toast} from 'vant'
 
-// Full config:  https://github.com/axios/axios#request-config
-// axios.defaults.baseURL = process.env.baseURL || process.env.apiUrl || '';
-// axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
-// axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
-
 // 请求数
 let LOADINGCOUNT = 0;
 let LOADING;
@@ -14,7 +9,6 @@ let LOADING;
 let config = {
   baseURL: import.meta.env.VITE_APP_CYGX_BASEAPIURL,
   timeout: 60 * 1000, // Timeout
-  // withCredentials: true, // Check cross-site Access-Control
 };
 
 const _axios = axios.create(config);
@@ -26,15 +20,7 @@ _axios.interceptors.request.use(
     if (auth) {
       config.headers.Authorization = auth;
     }
-    // 设置loading
-    // if (LOADINGCOUNT === 0) {
-    //   LOADING = Toast.loading({
-    //     message: "loading...",
-    //     duration: 0,
-    //     forbidClick: true,
-    //   });
-    // }
-    // LOADINGCOUNT++;
+
     return config;
   },
   function (error) {
@@ -46,13 +32,7 @@ _axios.interceptors.request.use(
 // Add a response interceptor
 _axios.interceptors.response.use(
   function (response) {
-    // Do something with response data
-
-    //关闭loading
-    // LOADINGCOUNT--;
-    // if (LOADINGCOUNT === 0) {
-    //   LOADING.clear();
-    // }
+    
     return response.data;
   },
   function (error) {

+ 20 - 0
src/api/cygxPc/api.js

@@ -0,0 +1,20 @@
+import { get, post } from "./http";
+
+/* 权益链接 */
+export const RaiApiPc = {
+  /* 获取详情 */
+  reportDtl: (params) => {
+    return get("/article/detailPublic", params);
+  },
+  /* 查看报告 */
+  lookReport: (params) => {
+    return get("/article/look/detail", params);
+  },
+  Bind: (params) => {
+    return post("/user/loginPublic", params);
+  },
+  /* 获取手机验证码  Mobile * AreaNum */
+  getPhoneCode: (params) => {
+    return get("/wechat/getSmsCodePublic", params);
+  },
+};

+ 56 - 0
src/api/cygxPc/http.js

@@ -0,0 +1,56 @@
+"use strict";
+import axios from "axios";
+import { Toast } from "vant";
+import router from "@/router";
+
+let config = {
+  baseURL: import.meta.env.VITE_APP_CYGX_BASEAPIURL,
+  timeout: 60 * 1000, // Timeout
+};
+
+const _axios = axios.create(config);
+
+_axios.interceptors.request.use(
+  function (config) {
+    let auth = localStorage.getItem("cygx_token") || "";
+    if (auth) {
+      config.headers.Authorization = auth;
+    }
+
+    return config;
+  },
+  function (error) {
+    return Promise.reject(error);
+  }
+);
+
+_axios.interceptors.response.use(
+  function (response) {
+    if (response.data.Ret == 408) {
+      localStorage.removeItem("cygx_token");
+      router.push("/cygx/login");
+    }
+    return response.data;
+  },
+  function (error) {
+    return Promise.reject(error);
+  }
+);
+
+/**
+ * 导出get请求方法
+ * @url 请求地址
+ * @params get请求参数
+ */
+export const get = (url, params) => {
+  return _axios.get(url, { params });
+};
+
+/**
+ * 导出post请求方法
+ * @url 请求地址
+ * @params post请求参数
+ */
+export const post = (url, params) => {
+  return _axios.post(url, params);
+};

+ 24 - 7
src/router/cygx/index.js

@@ -1,7 +1,24 @@
-export const cygxRoutes=[
-    {
-        path:'/raiReportDtl',
-        name:"raiReportDtl",
-        component: () => import("@/views/cygx/raiReportDtl.vue"),
-    },  
-]
+export const cygxRoutes = [
+  {
+    path: "/raiReportDtl",
+    name: "raiReportDtl",
+    component: () => import("@/views/cygx/raiReportDtl.vue"),
+  },
+  {
+    path: "/cygx",
+    name: "cygx",
+    component: () => import("@/App.vue"),
+    children: [
+      {
+        path: "report",
+        name: "report",
+        component: () => import("@/views/cygxPc/report.vue"),
+      },
+      {
+        path: "login",
+        name: "login",
+        component: () => import("@/views/cygxPc/login.vue"),
+      },
+    ],
+  },
+];

+ 274 - 0
src/views/cygxPc/login.vue

@@ -0,0 +1,274 @@
+<script setup>
+import { reactive, onMounted, toRefs, ref, nextTick } from "vue";
+import { useRouter, useRoute } from "vue-router";
+import { RaiApiPc } from "@/api/cygxPc/api.js";
+import { Field, CellGroup, Icon, Button, CountDown, Toast } from "vant";
+const router = useRouter();
+const route = useRoute();
+//获取手机号模块
+const selectOptions = ref([
+  {
+    value: "+86",
+    label: "86",
+  },
+  {
+    value: "+852",
+    label: "852",
+  },
+  {
+    value: "+886",
+    label: "886",
+  },
+  {
+    value: "+1",
+    label: "1",
+  },
+  {
+    value: "+65",
+    label: "65",
+  },
+]);
+const valueMobile = ref("");
+const selectMobileValue = ref("86");
+const isShowMobile = ref(false);
+const dropDownCode = () => {
+  isShowMobile.value = !isShowMobile.value;
+};
+const selectMobileHandle = (val) => {
+  selectMobileValue.value = val;
+  isShowMobile.value = false;
+};
+
+//获取验证码模块
+const smsVerify = ref("");
+const countDownTime = ref(null);
+const smsTime = ref(60 * 1000);
+const isShowSmsTime = ref(false);
+const finishTimeHandler = () => {
+  isShowSmsTime.value = false;
+};
+
+//发送短信验证码
+const startTime = async () => {
+  if (!valueMobile.value) return Toast("手机号不能为空");
+  const res = await RaiApiPc.getPhoneCode({
+    Mobile: valueMobile.value,
+    CountryCode: selectMobileValue.value,
+  });
+  if (res.Ret === 200) {
+    Toast("验证码已发送");
+    countDownTime.value.start();
+    isShowSmsTime.value = true;
+  }
+};
+const submitContactInformation = async () => {
+  if (!valueMobile.value) return Toast("手机号不能为空");
+  if (!smsVerify.value) return Toast("验证码不能为空");
+  const res = await RaiApiPc.Bind({
+    LoginType: 3,
+    Mobile: valueMobile.value,
+    VCode: smsVerify.value,
+    CountryCode: selectMobileValue.value,
+  });
+  if (res.Ret === 200) {
+    localStorage.setItem("cygx_token", res.Data.Authorization);
+    router.back();
+    console.log(localStorage.getItem('cygx_token'));
+  } else {
+    Toast(res.Msg);
+  }
+};
+onMounted(() => {
+});
+</script>
+
+<template>
+  <div class="container-cygx-login">
+    <div class="login-box">
+      <h4>验证码登陆</h4>
+      <p>手机号</p>
+      <div class="mobile">
+        <div class="area-code" @click="dropDownCode">
+          <span> +{{ selectMobileValue }} </span>
+          <Icon name="arrow-down" color="#333333" size="12" />
+          <div class="drop-down">
+            <template v-if="isShowMobile">
+              <span @click.stop="selectMobileHandle(item.label)" :class="['item', selectMobileValue == item.label && 'active']" v-for="item in selectOptions" :key="item.label">{{ item.value }}</span>
+            </template>
+          </div>
+        </div>
+        <div class="mobile-input">
+          <CellGroup>
+            <Field v-model.trim="valueMobile" placeholder="请输入手机号" />
+          </CellGroup>
+        </div>
+      </div>
+      <p>验证码</p>
+      <div class="sms-verification">
+        <CellGroup>
+          <Field v-model.trim="smsVerify" placeholder="请输入验证码" />
+        </CellGroup>
+        <div class="sms-button">
+          <span v-if="!isShowSmsTime" @click="startTime">发送验证码</span>
+          <CountDown ref="countDownTime" :auto-start="false" :time="smsTime" format="ss 秒" @finish="finishTimeHandler" />
+        </div>
+      </div>
+      <div class="login-btn">
+        <Button type="primary" @click="submitContactInformation">验证码登陆</Button>
+      </div>
+    </div>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.container-cygx-login {
+  background: #f5f7f9;
+  width: 100%;
+  height: 100vh;
+  font-size: 14px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  .login-box {
+    width: 591px;
+    background: #ffffff;
+    box-shadow: 0px 0px 12px 0px #e4e7ea;
+    border-radius: 16px;
+    padding: 70px 40px;
+    h4 {
+      font-size: 30px;
+      font-weight: 500;
+      color: #333333;
+    }
+    p {
+      font-size: 24px;
+      font-weight: 400;
+      color: #333333;
+      margin: 35px 0 16px;
+    }
+    .mobile {
+      display: flex;
+      align-items: center;
+      height: 40px;
+      border-radius: 2px;
+      border: 1px solid #d9d9d9;
+      .mobile-input {
+        height: 100%;
+        width: 100%;
+        overflow: hidden;
+      }
+      .area-code {
+        position: relative;
+        width: 72px;
+        height: 100%;
+        line-height: 38px;
+        text-align: center;
+        background: #fafafa;
+        border-right: 1px solid #d9d9d9;
+        cursor: pointer;
+        .drop-down {
+          position: absolute;
+          top: 40px;
+          left: 0;
+          width: 108px;
+          box-shadow: 0px 9px 28px 8px rgba(0, 0, 0, 0.05), 0px 6px 16px 0px rgba(0, 0, 0, 0.08), 0px 3px 6px -4px rgba(0, 0, 0, 0.12);
+          border-radius: 2px;
+          z-index: 99;
+          background-color: #fff;
+          .item {
+            display: block;
+            height: 32px;
+            line-height: 32px;
+            text-indent: 1em;
+            text-align: left;
+            cursor: pointer;
+            &:hover {
+              background-color: #f9f9f9;
+            }
+          }
+          .active {
+            color: #3385ff;
+            background-color: #f5f5f5;
+          }
+        }
+      }
+    }
+    .sms-verification {
+      border: 1px solid #d9d9d9;
+      border-radius: 2px;
+      overflow: hidden;
+      position: relative;
+      .sms-button {
+        position: absolute;
+        cursor: pointer;
+        top: 0;
+        right: 0;
+        width: 112px;
+        height: 40px;
+        background: #1890ff;
+        box-shadow: 0px 2px 0px 0px rgba(0, 0, 0, 0.04);
+        border: 1px solid #1890ff;
+        text-align: center;
+        line-height: 40px;
+        font-size: 16px;
+        color: #fff;
+        .van-count-down {
+          color: #fff;
+          line-height: 40px;
+          font-size: 16px;
+        }
+      }
+    }
+    .login-btn {
+      text-align: center;
+      margin-top: 50px;
+    }
+  }
+  .van-cell-group {
+    height: 40px;
+    width: 100%;
+    line-height: 38px;
+  }
+  .van-cell {
+    padding: 0 20px !important;
+    line-height: 40px;
+  }
+  @media screen and (max-width: 790px) {
+    padding: 10px;
+    .login-box {
+      width: 691px;
+      padding: 30px 20px;
+      h4 {
+        font-size: 22px;
+        text-align: center;
+      }
+      p {
+        font-size: 16px;
+        margin: 25px 0 10px;
+      }
+      .sms-verification {
+        position: relative;
+        .sms-button {
+          position: absolute;
+          top: 0;
+          right: 0;
+          width: 82px;
+          height: 40px;
+          background: #1890ff;
+          box-shadow: 0px 2px 0px 0px rgba(0, 0, 0, 0.04);
+          border: 1px solid #1890ff;
+          text-align: center;
+          line-height: 40px;
+          font-size: 14px;
+          color: #fff;
+          .van-count-down {
+            color: #fff;
+            line-height: 40px;
+            font-size: 14px;
+          }
+        }
+      }
+    }
+  }
+}
+</style>

+ 376 - 0
src/views/cygxPc/report.vue

@@ -0,0 +1,376 @@
+<script setup>
+import { reactive, onMounted, toRefs, ref } from "vue";
+import { useRouter, useRoute } from "vue-router";
+import { Icon, Dialog, Toast } from "vant";
+import { RaiApiPc } from "@/api/cygxPc/api.js";
+
+import dlg from "../cygx/dlg.vue";
+
+const router = useRouter();
+const route = useRoute();
+const state = reactive({
+  reportInfo: {},
+  reportResearch: [],
+});
+const rerportId = ref(null);
+const from_type = ref(null);
+const haveData = ref(false);
+const showTips = ref(false);
+const mobile = ref("");
+/* 获取报告详情 */
+const getReport = (id) => {
+  RaiApiPc.lookReport({
+    ArticleIdMd5: id,
+  }).then((res) => {
+    if (res.Ret === 200) {
+      haveData.value = res.Data.HasPermission === 1 ? true : false;
+      mobile.value = res.Data.Mobile
+      if (res.Data.HasPermission === 1) {
+        //有访问权限
+        state.reportInfo = res.Data.Detail;
+        $(document).on("click", "#report-content img", function (event) {
+          let imgArray = [];
+          let src_tag = $(this).attr("src");
+          let parent_tag = $(this).parent();
+          if (src_tag && !parent_tag.attr("href")) {
+            $("#report-content img").each(function (index, el) {
+              let itemSrc = $(this).attr("src");
+              imgArray.push(itemSrc);
+            });
+            wx.previewImage({ current: src_tag, urls: imgArray });
+          }
+        });
+      }
+    }
+  });
+};
+onMounted(() => {
+  if (localStorage.getItem("cygx_token")) {
+    rerportId.value = route.query.id;
+    getReport(rerportId.value);
+  } else {
+    router.push("/cygx/login");
+  }
+});
+const { reportInfo, reportResearch } = toRefs(state);
+</script>
+
+<template>
+  <div class="container-cygx-pc" v-if="haveData" :class="reportInfo.IsResearch ? 'no-cv' : ''">
+    <div class="z-index-content">
+      <div class="content-top">
+        <div class="report-title">{{ reportInfo.Title }}</div>
+        <div class="report-text">
+          <template v-if="!reportInfo.IsResearch">
+            <div class="report_desc">
+              <span class="author">{{ reportInfo.Department }}</span>
+              <span>{{ reportInfo.PublishDate }}</span>
+            </div>
+            <div class="seller-list">
+              <span>联系人:</span>
+              <span v-for="(item, index) in reportInfo.SellerList" :key="index"> {{ item.SellerName }}({{ item.SellerMobile }})&nbsp;&nbsp; </span>
+            </div>
+          </template>
+          <template v-else>
+            <div class="report-research">
+              <div style="display: flex">
+                <img :src="reportInfo.DepartmentImgUrl" @click="goAuthorPages" />
+                <div class="research-author">
+                  <p @click="goAuthorPages">{{ reportInfo.SellerAndMobile }}</p>
+                  <p class="time">{{ reportInfo.PublishDate }}</p>
+                </div>
+              </div>
+              <div @click="attentionBtn" class="is-follow" :class="reportInfo.IsFollow ? 'follow-cancel' : ''">
+                {{ reportInfo.IsFollow ? "取消关注" : "+ 关注" }}
+              </div>
+            </div>
+          </template>
+          <div>注:请务必阅读<span class="tip" @click="showTips = true"> &nbsp;免责声明</span></div>
+          <div class="container-abstract">&nbsp;&nbsp;摘要:&nbsp;{{ reportInfo.Abstract }}</div>
+        </div>
+      </div>
+      <div class="detail-report" :class="reportInfo.IsResearch ? '' : 'detail-bottom'">
+        <div id="report-content" v-html="reportInfo.Body"></div>
+      </div>
+    </div>
+    <div class="btn-returntop">
+      <img src="~@/assets/cygx/returntop.png" @click="scrolltop" style="width: 40px" />
+    </div>
+    <dlg :showTips="showTips" :reportInfo="reportInfo" @hideDlg="showTips = false" />
+  </div>
+  <div v-else class="nodata-cygx-pc">
+    <div>
+      <img src="https://hzchart.oss-cn-shanghai.aliyuncs.com/cygx/czbk/act_search.png" alt="" />
+      <div>
+        <span>{{ mobile }}</span>
+        <p>您暂无权限查看【买方研选】的报告内容</p>
+      </div>
+    </div>
+  </div>
+</template>
+
+<style lang="scss">
+.container-cygx-pc {
+  @media screen and (min-width: 790px) {
+    width: 1200px;
+    margin: 0 auto;
+  }
+  padding: 20px;
+  position: relative;
+  z-index: 5;
+  .z-index-content {
+    position: relative;
+    z-index: 5;
+  }
+  .host-collect {
+    margin-top: 10px;
+    padding-bottom: 50px;
+    padding-bottom: calc(50px + constant(safe-area-inset-bottom));
+    padding-bottom: calc(50px + env(safe-area-inset-bottom));
+    h4 {
+      font-size: 14px;
+    }
+
+    background-color: #fff;
+    .host-content {
+      border-top: 1px solid #ececec;
+      .host-title {
+        margin: 15px 0;
+        color: #333;
+        font-size: 14px;
+        font-weight: 500;
+      }
+      .item-more {
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        color: #cecece;
+        font-size: 12px;
+        margin-bottom: 15px;
+      }
+      .pv-ollect {
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        img {
+          width: 10px;
+          height: 10px;
+          margin-left: 5px;
+        }
+        .pv {
+          height: 8px;
+        }
+      }
+    }
+  }
+  .search {
+    width: 100%;
+    padding: 10;
+    line-height: 35px;
+    position: fixed;
+    top: 0;
+    left: 0;
+    background: #fff;
+    z-index: 9;
+
+    .search-box {
+      display: flex;
+      align-items: center;
+      padding-left: 10px;
+      width: 100%;
+      height: 35px;
+      border-radius: 18px;
+      background: #f6f6f6;
+      color: #8d8d8d;
+      font-size: 12px;
+    }
+  }
+  .content-top {
+    .report-research {
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      font-size: 14px;
+      font-weight: 500;
+      color: #333;
+      margin-bottom: 10px;
+
+      img {
+        width: 41px;
+        height: 41px;
+        overflow: hidden;
+        margin-right: 15px;
+      }
+      .time {
+        font-size: 12px;
+        color: #999999;
+        font-weight: 300;
+      }
+      .is-follow {
+        padding: 3px 14px;
+        background-color: #3385ff;
+        border-radius: 39px;
+        color: #fff;
+      }
+      .follow-cancel {
+        background: #f0f0f0;
+        color: #999999;
+      }
+    }
+
+    .report-title {
+      font-size: 17px;
+      font-weight: bold;
+      color: #4a4a4a;
+      margin: 0px 0 10px;
+    }
+    .report-text {
+      color: #999999;
+      font-size: 14px;
+
+      .seller-list {
+        margin: 10px 0;
+      }
+      .report_desc {
+        display: flex;
+        justify-content: space-between;
+      }
+      .tip {
+        color: #3385ff;
+      }
+      .container-abstract {
+        margin: 20px 0 10px;
+        padding-bottom: 20px;
+        border-bottom: 1px dashed #999;
+        position: relative;
+        line-height: 22px;
+        color: #333;
+        &::before {
+          content: "";
+          position: absolute;
+          top: 0;
+          left: 0;
+          width: 4px;
+          height: 22px;
+          background: #2a65f5;
+        }
+      }
+    }
+  }
+  .report-link {
+    font-size: 14px;
+    line-height: 40px;
+  }
+  .detail-report {
+    p,
+    span {
+      font-size: 14px !important;
+    }
+    img {
+      width: 100% !important;
+    }
+    a {
+      color: #333;
+    }
+    table {
+      border-collapse: collapse;
+      width: 100% !important;
+      margin-left: 0 !important;
+    }
+    tr td,
+    th {
+      border: 1px solid #333;
+    }
+  }
+  pre {
+    width: 100%;
+    overflow-y: auto;
+    overflow-x: hidden;
+    outline: none;
+    border: 0;
+    white-space: pre-wrap;
+    word-break: normal;
+  }
+  .btn-returntop {
+    position: fixed;
+    right: 20px;
+    bottom: 150px;
+    width: 44px;
+    height: 44px;
+    z-index: 10;
+  }
+  .fixed_cont {
+    position: fixed;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    display: flex;
+    justify-content: space-around;
+    border-top: 1px solid #ddd;
+    padding-bottom: calc(5px + constant(safe-area-inset-bottom));
+    padding-bottom: calc(5px + env(safe-area-inset-bottom));
+    background-color: #fff;
+    z-index: 9;
+    box-sizing: border-box;
+    .handle-item {
+      padding-top: 7px;
+      text-align: center;
+      line-height: 17px;
+      font-size: 12px;
+      color: #888888;
+
+      img {
+        width: 22px;
+        height: 22px;
+        padding: 0;
+        margin: 0;
+      }
+      div {
+        padding: 0;
+        margin: 0;
+      }
+    }
+  }
+  .btn-freecharge {
+    position: fixed;
+    right: 10px;
+    bottom: 190px;
+    z-index: 10;
+    .image {
+      width: 78px;
+      height: 78px;
+    }
+    .remove-icon {
+      width: 16px;
+      height: 16px;
+      position: absolute;
+      right: 0;
+      top: 0;
+    }
+  }
+}
+.nodata-cygx-pc {
+  width: 100%;
+  height: 100vh;
+  text-align: center;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  img {
+    width: 260px;
+    height: 200px;
+  }
+  span {
+    color: #3385ff;
+  }
+  p {
+    margin-top: 20px;
+    color: #666666;
+  }
+  @media screen and (min-width: 790px) {
+    width: 1200px;
+    margin: 0 auto;
+    font-size: 24px;
+  }
+}
+</style>