hanxiaohui 6 месяцев назад
Родитель
Сommit
811a5ddc3b

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
src/assets/iconfont/iconfont.js


+ 82 - 0
src/hooks/useFullscreen.js

@@ -0,0 +1,82 @@
+import { onMounted, onUnmounted, ref } from 'vue';
+
+export const useFullscreen = (target) => {
+  const isFullscreen = ref(false);
+  let element = target;
+
+  // 处理不同浏览器的前缀
+  const getFullscreenElement = () => {
+    if (document.fullscreenElement) return true;
+    if (document.webkitFullscreenElement) return true;
+    if (document.mozFullScreenElement) return true;
+    if (document.msFullscreenElement) return true;
+    return false;
+  };
+
+  // 进入全屏
+  const enter = async () => {
+    if (!element) element = document.documentElement;
+
+    try {
+      if (element.requestFullscreen) {
+        await element.requestFullscreen();
+      } else if (element.webkitRequestFullscreen) {
+        await element.webkitRequestFullscreen();
+      } else if (element.mozRequestFullScreen) {
+        await element.mozRequestFullScreen();
+      } else if (element.msRequestFullscreen) {
+        await element.msRequestFullscreen();
+      }
+      isFullscreen.value = true;
+    } catch (error) {
+      console.error('全屏请求失败:', error);
+    }
+  };
+
+  // 退出全屏
+  const exit = () => {
+    if (document.exitFullscreen) {
+      document.exitFullscreen();
+    } else if (document.webkitExitFullscreen) {
+      document.webkitExitFullscreen();
+    } else if (document.mozCancelFullScreen) {
+      document.mozCancelFullScreen();
+    } else if (document.msExitFullscreen) {
+      document.msExitFullscreen();
+    }
+    isFullscreen.value = false;
+  };
+
+  // 切换全屏状态
+  const toggle = () => {
+    isFullscreen.value ? exit() : enter();
+  };
+
+  // 事件处理器
+  const handleFullscreenChange = () => {
+    isFullscreen.value = getFullscreenElement();
+  };
+
+  // 设置事件监听
+  onMounted(() => {
+    document.addEventListener('fullscreenchange', handleFullscreenChange);
+    document.addEventListener('webkitfullscreenchange', handleFullscreenChange);
+    document.addEventListener('mozfullscreenchange', handleFullscreenChange);
+    document.addEventListener('MSFullscreenChange', handleFullscreenChange);
+  });
+
+  // 清除事件监听
+  onUnmounted(() => {
+    document.removeEventListener('fullscreenchange', handleFullscreenChange);
+    document.removeEventListener('webkitfullscreenchange', handleFullscreenChange);
+    document.removeEventListener('mozfullscreenchange', handleFullscreenChange);
+    document.removeEventListener('MSFullscreenChange', handleFullscreenChange);
+  });
+
+  return {
+    isFullscreen,
+    enter,
+    exit,
+    toggle,
+  };
+};

+ 206 - 180
src/views/customer-manage/customer-detail/components/LinkCompany/compoents/OrgStructChart/index.vue

@@ -1,20 +1,21 @@
 <template>
-  <div ref="containerRef" class="org-chart-container" />
+  <div ref="containerRef" class="org-chart-container" id="org-chart-container" />
 </template>
 
 <script>
-import { ref, onMounted, onBeforeUnmount } from 'vue'
-import { Graph, Node, Point } from '@antv/x6'
+  import { ref, onMounted, onBeforeUnmount } from 'vue';
+  import { Graph, Node, Point } from '@antv/x6';
+  import {useFullscreen} from "/@/hooks/useFullscreen.js";
 
-export default {
-  name: 'OrgChart',
-  setup() {
-    const containerRef = ref(null)
-    let graph = null
+  export default {
+    name: 'OrgChart',
+    setup() {
+      const containerRef = ref(null);
+      let graph = null;
 
-    // 注册节点和边的类型
-    const registerChartElements = () => {
-      Graph.registerNode(
+      // 注册节点和边的类型
+      const registerChartElements = () => {
+        Graph.registerNode(
           'org-node',
           {
             width: 180,
@@ -75,9 +76,9 @@ export default {
             },
           },
           true
-      )
+        );
 
-      Graph.registerEdge(
+        Graph.registerEdge(
           'org-edge',
           {
             zIndex: -1,
@@ -93,191 +94,216 @@ export default {
             },
           },
           true
-      )
-    }
+        );
+      };
 
-    // 创建节点
-    const createNode = (x, y, rank, name, image) => {
-      return graph.addNode({
-        x,
-        y,
-        shape: 'org-node',
-        attrs: {
-          avatar: {
-            opacity: 0.7,
-            // 'xlink:href': image,
+      // 创建节点
+      const createNode = (x, y, rank, name, image) => {
+        return graph.addNode({
+          x,
+          y,
+          shape: 'org-node',
+          attrs: {
+            avatar: {
+              opacity: 0.7,
+              // 'xlink:href': image,
+            },
+            rank: {
+              text: rank,
+              wordSpacing: '-5px',
+              letterSpacing: 0,
+            },
+            name: {
+              text: name,
+              fontSize: 13,
+              fontFamily: 'Arial',
+              letterSpacing: 0,
+            },
+          },
+          // 禁用节点拖动
+          movable: false,
+        });
+      };
+
+      // 创建连线
+      const createLink = (source, target, vertices) => {
+        return graph.addEdge({
+          vertices,
+          source: {
+            cell: source,
           },
-          rank: {
-            text: rank,
-            wordSpacing: '-5px',
-            letterSpacing: 0,
+          target: {
+            cell: target,
           },
-          name: {
-            text: name,
-            fontSize: 13,
-            fontFamily: 'Arial',
-            letterSpacing: 0,
+          shape: 'org-edge',
+          // 禁用连线拖动
+          connector: {
+            name: 'normal',
+            args: {
+              style: {
+                pointerEvents: 'none',
+              },
+            },
           },
-        },
-        // 禁用节点拖动
-        movable: false,
-      })
-    }
-
-    // 创建连线
-    const createLink = (source, target, vertices) => {
-      return graph.addEdge({
-        vertices,
-        source: {
-          cell: source,
-        },
-        target: {
-          cell: target,
-        },
-        shape: 'org-edge',
-        // 禁用连线拖动
-        connector: {
-          name: 'normal',
-          args: {
-            style: {
+          // 禁用连线调整
+          router: {
+            name: 'manhattan',
+            args: {
+              padding: 10,
+            },
+          },
+          attrs: {
+            line: {
+              // 禁止选中连线
               pointerEvents: 'none',
             },
           },
-        },
-        // 禁用连线调整
-        router: {
-          name: 'manhattan',
-          args: {
-            padding: 10,
+        });
+      };
+
+      // 初始化图表
+      const initChart = () => {
+        if (!containerRef.value) return;
+
+        // 创建图表实例
+        graph = new Graph({
+          container: containerRef.value,
+          connecting: {
+            anchor: 'orth',
+          },
+          // 禁用鼠标滚轮缩放
+          mousewheel: {
+            enabled: true,
           },
-        },
-        attrs: {
-          line: {
-            // 禁止选中连线
-            pointerEvents: 'none',
+          // 禁用平移
+          panning: true,
+          // 禁用框选
+          selecting: {
+            enabled: false,
           },
-        },
-      })
-    }
+          interacting: {
+            nodeMovable: false,
+            edgeMovable: false,
+          },
+        });
 
-    // 初始化图表
-    const initChart = () => {
-      if (!containerRef.value) return
+        // 图表数据
+        const male = 'https://gw.alipayobjects.com/mdn/rms_43231b/afts/img/A*kUy8SrEDp6YAAAAAAAAAAAAAARQnAQ';
+        const female = 'https://gw.alipayobjects.com/mdn/rms_43231b/afts/img/A*f6hhT75YjkIAAAAAAAAAAAAAARQnAQ';
 
-      // 创建图表实例
-      graph = new Graph({
-        container: containerRef.value,
-        connecting: {
-          anchor: 'orth',
-        },
-        // 禁用鼠标滚轮缩放
-        mousewheel: {
-          enabled: true,
-        },
-        // 禁用平移
-        panning: true,
-        // 禁用框选
-        selecting: {
-          enabled: false,
-        },
-        interacting: {
-          nodeMovable: false,
-          edgeMovable: false,
-        },
-      })
+        // 创建节点
+        const bart = createNode(300, 70, 'CEO', 'Bart Simpson', male);
+        const homer = createNode(90, 200, 'VP Marketing', 'Homer Simpson', male);
+        const marge = createNode(300, 200, 'VP Sales', 'Marge Simpson', female);
+        const lisa = createNode(500, 200, 'VP Production', 'Lisa Simpson', female);
+        const maggie = createNode(400, 350, 'Manager', 'Maggie Simpson', female);
+        const lenny = createNode(190, 350, 'Manager', 'Lenny Leonard', male);
+        const carl = createNode(190, 500, 'Manager', 'Carl Carlson', male);
 
-      // 图表数据
-      const male =
-          'https://gw.alipayobjects.com/mdn/rms_43231b/afts/img/A*kUy8SrEDp6YAAAAAAAAAAAAAARQnAQ'
-      const female =
-          'https://gw.alipayobjects.com/mdn/rms_43231b/afts/img/A*f6hhT75YjkIAAAAAAAAAAAAAARQnAQ'
+        // 创建连线
+        createLink(bart, marge, [
+          {
+            x: 385,
+            y: 180,
+          },
+        ]);
+        createLink(bart, homer, [
+          {
+            x: 385,
+            y: 180,
+          },
+          {
+            x: 175,
+            y: 180,
+          },
+        ]);
+        createLink(bart, lisa, [
+          {
+            x: 385,
+            y: 180,
+          },
+          {
+            x: 585,
+            y: 180,
+          },
+        ]);
+        createLink(homer, lenny, [
+          {
+            x: 175,
+            y: 380,
+          },
+        ]);
+        createLink(homer, carl, [
+          {
+            x: 175,
+            y: 530,
+          },
+        ]);
+        createLink(marge, maggie, [
+          {
+            x: 385,
+            y: 380,
+          },
+        ]);
 
-      // 创建节点
-      const bart = createNode(300, 70, 'CEO', 'Bart Simpson', male)
-      const homer = createNode(90, 200, 'VP Marketing', 'Homer Simpson', male)
-      const marge = createNode(300, 200, 'VP Sales', 'Marge Simpson', female)
-      const lisa = createNode(500, 200, 'VP Production', 'Lisa Simpson', female)
-      const maggie = createNode(400, 350, 'Manager', 'Maggie Simpson', female)
-      const lenny = createNode(190, 350, 'Manager', 'Lenny Leonard', male)
-      const carl = createNode(190, 500, 'Manager', 'Carl Carlson', male)
+        // 调整视图以适应所有节点
+        graph.zoomToFit({ padding: 20, maxScale: 1 });
+      };
 
-      // 创建连线
-      createLink(bart, marge, [
-        {
-          x: 385,
-          y: 180,
-        },
-      ])
-      createLink(bart, homer, [
-        {
-          x: 385,
-          y: 180,
-        },
-        {
-          x: 175,
-          y: 180,
-        },
-      ])
-      createLink(bart, lisa, [
-        {
-          x: 385,
-          y: 180,
-        },
-        {
-          x: 585,
-          y: 180,
-        },
-      ])
-      createLink(homer, lenny, [
-        {
-          x: 175,
-          y: 380,
-        },
-      ])
-      createLink(homer, carl, [
-        {
-          x: 175,
-          y: 530,
-        },
-      ])
-      createLink(marge, maggie, [
-        {
-          x: 385,
-          y: 380,
-        },
-      ])
+      const zoomIn = () => {
+        const currentZoom = graph.zoom();
+        console.log('currentZoom', currentZoom);
+        graph.zoomTo(currentZoom + 0.1, { animation: true }); // 带动画放大
+      };
+
+      const zoomOut = () => {
+        const currentZoom = graph.zoom();
+        console.log('currentZoom', currentZoom);
+        graph.zoomTo(currentZoom - 0.1, { animation: true }); // 带动画放大
+      };
+
+      const handleFullscreen = () => {
+        // 全屏功能
+        const container = document.getElementById('org-chart-container');
+
+        const {  toggle  } = useFullscreen(container);
 
-      // 调整视图以适应所有节点
-      graph.zoomToFit({ padding: 20, maxScale: 1 })
-    }
+        // 调整内容适应
+        setTimeout(() => graph.zoomTo({ padding: 20, maxScale: 2 }), 300);
+        toggle();
+      };
 
-    // 组件挂载后初始化图表
-    onMounted(() => {
-      registerChartElements()
-      initChart()
-    })
+      // 组件挂载后初始化图表
+      onMounted(() => {
+        registerChartElements();
+        initChart();
+      });
 
-    // 组件卸载前清理图表
-    onBeforeUnmount(() => {
-      if (graph) {
-        graph.dispose()
-        graph = null
-      }
-    })
+      // 组件卸载前清理图表
+      onBeforeUnmount(() => {
+        if (graph) {
+          graph.dispose();
+          graph = null;
+        }
+      });
 
-    return {
-      containerRef,
-    }
-  },
-}
+      return {
+        containerRef,
+        zoomIn,
+        zoomOut,
+        handleFullscreen
+      };
+    },
+  };
 </script>
 
 <style scoped>
-.org-chart-container {
-  width: 100%;
-  height: 485px;
-  border: 1px solid #e5e7eb;
-  border-radius: 6px;
-  overflow: hidden;
-}
-</style>
+  .org-chart-container {
+    width: 100%;
+    height: 485px;
+    border: 1px solid #e5e7eb;
+    border-radius: 6px;
+    overflow: hidden;
+    background: #fff;
+  }
+</style>

+ 39 - 1
src/views/customer-manage/customer-detail/components/LinkCompany/index.vue

@@ -3,7 +3,21 @@
     <div class="link-flow">
       <bs-catalog title="关联公司架构">
         <template #content>
-          <org-struct-chart />
+          <div class="link-company-content">
+            <div class="func-btns">
+              <a-tooltip placement="right" title="全屏">
+                <bs-svg-icon name="icon-quanping" size="20" @click="handleFunc('quanping')" />
+              </a-tooltip>
+              <a-tooltip placement="right" title="放大">
+                <bs-svg-icon name="icon-fangda" size="20" @click="handleFunc('fangda')" />
+              </a-tooltip>
+              <a-tooltip placement="right" title="缩小">
+                <bs-svg-icon name="icon-suoxiao" size="20" @click="handleFunc('suoxiao')" />
+              </a-tooltip>
+            </div>
+
+            <org-struct-chart ref="orgStructChartRef" />
+          </div>
         </template>
       </bs-catalog>
     </div>
@@ -16,6 +30,17 @@
   import OrgStructChart from './compoents/OrgStructChart/index.vue';
   import LinkList from './compoents/LinkList/index.vue';
   import { BsCatalog } from '/@/components/BsUi/index.js';
+  import { ref } from 'vue';
+  const orgStructChartRef = ref(null);
+  const handleFunc = (code) => {
+    if (code === 'quanping') {
+      orgStructChartRef.value.handleFullscreen();
+    } else if (code === 'fangda') {
+      orgStructChartRef.value.zoomIn()
+    } else {
+      orgStructChartRef.value.zoomOut()
+    }
+  };
 </script>
 
 <style scoped lang="scss">
@@ -26,6 +51,19 @@
     .link-flow {
       border-radius: 8px;
       flex: 1;
+      .link-company-content {
+        width: 100%;
+        position: relative;
+        .func-btns {
+          position: absolute;
+          display: flex;
+          flex-direction: column;
+          gap: 10px;
+          right: 10px;
+          top: 10px;
+          z-index: 10;
+        }
+      }
     }
     .link-list {
       width: 670px;

+ 29 - 12
src/views/customer-manage/customer-management/index.vue

@@ -26,7 +26,7 @@
 
   const activeKey = ref(0);
 
-  const tabsOptions = [
+  const tabsOptions = ref([
     {
       title: '全部',
       icon: 'AppstoreOutlined',
@@ -35,31 +35,43 @@
         a: 1,
       },
       onClick: (value) => {
-        console.log(value);
+        fetchTableData(value);
       },
     },
     {
       title: '客户列表',
       icon: 'TeamOutlined',
       count: 0,
-      params: {},
-      onClick: (value) => {},
+      params: {
+        a: 2,
+      },
+      onClick: (value) => {
+        fetchTableData(value);
+      },
     },
     {
       title: '审核中',
       count: 0,
       icon: 'FileSyncOutlined',
-      params: {},
-      onClick: (value) => {},
+      params: {
+        a: 3,
+      },
+      onClick: (value) => {
+        fetchTableData(value);
+      },
     },
     {
       title: '无效客户',
       count: 0,
       icon: 'UserDeleteOutlined',
-      params: {},
-      onClick: (value) => {},
+      params: {
+        a: 4,
+      },
+      onClick: (value) => {
+        fetchTableData(value);
+      },
     },
-  ];
+  ]);
   const {
     tableOptions,
     setTablePropsValue: setValue,
@@ -244,6 +256,11 @@
           },
         ],
       },
+      // 每次查询接口之前,都会调用这个回调函数
+      tableSearchBeforeBiz() {
+        const searchParams = getValue('searchConfig.data');
+        setValue('searchConfig.data', { ...searchParams, otherField: 'abc' });
+      },
       mounted() {
         updateHeaderInfo();
       },
@@ -262,9 +279,9 @@
     updateTabsCount([customerQuantity, customerAuditQuantity, customerInvalidQuantity, customerValidQuantity]);
   };
 
-  watch(activeKey, () => {
-    fetchTableData();
-  });
+  // watch(activeKey, () => {
+  //   fetchTableData();
+  // });
 </script>
 <style lang="scss" scoped>
   .customer-management {

Некоторые файлы не были показаны из-за большого количества измененных файлов