浏览代码

Merge branch 'yb6.0'

Karsa 2 年之前
父节点
当前提交
09acc4bacf
共有 6 个文件被更改,包括 667 次插入7 次删除
  1. 26 0
      src/api/priceDriven.js
  2. 二进制
      src/assets/pricedriven/new_ico.png
  3. 二进制
      src/assets/pricedriven/nodata.png
  4. 7 7
      src/layout/component/Aside.vue
  5. 22 0
      src/router/index.js
  6. 612 0
      src/views/priceDriven/detail.vue

+ 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)
+}

二进制
src/assets/pricedriven/new_ico.png


二进制
src/assets/pricedriven/nodata.png


+ 7 - 7
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,
     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,
     name: "活动",

+ 22 - 0
src/router/index.js

@@ -248,6 +248,28 @@ 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: '/:pathMatch(.*)',
     name: 'error',

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