From 9e3911480ea589b73dec7ca944334e742e627f6f Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期四, 06 八月 2026 16:48:37 +0800
Subject: [PATCH] feat(bi): 新增仓库坐标配置功能并优化地图可视化效果

---
 src/views/bi/warehouse/chart-options.ts |  233 +++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 199 insertions(+), 34 deletions(-)

diff --git a/src/views/bi/warehouse/chart-options.ts b/src/views/bi/warehouse/chart-options.ts
index 90b9b41..a64def5 100644
--- a/src/views/bi/warehouse/chart-options.ts
+++ b/src/views/bi/warehouse/chart-options.ts
@@ -112,75 +112,213 @@
   };
 }
 
-/** 涓浗鍦板浘 + 浠撳簱鑺傜偣 */
+function generateStardust(nodes: Array<{ value: number[] }>, count = 50): Array<{ value: number[] }> {
+  const particles: Array<{ value: number[] }> = [];
+  // 涓浗鍦扮悊鑼冨洿锛氱粡搴� 73~135锛岀含搴� 18~54
+  const lngRange = [75, 132];
+  const latRange = [20, 52];
+  for (let i = 0; i < count; i++) {
+    // 绉嶅瓙寮忓垎甯冿細閮ㄥ垎绮掑瓙闈犺繎浠撳簱鑺傜偣锛岄儴鍒嗛殢鏈�
+    if (i < count * 0.4 && nodes.length > 0) {
+      const seed = nodes[i % nodes.length];
+      const [lng, lat] = seed.value;
+      particles.push({
+        value: [lng + (Math.random() - 0.5) * 6, lat + (Math.random() - 0.5) * 4],
+      });
+    } else {
+      particles.push({
+        value: [
+          lngRange[0] + Math.random() * (lngRange[1] - lngRange[0]),
+          latRange[0] + Math.random() * (latRange[1] - latRange[0]),
+        ],
+      });
+    }
+  }
+  return particles;
+}
+
+/** 涓浗鍦板浘 + 浠撳簱鑺傜偣锛堥珮绾у厜鎬佺壒鏁堢増锛� */
 export function getChinaMapOptions(
   warehouseNodes: Array<{ name: string; value: number[]; stock: number }>,
   flyLines: Array<{ from: string; to: string }> = [],
 ): EChartsOption {
+  const nodeData = warehouseNodes.map((n) => ({
+    name: n.name,
+    value: [...n.value, n.stock],
+  }));
+
+  const maxStock = Math.max(1, ...warehouseNodes.map((n) => Math.abs(n.stock)));
+
+  // 鑺傜偣鍏夋檿灏哄鏄犲皠
+  function glowSize(stock: number, base: number, range: number) {
+    return base + (Math.abs(stock) / maxStock) * range;
+  }
+
+  const stardust = generateStardust(warehouseNodes, 50);
+
   return {
     geo: {
       map: 'china',
       roam: false,
       label: { show: false },
+      // 搴曞眰鍖哄煙鍙戝厜锛氱敤涓ゅ眰 geo 瀹炵幇锛岃繖閲屽寮轰富 geo 鏍峰紡
       itemStyle: {
         areaColor: {
           type: 'linear',
           x: 0, y: 0, x2: 0, y2: 1,
           colorStops: [
-            { offset: 0, color: '#0d1f42' },
-            { offset: 0.5, color: '#0a1835' },
-            { offset: 1, color: '#081028' },
+            { offset: 0, color: '#0d1f4a' },
+            { offset: 0.4, color: '#0a1838' },
+            { offset: 0.7, color: '#08102a' },
+            { offset: 1, color: '#060e20' },
           ],
         },
-        borderColor: 'rgba(0, 229, 255, 0.22)',
-        borderWidth: 1.2,
-        shadowColor: 'rgba(0, 229, 255, 0.08)',
+        borderColor: 'rgba(0, 229, 255, 0.28)',
+        borderWidth: 1.5,
+        shadowBlur: 18,
+        shadowColor: 'rgba(0, 180, 255, 0.25)',
         shadowOffsetX: 0,
-        shadowOffsetY: 3,
+        shadowOffsetY: 0,
       },
       emphasis: {
-        itemStyle: {
-          areaColor: '#132848',
-          borderColor: 'rgba(0, 229, 255, 0.45)',
-          borderWidth: 1.5,
-        },
+        disabled: true,
       },
+      // 绗簩灞� outline 閫氳繃 zlevel 鏇撮珮鐨� border 妯℃嫙
+      regions: [],
     },
     series: [
+      // ====== Series 0: 澶栧眰鍏夋檿锛堝ぇ灏哄銆佹瀬浣庨�忔槑搴︼級 ======
       {
+        name: 'outerGlow',
+        type: 'scatter',
+        coordinateSystem: 'geo',
+        data: nodeData,
+        symbolSize: (val: number[]) => glowSize(val[2] || 0, 50, 30),
+        silent: true,
+        itemStyle: {
+          color: {
+            type: 'radial',
+            x: 0.5, y: 0.5, r: 0.5,
+            colorStops: [
+              { offset: 0, color: 'rgba(0,229,255,0.12)' },
+              { offset: 0.3, color: 'rgba(0,229,255,0.05)' },
+              { offset: 1, color: 'rgba(0,229,255,0)' },
+            ],
+          },
+        },
+        emphasis: { disabled: true },
+        zlevel: 1,
+      },
+      // ====== Series 1: 鍐呭眰鍏夋檿锛堜腑绛夊昂瀵革紝鑴夊姩寮忥級 ======
+      {
+        name: 'innerGlow',
+        type: 'scatter',
+        coordinateSystem: 'geo',
+        data: nodeData,
+        symbolSize: (val: number[]) => glowSize(val[2] || 0, 26, 18),
+        silent: true,
+        itemStyle: {
+          color: {
+            type: 'radial',
+            x: 0.5, y: 0.5, r: 0.5,
+            colorStops: [
+              { offset: 0, color: 'rgba(0,255,200,0.22)' },
+              { offset: 0.4, color: 'rgba(0,229,255,0.1)' },
+              { offset: 1, color: 'rgba(0,150,255,0)' },
+            ],
+          },
+        },
+        emphasis: { disabled: true },
+        zlevel: 2,
+      },
+      // ====== Series 2: 涓昏妭鐐癸紙effectScatter 娑熸吉鍏夋晥锛� ======
+      {
+        name: 'warehouseNodes',
         type: 'effectScatter',
         coordinateSystem: 'geo',
-        data: warehouseNodes.map((n) => ({
-          name: n.name,
-          value: [...n.value, n.stock],
-        })),
-        symbolSize: (val: number[]) => Math.max(8, Math.min(22, (val[2] || 1) / 1500)),
+        data: nodeData,
+        symbolSize: (val: number[]) => Math.max(10, Math.min(26, glowSize(val[2] || 0, 10, 12))),
         showEffectOn: 'render',
-        rippleEffect: { brushType: 'stroke', scale: 4, period: 4.5 },
+        rippleEffect: {
+          brushType: 'stroke',
+          scale: 5.5,
+          period: 3.5,
+          color: {
+            type: 'radial',
+            x: 0.5, y: 0.5, r: 0.5,
+            colorStops: [
+              { offset: 0, color: C.cyan },
+              { offset: 0.4, color: 'rgba(0,229,255,0.5)' },
+              { offset: 1, color: 'rgba(0,100,255,0)' },
+            ],
+          },
+        },
         label: {
           show: true,
           position: 'bottom',
-          distance: 8,
+          distance: 14,
           formatter: '{b}',
-          fontSize: 10,
+          fontSize: 11,
+          fontWeight: 'bold',
           color: C.textPrimary,
+          textShadowBlur: 8,
+          textShadowColor: 'rgba(0,229,255,0.5)',
         },
         itemStyle: {
           color: {
             type: 'radial',
             x: 0.5, y: 0.5, r: 0.5,
             colorStops: [
-              { offset: 0, color: '#fff' },
-              { offset: 0.3, color: C.cyan },
-              { offset: 1, color: 'rgba(0,229,255,0.3)' },
+              { offset: 0, color: '#ffffff' },
+              { offset: 0.15, color: '#b5f0ff' },
+              { offset: 0.45, color: C.cyan },
+              { offset: 1, color: 'rgba(0,120,220,0.3)' },
             ],
           },
-          shadowBlur: 20,
+          shadowBlur: 28,
           shadowColor: C.cyan,
         },
-        zlevel: 1,
+        emphasis: {
+          scale: 1.6,
+          itemStyle: {
+            shadowBlur: 40,
+            shadowColor: '#fff',
+          },
+          label: {
+            fontSize: 13,
+            textShadowBlur: 14,
+            textShadowColor: 'rgba(0,229,255,0.8)',
+          },
+        },
+        zlevel: 3,
       },
+      // ====== Series 3: 浜牳锛堢櫧鑹查珮浜牳蹇冿級 ======
       {
+        name: 'nodeCores',
+        type: 'scatter',
+        coordinateSystem: 'geo',
+        data: nodeData,
+        symbolSize: (val: number[]) => Math.max(3, Math.min(7, glowSize(val[2] || 0, 3, 3))),
+        silent: true,
+        itemStyle: {
+          color: {
+            type: 'radial',
+            x: 0.5, y: 0.5, r: 0.5,
+            colorStops: [
+              { offset: 0, color: '#ffffff' },
+              { offset: 0.5, color: 'rgba(255,255,255,0.7)' },
+              { offset: 1, color: 'rgba(255,255,255,0)' },
+            ],
+          },
+          shadowBlur: 14,
+          shadowColor: '#fff',
+        },
+        emphasis: { disabled: true },
+        zlevel: 4,
+      },
+      // ====== Series 4: 椋炵嚎锛堝厜娴侊級 ======
+      {
+        name: 'flyLines',
         type: 'lines',
         coordinateSystem: 'geo',
         data: flyLines.map((f) => {
@@ -194,22 +332,49 @@
             x: 0, y: 0, x2: 1, y2: 1,
             colorStops: [
               { offset: 0, color: C.cyan },
+              { offset: 0.5, color: '#5ce6ff' },
               { offset: 1, color: C.green },
             ],
           },
-          curveness: 0.25,
-          width: 1.2,
-          opacity: 0.5,
+          curveness: 0.28,
+          width: 1.5,
+          opacity: 0.6,
+          shadowBlur: 8,
+          shadowColor: 'rgba(0,229,255,0.4)',
         },
         effect: {
           show: true,
-          period: 3,
-          trailLength: 0.4,
+          period: 2.5,
+          trailLength: 0.5,
           symbol: 'arrow',
-          symbolSize: 6,
-          color: C.green,
+          symbolSize: 7,
+          color: {
+            type: 'radial',
+            x: 0.5, y: 0.5, r: 0.5,
+            colorStops: [
+              { offset: 0, color: '#fff' },
+              { offset: 0.5, color: C.green },
+              { offset: 1, color: 'rgba(0,255,136,0)' },
+            ],
+          },
         },
-        zlevel: 1,
+        zlevel: 2,
+      },
+      // ====== Series 5: 鐜鍏夊皹锛堣儗鏅矑瀛愶級 ======
+      {
+        name: 'stardust',
+        type: 'scatter',
+        coordinateSystem: 'geo',
+        data: stardust,
+        symbolSize: 2,
+        silent: true,
+        itemStyle: {
+          color: 'rgba(100,200,255,0.5)',
+          shadowBlur: 4,
+          shadowColor: 'rgba(100,180,255,0.5)',
+        },
+        emphasis: { disabled: true },
+        zlevel: 0,
       },
     ],
     tooltip: {

--
Gitblit v1.9.3