2 Komitmen fc84c48d25 ... 5c5816adad

Pembuat SHA1 Pesan Tanggal
  wangzs 5c5816adad Merge branch 'dev' of http://59.110.6.97:3000/root/BoundLink-Plate-UI into dev 4 bulan lalu
  wangzs 7437a566ec feat: 营销工作台 4 bulan lalu
1 mengubah file dengan 706 tambahan dan 0 penghapusan
  1. 706 0
      src/views/marketing-workbench/index.vue

+ 706 - 0
src/views/marketing-workbench/index.vue

@@ -0,0 +1,706 @@
+<template>
+  <div class="home-container" ref="rootRef">
+    <div class="top">
+      <div class="top-left">
+        <img :src="headerIcon">
+        <span>营销门户</span>
+      </div>
+      <a-space>
+        <a-button type="primary" size="small">管理工作台</a-button>
+        <a-button type="primary" size="small" ghost>业务表单</a-button>
+        <a-button type="primary" size="small" ghost>集成关系图</a-button>
+      </a-space>
+    </div>
+    <div class="center">
+      <div class="center-item">
+        <div class="item-title">
+          <div class="item-title-box">
+            <img :src="scghIcon">
+            <span>市场规划</span>
+          </div>
+        </div>
+        <div class="center-item-content">
+          <SquareListRender class="item-render" ratioVariable="--fitWidthRatio" :templateCondition="centerSquare1" />
+        </div>
+      </div>
+      <div class="center-item">
+        <div class="item-title">
+          <div class="item-title-box">
+            <img :src="yxgcIcon">
+            <span>营销过程</span>
+          </div>
+        </div>
+        <div class="center-item-content special">
+          <div class="special-left">
+            <div class="special-header">
+              <img :src="specialHeaderIcon">
+              <span>营销管理</span>
+            </div>
+          </div>
+          <div class="special-right">
+            <div class="special-right-container">
+              <div class="item-line" v-for="(item, index) in centerSquare2" :key="index">
+                <template v-for="(el, elIdx) in item" :key="el.title">
+                  <div class="line-item" v-if="elIdx > 0" @click="goLink(el.link)">
+                    <span>{{ el.title }}</span>
+                    <ArrowRightOutlined class="item-icon" />
+                  </div>
+                  <div class="line-item-first" v-else @click="goLink(el.link)">
+                    <span>{{ el.title }}</span>
+                  </div>
+                </template>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="center-item">
+        <div class="item-title">
+          <div class="item-title-box">
+            <img :src="swtbIcon">
+            <span>商务投标</span>
+          </div>
+        </div>
+        <div class="center-item-content">
+          <SquareListRender class="item-render" ratioVariable="--fitWidthRatio" v-for="(item, index) in centerSquare3"
+            :key="index" :templateCondition="item" />
+        </div>
+      </div>
+      <div class="center-item">
+        <div class="item-title">
+          <div class="item-title-box">
+            <img :src="htlyIcon">
+            <span>合同履约</span>
+          </div>
+        </div>
+        <div class="center-item-content">
+          <SquareListRender class="item-render" ratioVariable="--fitWidthRatio" :templateCondition="centerSquare4" />
+        </div>
+      </div>
+    </div>
+    <div class="bottom">
+      <div class="bottom-header">
+        <span>支撑管理</span>
+      </div>
+      <div class="bottom-content">
+        <div class="content-item" v-for="item in bottomCondition" :key="item.title" @click="goLink(item.link)">
+          <img :src="item.icon">
+          <span>{{ item.title }}</span>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+// 头部-icon---------------------------------------------------------------
+import headerIcon from '/@/assets/images/marketing/home/header-icon.png';
+import scghIcon from '/@/assets/images/marketing/home/scgh-icon.png';
+import yxgcIcon from '/@/assets/images/marketing/home/yxgc-icon.png';
+import swtbIcon from '/@/assets/images/marketing/home/swtb-icon.png';
+import htlyIcon from '/@/assets/images/marketing/home/htly-icon.png';
+// 中心-back---------------------------------------------------------------
+import specialHeaderIcon from '/@/assets/images/marketing/home/special-header-icon.png';
+// 底部-icon---------------------------------------------------------------
+import yxjscIcon from '/@/assets/images/marketing/home/yxjsc-icon.png';
+import yxbbIcon from '/@/assets/images/marketing/home/yxbb-icon.png';
+import yxmbIcon from '/@/assets/images/marketing/home/yxmb-icon.png';
+import tbglIcon from '/@/assets/images/marketing/home/tbgl-icon.png';
+import bzjglIcon from '/@/assets/images/marketing/home/bzjgl-icon.png';
+import jyptIcon from '/@/assets/images/marketing/home/jypt-icon.png';
+import bgglIcon from '/@/assets/images/marketing/home/bggl-icon.png';
+import flzcIcon from '/@/assets/images/marketing/home/flzc-icon.png';
+import fxgkIcon from '/@/assets/images/marketing/home/fxgk-icon.png';
+// ------------------------------------------------------------------------
+import { ref, onMounted, onUnmounted } from 'vue';
+import SquareListRender from '/@/components/common/modules-home/square-list-render.vue';
+
+import { theme, message } from 'ant-design-vue';
+
+const { useToken } = theme;
+const { token } = useToken();
+const borderRadius = token.value.borderRadius + 'px';
+
+const bottomCondition = ref([
+  {
+    title: '营销驾驶舱',
+    icon: yxjscIcon,
+    link: '',
+  },
+  {
+    title: '营销报表',
+    icon: yxbbIcon,
+    link: '',
+  },
+  {
+    title: '营销目标',
+    icon: yxmbIcon,
+    link: '',
+  },
+  {
+    title: '投标管理',
+    icon: tbglIcon,
+    link: '',
+  },
+  {
+    title: '保证金管理',
+    icon: bzjglIcon,
+    link: '',
+  },
+  {
+    title: '交易平台',
+    icon: jyptIcon,
+    link: '',
+  },
+  {
+    title: '报告管理',
+    icon: bgglIcon,
+    link: '',
+  },
+  {
+    title: '法律政策',
+    icon: flzcIcon,
+    link: '',
+  },
+  {
+    title: '风险管控',
+    icon: fxgkIcon,
+    link: '',
+  }
+]);
+
+const centerSquare1 = [
+  {
+    title: '市场管理',
+    link: '',
+  },
+  {
+    title: '生态合作申请',
+    link: '',
+  },
+  {
+    title: '生态合作管理',
+    link: '',
+  },
+  {
+    title: '生态合作分析',
+    link: '',
+  },
+  {
+    title: '生态合作创建',
+    link: '',
+  },
+  {
+    title: '生态计划管理',
+    link: '',
+  },
+  {
+    title: '市场计划分析',
+    link: '',
+  },
+];
+const centerSquare2 = [
+  [
+    {
+      title: '客户管理',
+      link: '',
+    },
+    {
+      title: '客户创建',
+      link: '',
+    },
+    {
+      title: '客户跟进',
+      link: '',
+    },
+    {
+      title: '客户维护',
+      link: '',
+    },
+    {
+      title: '客户分析',
+      link: '',
+    },
+  ],
+  [
+    {
+      title: '线索跟进',
+      link: '',
+    },
+    {
+      title: '线索创建',
+      link: '',
+    },
+    {
+      title: '线索管理',
+      link: '',
+    },
+    {
+      title: '线索分析',
+      link: '',
+    },
+  ],
+  [
+    {
+      title: '商机维护',
+      link: '',
+    },
+    {
+      title: '商机创建',
+      link: '',
+    },
+    {
+      title: '商机管理',
+      link: '',
+    },
+    {
+      title: '商机分析',
+      link: '',
+    },
+  ],
+];
+const centerSquare3 = [
+  [
+    {
+      title: '项目立项',
+      link: '',
+    },
+    {
+      title: '立项创建',
+      link: '',
+    },
+    {
+      title: '立项管理',
+      link: '',
+    },
+    {
+      title: '立项分析',
+      link: '',
+    },
+  ],
+  [
+    {
+      title: '商务谈判',
+      link: '',
+    },
+    {
+      title: '报价管理',
+      link: '',
+    },
+    {
+      title: '在投',
+      link: '',
+    },
+    {
+      title: '已投未定',
+      link: '',
+    },
+    {
+      title: '项目终止',
+      link: '',
+    },
+  ],
+  [
+    {
+      title: '合同管理',
+      link: '',
+    },
+    {
+      title: '合同发起',
+      link: '',
+    },
+    {
+      title: '合同管理',
+      link: '',
+    },
+    {
+      title: '合同归档',
+      link: '',
+    },
+  ],
+];
+const centerSquare4 = [
+  {
+    title: '履约管理',
+    link: '',
+  },
+  {
+    title: '履约执行',
+    link: '',
+  },
+  {
+    title: '履约关闭',
+    link: '',
+  },
+  {
+    title: '履约分析',
+    link: '',
+  },
+];
+
+function goLink(link) {
+    if (!link) {
+        message.warning('暂未开放');
+        return;
+    }
+    router.push({
+        path: link,
+    });
+}
+
+// ---------------- 适配屏幕缩放 ----------------
+const rootRef = ref(null);
+
+function reduceRatio() {
+  handleResize();
+  window.addEventListener('resize', handleResize);
+}
+
+function handleResize() {
+  const ratio = window.innerWidth / 1920;
+  rootRef.value.style.setProperty('--fitWidthRatio', ratio);
+}
+
+onMounted(() => {
+  reduceRatio();
+});
+
+onUnmounted(() => {
+  window.removeEventListener('resize', handleResize);
+});
+
+</script>
+
+<style lang="less" scoped>
+.home-container {
+  --fitWidthRatio: 1; // 1920px
+  font-size: calc(var(--fitWidthRatio) * 16px); // 页面默认字体大小
+
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+  height: calc(100vh - 102px);
+
+  .top {
+    height: calc(var(--fitWidthRatio) * 30px);
+
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+
+    .top-left {
+      display: flex;
+      align-items: center;
+      gap: 6px;
+
+      img {
+        width: calc(var(--fitWidthRatio) * 28px);
+        height: 100%;
+      }
+
+      span {
+        color: v-bind("token.colorPrimary");
+        font-size: calc(var(--fitWidthRatio) * 20px);
+        font-weight: 600;
+        margin-bottom: 6px;
+      }
+    }
+  }
+
+  .center {
+    flex: 1;
+    display: flex;
+    gap: calc(var(--fitWidthRatio) * 10px);
+    position: relative;
+    min-height: calc(var(--fitWidthRatio) * 570px);
+    max-height: calc(var(--fitWidthRatio) * 595px);
+    overflow: hidden;
+
+    &::before {
+      content: '';
+      position: absolute;
+      top: calc(var(--fitWidthRatio) * 61px);
+      left: 50%;
+      transform: translateX(-50%);
+      width: 90%;
+      z-index: 1;
+      border-bottom: calc(var(--fitWidthRatio) * 2px) dashed v-bind("token.colorPrimary");
+    }
+
+    .center-item {
+      width: calc(var(--fitWidthRatio) * 188px);
+      background-color: #fff;
+      border-radius: calc(var(--fitWidthRatio) * v-bind(borderRadius));
+      padding: calc(var(--fitWidthRatio) * 30px) calc(var(--fitWidthRatio) * 10px) calc(var(--fitWidthRatio) * 10px);
+      position: relative;
+
+      display: flex;
+      flex-direction: column;
+      gap: calc(var(--fitWidthRatio) * 30px);
+
+      &:nth-child(2) {
+        flex: 1.5;
+      }
+
+      &:nth-child(3) {
+        flex: 1;
+      }
+
+      &:not(:last-child) {
+        & .item-title::after {
+          content: '';
+          position: absolute;
+          top: 50%;
+          right: calc(var(--fitWidthRatio) * -8px);
+          transform: translateY(-50%);
+          width: calc(var(--fitWidthRatio) * 8px);
+          height: calc(var(--fitWidthRatio) * 8px);
+          border-radius: 50%;
+          background-color: v-bind("token.colorPrimary");
+        }
+      }
+
+      .center-item-content {
+        flex: 1;
+
+        display: flex;
+        gap: 10px;
+
+        .item-render {
+          flex: 1;
+        }
+
+      }
+
+      .special {
+        overflow: hidden;
+        background: url('/@/assets/images/marketing/home/round-line.png');
+        background-size: contain;
+        background-repeat: no-repeat;
+        background-position: 0 calc(var(--fitWidthRatio) * 20%);
+        margin-bottom: calc(var(--fitWidthRatio) * 40px);
+
+        display: flex;
+        gap: calc(var(--fitWidthRatio) * 60px);
+
+        .special-left {
+          position: relative;
+          flex: 1;
+
+
+          .special-header {
+
+            position: absolute;
+            left: 35%;
+            top: 50%;
+            transform: translateY(-50%);
+
+            width: calc(var(--fitWidthRatio) * 120px);
+            height: calc(var(--fitWidthRatio) * 120px);
+            border-radius: 50%;
+            background-color: #e0eeff;
+            box-shadow: 2px 4px 12px 0px #0338871A;
+            display: flex;
+            flex-direction: column;
+            justify-content: center;
+            align-items: center;
+            gap: calc(var(--fitWidthRatio) * 10px);
+
+            img {
+              width: calc(var(--fitWidthRatio) * 40px);
+              height: calc(var(--fitWidthRatio) * 40px);
+            }
+
+            span {
+              font-size: calc(var(--fitWidthRatio) * 16px);
+              font-weight: 500;
+              color: #1D2129;
+            }
+          }
+        }
+
+        .special-right {
+          flex: 4;
+          min-width: 320px;
+
+          .special-right-container {
+            height: 100%;
+            display: flex;
+            flex-direction: column;
+            justify-content: space-between;
+            gap: calc(var(--fitWidthRatio) * 20px);
+            padding: calc(var(--fitWidthRatio) * 30px) 0;
+
+            .item-line {
+              display: flex;
+              align-items: center;
+              gap: calc(var(--fitWidthRatio) * 10px);
+              background: linear-gradient(90deg, #f5f5f5 0%, #fff 80%);
+              border-top-left-radius: 50px;
+              border-bottom-left-radius: 50px;
+
+              &:nth-child(2) {
+                transform: translateX(calc(var(--fitWidthRatio) * 60px));
+              }
+
+              .line-item-first {
+                width: calc(var(--fitWidthRatio) * 72px);
+                height: calc(var(--fitWidthRatio) * 72px);
+                border-radius: 50%;
+                background: linear-gradient(180deg, #38adff 0%, #2785ff 50%, #175fff 100%);
+
+                display: flex;
+                justify-content: center;
+                align-items: center;
+                
+                span {
+                  padding: 0 calc(var(--fitWidthRatio) * 14px);
+                  font-size: calc(var(--fitWidthRatio) * 16px);
+                  font-weight: 500;
+                  color: #fff;
+                  text-align: center;
+                }
+              }
+
+              .line-item {
+                display: flex;
+                justify-content: center;
+                align-items: center;
+                padding: calc(var(--fitWidthRatio) * 10px) calc(var(--fitWidthRatio) * 10px);
+                border: 1px solid v-bind("token.colorLinkHover");
+                border-radius: calc(var(--fitWidthRatio) * v-bind(borderRadius));
+
+                display: flex;
+                align-items: center;
+                justify-content: center;
+                gap: calc(var(--fitWidthRatio) * 4px);
+
+                span {
+                  white-space: nowrap;
+                  font-size: calc(var(--fitWidthRatio) * 14px);
+                  text-align: center;
+                }
+
+                &:hover:not(:nth-child(1)) {
+                  cursor: pointer;
+                  background-color: #d6e9ff;
+                  box-shadow: 0 calc(var(--xxx) * 4px) calc(var(--xxx) * 10px) 0 rgba(0, 0, 0, 0.1);
+                }
+              }
+            }
+          }
+        }
+      }
+
+      &:not(:first-child) {
+        & .item-title::before {
+          content: '';
+          position: absolute;
+          top: 43%;
+          left: calc(var(--fitWidthRatio) * -7px);
+          transform: translateY(-50%);
+          width: calc(var(--fitWidthRatio) * 8px);
+          height: calc(var(--fitWidthRatio) * 8px);
+          border-top: calc(var(--fitWidthRatio) * 2px) dashed v-bind("token.colorPrimary");
+          border-right: calc(var(--fitWidthRatio) * 2px) dashed v-bind("token.colorPrimary");
+          transform: rotate(45deg);
+          background-color: #fff;
+        }
+      }
+
+      .item-title {
+        position: relative;
+        z-index: 1;
+
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        padding: 0 calc(var(--fitWidthRatio) * 12px);
+        background-color: #fff;
+        // width: calc(var(--fitWidthRatio) * 152px);
+        white-space: nowrap;
+        margin: 0 auto;
+
+        .item-title-box {
+          display: flex;
+          align-items: center;
+          gap: calc(var(--fitWidthRatio) * 10px);
+          border: calc(var(--fitWidthRatio) * 2px) dashed #E5E6EB;
+          padding: calc(var(--fitWidthRatio) * 10px);
+          border-radius: calc(var(--fitWidthRatio) * v-bind(borderRadius));
+
+          img {
+            width: calc(var(--fitWidthRatio) * 40px);
+            height: calc(var(--fitWidthRatio) * 40px);
+          }
+
+          span {
+            font-size: calc(var(--fitWidthRatio) * 16px);
+            color: v-bind("token.colorPrimary");
+            font-weight: 600;
+          }
+        }
+      }
+    }
+  }
+
+  .bottom {
+    height: calc(var(--fitWidthRatio) * 200px);
+    background-color: #fff;
+    border-radius: calc(var(--fitWidthRatio) * v-bind(borderRadius));
+    padding: calc(var(--fitWidthRatio) * 14px) calc(var(--fitWidthRatio) * 10px);
+
+    display: flex;
+    flex-direction: column;
+    gap: calc(var(--fitWidthRatio) * 20px);
+
+    .bottom-header {
+      span {
+        font-size: calc(var(--fitWidthRatio) * 16px);
+        font-weight: 500;
+        color: #1D2129;
+      }
+    }
+
+    .bottom-content {
+      flex: 1;
+
+      display: flex;
+      // align-items: center;
+      gap: calc(var(--fitWidthRatio) * 30px);
+      padding: calc(var(--fitWidthRatio) * 10px) calc(var(--fitWidthRatio) * 10px) calc(var(--fitWidthRatio) * 10px) calc(var(--fitWidthRatio) * 40px);
+
+      .content-item {
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        gap: calc(var(--fitWidthRatio) * 10px);
+
+        cursor: pointer;
+        padding: calc(var(--fitWidthRatio) * 10px);
+        border-radius: calc(var(--fitWidthRatio) * v-bind(borderRadius));
+
+        &:hover {
+          background-color: v-bind('token.colorPrimaryBg');
+          box-shadow: 0 calc(var(--fitWidthRatio) * 4px) calc(var(--fitWidthRatio) * 8px) 0 rgba(0, 0, 0, 0.1);
+        }
+        
+        img {
+          width: calc(var(--fitWidthRatio) * 56px);
+          height: calc(var(--fitWidthRatio) * 56px);
+          background-color: #F7F8FA;
+          border-radius: calc(var(--fitWidthRatio) * v-bind(borderRadius));
+        }
+
+        span {
+          font-size: calc(var(--fitWidthRatio) * 14px);
+          font-weight: 400;
+          color: #4E5969;
+          width: calc(var(--fitWidthRatio) * 60px);
+          text-align: center;
+        }
+      }
+    }
+  }
+}
+</style>