繼上次實現圖譜后,后續發現如果要繼續加入不同樣式的圖譜實現起來太過麻煩,因此考慮將配置項全部提取封裝到js文件中,圖譜組件只專注于實現各種不同的組件,其中主要封裝的點就是各個節點的橫坐標(x),縱坐標(y),以及節點寬(width),節點高(height),節點數組(nodes)和節點相連的邊(edges),其他如顏色,字體大小等
封裝效果如下:
mapData對象中保存每種金屬對應的產業鏈,通過判斷來選擇取哪部分數據去顯示對應的圖譜,比如MapData['CU']即為顯示銅的圖譜,mapHeight為圖譜的默認高度,mapPadding為圖譜的父節點要顯示的padding,因為圖譜不一定需要占滿顯示,因此加了padding,desc為圖譜的描述,nodes和edges為節點和邊
實現效果如下:
其中mapData.js內容:
//有色金屬
export const mapData = {CU: {//銅mapHeight: 450,mapPadding: 35,desc: '<span>銅產業鏈邏輯:</span>銅產業鏈分為上、中、下游。上游主要是采選、冶煉,中游是銅材加工,下游是終端消費。銅價主要受產業供需和宏觀因素兩個方面影響,但從研究分析上來講產業可看供給,需求看宏觀。宏觀因素(核心):經濟周期、政策周期、通脹/通縮;基本面因素:供需平衡表、庫存周期、價差結構與區域溢價(短期)其他因素:商品大環境、資金面(博弈)、情緒面(事件、避險)',nodes: [{id: 'node1',x: 138,y: 135,width: 176,height: 60,label: '全球銅礦山產能',breedCode: 'CU',indexCode: 'OFFRDE0678557898',text: '全球銅礦山產能',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node2',x: 138,y: 209,width: 176,height: 60,label: '全球銅礦產能利用率',breedCode: 'CU',indexCode: 'ID00303168',text: '全球銅礦產能利用率',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node3',x: 394,y: 172,width: 134,height: 60,label: '全球銅礦供應',breedCode: 'CU',indexCode: 'OFFRDE0789849953',text: '全球銅礦供應',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node4',x: 394,y: 264,width: 134,height: 60,label: '加工費',breedCode: 'CU',indexCode: 'OFFRDE0407946063',text: '加工費',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node5',x: 394,y: 357,width: 134,height: 60,label: '國內銅礦供應',breedCode: 'CU',indexCode: 'OFFRDE0503146446',text: '國內銅礦供應',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node6',x: 591,y: 172,width: 158,height: 60,label: '精煉銅供應',breedCode: 'CU',indexCode: 'ID00407927',text: '精煉銅供應',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node7',x: 591,y: 234,width: 158,height: 40,label: '再生(廢雜)銅供應',text: '各類政策因素',breedCode: 'JM',text: '再生(廢雜)銅供應',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node8',x: 591,y: 286,width: 158,height: 40,label: '各類政策因素',text: '各類政策因素',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node9',x: 838,y: 31,width: 134,height: 60,label: '全球社會庫存',text: '全球社會庫存',breedCode: 'CU',indexCode: 'OFFRDE0416122129',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node10',x: 984,y: 31,width: 134,height: 60,label: 'LME銅庫存',text: 'LME銅庫存',breedCode: 'CU',indexCode: 'OFFRDE0099802675',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node11',x: 1130,y: 31,width: 134,height: 60,label: 'SHFE銅庫存',text: 'SHFE銅庫存',breedCode: 'CU',indexCode: 'OFFRDE0900823051',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node12',x: 1281,y: 31,width: 145,height: 60,label: 'COMEX銅庫存',text: 'COMEX銅庫存',breedCode: 'CU',indexCode: 'OFFRDE0470038275',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node13',x: 838,y: 136,width: 134,height: 60,label: '總庫存變化',breedCode: 'CU',indexCode: 'OFFRDE0704512926',text: '總庫存變化',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node14',x: 838,y: 234,width: 134,height: 60,label: '銅現貨價',breedCode: 'CU',indexCode: 'ID00303957',text: '銅現貨價',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node15',x: 838,y: 326,width: 134,height: 60,label: '比價與價差',text: '比價與價差',indexCode: 'FU00015882',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node16',x: 838,y: 418,width: 134,height: 60,label: '銅期貨價',text: '銅期貨價',indexCode: 'FU00015764',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node17',x: 1023,y: 136,width: 134,height: 60,label: '庫存消費比',breedCode: 'CU',indexCode: 'OFFRDE0881777811',text: '庫存消費比',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node18',x: 1023,y: 234,width: 134,height: 60,label: '表觀需求',breedCode: 'CU',indexCode: 'ID01167294',text: '表觀需求',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node19',x: 1023,y: 326,width: 134,height: 40,label: '貿易流向',text: '貿易流向',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node20',x: 1023,y: 418,width: 134,height: 40,label: '資金因素',text: '資金因素',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node21',x: 1257,y: 157,width: 134,height: 40,label: '房地產開工',text: '房地產開工',type: 'word-rect',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node22',x: 1257,y: 209,width: 134,height: 40,label: '汽車產銷',text: '汽車產銷',type: 'word-rect',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node23',x: 1257,y: 261,width: 134,height: 40,label: '基建投資',text: '基建投資',type: 'word-rect',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node24',x: 1257,y: 313,width: 134,height: 40,label: '家電等終端',text: '家電等終端',type: 'word-rect',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},],edges: [{ source: 'node1', target: 'node3' },{ source: 'node2', target: 'node3' },{ source: 'node3', target: 'node4', type: 'hvh3' },{ source: 'node4', target: 'node5', type: 'hvh3' },{ source: 'node3', target: 'node6' },{ source: 'node6', target: 'node14' },{ source: 'node7', target: 'node14' },{ source: 'node8', target: 'node14' },{ source: 'node9', target: 'node13', type: 'hvh3' },{source: 'node10',target: 'node13',type: 'hvh3',sourceAnchor: 2,targetAnchor: 0,},{source: 'node11',target: 'node13',type: 'hvh3',sourceAnchor: 2,targetAnchor: 0,},{source: 'node12',target: 'node13',type: 'hvh3',sourceAnchor: 2,targetAnchor: 0,},{ source: 'node13', target: 'node17' },{ source: 'node13', target: 'node14', type: 'hvh3' },{ source: 'node14', target: 'node18' },{ source: 'node14', target: 'node15', type: 'hvh3' },{ source: 'node15', target: 'node19' },{ source: 'node15', target: 'node16', type: 'hvh3' },{ source: 'node16', target: 'node20' },{ source: 'node18', target: 'node21' },{ source: 'node18', target: 'node22' },{ source: 'node18', target: 'node23' },{ source: 'node18', target: 'node24' },],},AL: {//鋁mapHeight: 229,mapPadding: 25,desc: '<span>鋁產業鏈邏輯:</span>鋁的產業鏈主要由鋁土礦開采、氧化鋁提煉、原鋁生產和鋁材加工四個環節組成。首先是鋁土礦開采,再通過對鋁土礦溶解、過濾、酸化和灼燒等工序提煉出氧化鋁,然后通過電解熔融的方式制備電解鋁。電解鋁經過重熔提純后可進一步加工成各種鋁材、鋁合金以及鋁粉等。鋁的上游產業鏈包括鋁土礦開采、氧化鋁提煉和原鋁生產。原鋁經過加工,制成鋁加工材,應用于下游各行各業。',nodes: [{id: 'block1',x: 176,y: 120,width: 353,height: 218,type: 'block-rect',label: '上游',},{id: 'block2',x: 530,y: 120,width: 330,height: 218,type: 'block-rect',label: '中游',},{id: 'block3',x: 1020,y: 120,width: 626,height: 218,type: 'block-rect',label: '下游',},{id: 'node1',x: 80,y: 63,width: 134,height: 60,label: '鋁土礦',breedCode: 'AL',indexCode: 'OFFRDE0116552998',text: '鋁土礦',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node2',x: 80,y: 127,width: 134,height: 40,label: '煤炭',text: '煤炭',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node3',x: 80,y: 179,width: 134,height: 40,label: '石灰石和堿',text: '石灰石和堿',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node4',x: 274,y: 127,width: 134,height: 60,label: '氧化鋁',breedCode: 'AL',indexCode: 'ID00188139',text: '氧化鋁',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node5',x: 444,y: 75,width: 132,height: 40,label: '電力',text: '電力',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node6',x: 444,y: 127,width: 132,height: 40,label: '氧化鋁',text: '氧化鋁',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node7',x: 444,y: 185,width: 132,height: 52,label: '碳素陽極、氟化鹽、冰晶石等',text: '碳素陽極、氟化鹽、冰晶石等',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node8',x: 616,y: 127,width: 134,height: 60,label: '電解鋁',breedCode: 'AL',indexCode: 'ID00188823',text: '電解鋁',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node9',x: 795,y: 127,width: 134,height: 60,label: '鋁合金錠',breedCode: 'AL',indexCode: 'ID01224399',text: '鋁合金錠',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node10',x: 970,y: 63,width: 74,height: 40,label: '擠壓材',text: '擠壓材',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node11',x: 970,y: 127,width: 74,height: 40,label: '壓制材',text: '壓制材',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node12',x: 970,y: 191,width: 74,height: 40,label: '鑄造材',text: '鑄造材',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node13',x: 1106,y: 63,width: 116,height: 52,label: '管、棒、型、線等',text: '管、棒、型、線等',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node14',x: 1106,y: 127,width: 116,height: 52,label: '板、帶、片、箔等',text: '板、帶、片、箔等',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node15',x: 1106,y: 191,width: 116,height: 52,label: '汽車輪轂、發動機等',text: '汽車輪轂、發動機等',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node16',x: 1263,y: 63,width: 116,height: 52,label: '建筑、光伏、線纜',text: '建筑、光伏、線纜',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node17',x: 1263,y: 127,width: 116,height: 52,label: '包裝、汽車、家電',text: '包裝、汽車、家電',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node18',x: 1263,y: 191,width: 116,height: 52,label: '汽車、五金、電器電子',text: '汽車、五金、電器電子',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},],edges: [{ source: 'node1', target: 'node4' },{ source: 'node2', target: 'node4' },{ source: 'node3', target: 'node4' },{ source: 'node4', target: 'node6' },{ source: 'node5', target: 'node8' },{ source: 'node6', target: 'node8' },{ source: 'node7', target: 'node8' },{ source: 'node8', target: 'node9' },{ source: 'node9', target: 'node10' },{ source: 'node9', target: 'node11' },{ source: 'node9', target: 'node12' },{ source: 'node10', target: 'node13' },{ source: 'node11', target: 'node14' },{ source: 'node12', target: 'node15' },{ source: 'node13', target: 'node16' },{ source: 'node14', target: 'node17' },{ source: 'node15', target: 'node18' },],},AO: {//氧化鋁,與鋁一樣mapHeight: 229,mapPadding: 25,desc: '<span>鋁產業鏈邏輯:</span>鋁的產業鏈主要由鋁土礦開采、氧化鋁提煉、原鋁生產和鋁材加工四個環節組成。首先是鋁土礦開采,再通過對鋁土礦溶解、過濾、酸化和灼燒等工序提煉出氧化鋁,然后通過電解熔融的方式制備電解鋁。電解鋁經過重熔提純后可進一步加工成各種鋁材、鋁合金以及鋁粉等。鋁的上游產業鏈包括鋁土礦開采、氧化鋁提煉和原鋁生產。原鋁經過加工,制成鋁加工材,應用于下游各行各業。',nodes: [{id: 'block1',x: 176,y: 120,width: 353,height: 218,type: 'block-rect',label: '上游',},{id: 'block2',x: 530,y: 120,width: 330,height: 218,type: 'block-rect',label: '中游',},{id: 'block3',x: 1020,y: 120,width: 626,height: 218,type: 'block-rect',label: '下游',},{id: 'node1',x: 80,y: 63,width: 134,height: 60,label: '鋁土礦',breedCode: 'AL',indexCode: 'OFFRDE0116552998',text: '鋁土礦',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node2',x: 80,y: 127,width: 134,height: 40,label: '煤炭',text: '煤炭',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node3',x: 80,y: 179,width: 134,height: 40,label: '石灰石和堿',text: '石灰石和堿',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node4',x: 274,y: 127,width: 134,height: 60,label: '氧化鋁',breedCode: 'AL',indexCode: 'ID00188139',text: '氧化鋁',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node5',x: 444,y: 75,width: 132,height: 40,label: '電力',text: '電力',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node6',x: 444,y: 127,width: 132,height: 40,label: '氧化鋁',text: '氧化鋁',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node7',x: 444,y: 185,width: 132,height: 52,label: '碳素陽極、氟化鹽、冰晶石等',text: '碳素陽極、氟化鹽、冰晶石等',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node8',x: 616,y: 127,width: 134,height: 60,label: '電解鋁',breedCode: 'AL',indexCode: 'ID00188823',text: '電解鋁',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node9',x: 795,y: 127,width: 134,height: 60,label: '鋁合金錠',breedCode: 'AL',indexCode: 'ID01224399',text: '鋁合金錠',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node10',x: 970,y: 63,width: 74,height: 40,label: '擠壓材',text: '擠壓材',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node11',x: 970,y: 127,width: 74,height: 40,label: '壓制材',text: '壓制材',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node12',x: 970,y: 191,width: 74,height: 40,label: '鑄造材',text: '鑄造材',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node13',x: 1106,y: 63,width: 116,height: 52,label: '管、棒、型、線等',text: '管、棒、型、線等',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node14',x: 1106,y: 127,width: 116,height: 52,label: '板、帶、片、箔等',text: '板、帶、片、箔等',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node15',x: 1106,y: 191,width: 116,height: 52,label: '汽車輪轂、發動機等',text: '汽車輪轂、發動機等',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node16',x: 1263,y: 63,width: 116,height: 52,label: '建筑、光伏、線纜',text: '建筑、光伏、線纜',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node17',x: 1263,y: 127,width: 116,height: 52,label: '包裝、汽車、家電',text: '包裝、汽車、家電',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node18',x: 1263,y: 191,width: 116,height: 52,label: '汽車、五金、電器電子',text: '汽車、五金、電器電子',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},],edges: [{ source: 'node1', target: 'node4' },{ source: 'node2', target: 'node4' },{ source: 'node3', target: 'node4' },{ source: 'node4', target: 'node6' },{ source: 'node5', target: 'node8' },{ source: 'node6', target: 'node8' },{ source: 'node7', target: 'node8' },{ source: 'node8', target: 'node9' },{ source: 'node9', target: 'node10' },{ source: 'node9', target: 'node11' },{ source: 'node9', target: 'node12' },{ source: 'node10', target: 'node13' },{ source: 'node11', target: 'node14' },{ source: 'node12', target: 'node15' },{ source: 'node13', target: 'node16' },{ source: 'node14', target: 'node17' },{ source: 'node15', target: 'node18' },],},PB: {//鉛mapHeight: 501,mapPadding: 100,desc: '',nodes: [{id: 'block1',x: 165,y: 255,width: 328,height: 490,type: 'block-rect',label: '原料端',labelCfg: { style: { width: 52, height: 20 } },},{id: 'block2',x: 475,y: 255,width: 270,height: 490,type: 'block-rect',label: '冶煉端',labelCfg: { style: { width: 52, height: 20 } },},{id: 'block3',x: 751,y: 255,width: 258,height: 490,type: 'block-rect',label: '初端下游產品',labelCfg: { style: { width: 88, height: 20 } },},{id: 'block4',x: 1037,y: 255,width: 290,height: 490,type: 'block-rect',label: '終端需求',labelCfg: { style: { width: 64, height: 20 } },},{id: 'node1',x: 50,y: 183,width: 74,height: 40,label: '鉛原礦',text: '鉛原礦',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node2',x: 164,y: 183,width: 74,height: 40,label: '鉛精礦',text: '鉛精礦',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node3',x: 279,y: 183,width: 74,height: 40,label: '粗鉛',text: '粗鉛',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node4',x: 432,y: 131,width: 74,height: 40,label: '陽極泥',text: '陽極泥',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node5',x: 554,y: 131,width: 88,height: 40,label: '金銀錫銻',text: '金銀錫銻',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node6',x: 554,y: 183,width: 88,height: 40,label: '原生鉛',text: '原生鉛',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node7',x: 778,y: 104,width: 156,height: 40,label: '其他',text: '其他',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node8',x: 778,y: 156,width: 156,height: 40,label: '蓄電池企業 (>85%)',text: '蓄電池企業 (>85%)',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',no_compute: true,},{id: 'node9',x: 778,y: 312,width: 156,height: 40,label: '氧化鉛',text: '氧化鉛',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node10',x: 778,y: 364,width: 156,height: 40,label: '鉛合金',text: '鉛合金',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node11',x: 778,y: 416,width: 156,height: 40,label: '鉛材',text: '鉛材',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node12',x: 1044,y: 52,width: 172,height: 40,label: '汽車啟動',text: '汽車啟動',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',fill: 'l(90) 0:#FBFCFF 1:#E9EDF3',strock: '#D4DBE7',},{id: 'node13',x: 1044,y: 104,width: 172,height: 40,label: '電動車',text: '電動車',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',fill: 'l(90) 0:#FBFCFF 1:#E9EDF3',strock: '#D4DBE7',},{id: 'node14',x: 1044,y: 156,width: 172,height: 40,label: '通信基站',text: '通信基站',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',fill: 'l(90) 0:#FBFCFF 1:#E9EDF3',strock: '#D4DBE7',},{id: 'node15',x: 1044,y: 208,width: 172,height: 40,label: '電力',text: '電力',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',fill: 'l(90) 0:#FBFCFF 1:#E9EDF3',strock: '#D4DBE7',},{id: 'node16',x: 1044,y: 260,width: 172,height: 40,label: '其他',text: '其他',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',fill: 'l(90) 0:#FBFCFF 1:#E9EDF3',strock: '#D4DBE7',},{id: 'node17',x: 1044,y: 312,width: 172,height: 40,label: '鋁鹽、穩定劑、助溶劑',text: '鋁鹽、穩定劑、助溶劑',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',fill: 'l(90) 0:#FBFCFF 1:#E9EDF3',strock: '#D4DBE7',},{id: 'node18',x: 1044,y: 364,width: 172,height: 40,label: '軸承、焊料、鉛彈',text: '軸承、焊料、鉛彈',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',fill: 'l(90) 0:#FBFCFF 1:#E9EDF3',strock: '#D4DBE7',},{id: 'node19',x: 1044,y: 416,width: 172,height: 40,label: '鉛板、鉛管、電纜護套',text: '鉛板、鉛管、電纜護套',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',fill: 'l(90) 0:#FBFCFF 1:#E9EDF3',strock: '#D4DBE7',},{id: 'node20',x: 778,y: 468,width: 156,height: 40,label: '回收',text: '回收',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',fill: 'l(90) 0:#FFF4F4 1:#FFE1E1',strock: '#F8C3C3',},{id: 'node21',x: 49,y: 312,width: 74,height: 40,label: '鉛廢料',text: '鉛廢料',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',fill: 'l(90) 0:#FFF4F4 1:#FFE1E1',strock: '#F8C3C3',},{id: 'node22',x: 279,y: 312,width: 74,height: 40,label: '還原鉛',text: '還原鉛',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',fill: 'l(90) 0:#FFF4F4 1:#FFE1E1',strock: '#F8C3C3',},{id: 'node23',x: 554,y: 312,width: 88,height: 40,label: '再生鉛',text: '再生鉛',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',fill: 'l(90) 0:#FFF4F4 1:#FFE1E1',strock: '#F8C3C3',},],edges: [{ source: 'node1', target: 'node2' },{ source: 'node2', target: 'node3' },{ source: 'node3', target: 'node4' },{source: 'node3',target: 'node6',label: '火法',subLabel: '電解',labelCfg: { style: { fontSize: 12, fill: '#245A9A' } },subLabelCfg: { style: { fontSize: 12, fill: '#245A9A' } },},{ source: 'node4', target: 'node5' },{ source: 'node6', target: 'node7' },{ source: 'node6', target: 'node8' },{source: 'node6',target: 'node9',sourceAnchor: 1,targetAnchor: 3,},{source: 'node6',target: 'node10',sourceAnchor: 1,targetAnchor: 3,},{source: 'node6',target: 'node11',sourceAnchor: 1,targetAnchor: 3,},{ source: 'node8', target: 'node12' },{ source: 'node8', target: 'node13' },{ source: 'node8', target: 'node14' },{ source: 'node8', target: 'node15' },{ source: 'node8', target: 'node16' },{ source: 'node9', target: 'node17' },{ source: 'node10', target: 'node18' },{ source: 'node11', target: 'node19' },{source: 'node12',target: 'node20',sourceAnchor: 1,targetAnchor: 1,type: 'hvh_custom',direction: 'left',path: [[1150, 52],[1150, 234],[1170, 234],[1170, 468],],},{source: 'node19',target: 'node20',sourceAnchor: 1,targetAnchor: 1,type: 'hvh_custom',path: [[1150, 416],[1150, 234],[1170, 234],[1170, 468],],},{source: 'node20',target: 'node21',sourceAnchor: 3,targetAnchor: 2,type: 'hvh2',corner: true,},{source: 'node21',target: 'node22',label: '火法',subLabel: '濕法',labelCfg: { style: { fontSize: 12, fill: '#245A9A' } },subLabelCfg: { style: { fontSize: 12, fill: '#245A9A' } },},{ source: 'node22', target: 'node23' },],},ZN: {//鋅mapHeight: 323,mapPadding: 0,desc: '<span>鋅產業鏈邏輯:</span>鋅生產過程以及實際的行業結構來看,行業價值鏈主要有三個主體:礦山、鋅冶煉商、鋅消費企業。礦山負責勘查和開采鋅精礦,并將鋅精礦出售給下游的鋅冶煉企業,鋅冶煉企業根據鋅消費市場的需求冶煉出符合市場需要的精煉鋅以及相關的副產品,鋅的最終消費企業從鋅冶煉企業購買所需的鋅產品。價值鏈的分析主要側重在各環節成本、收入的分析,由于礦山的收入基本等于冶煉商原料采購的成本,因此鋅精礦的定價機制是研究各環節盈利能力的關鍵所在。由于鋅精礦以加工費(TC/RC)的方式核算,因此鋅金屬價格和加工費(TC/RC)的高低是影響礦山和冶煉商收入的主要因素。',nodes: [{id: 'block1',x: 878.5,y: 54,width: 411,height: 108,type: 'block-rect',label: '',},{id: 'block2',x: 1155.5,y: 265,width: 425,height: 108,type: 'block-rect',label: '',},{id: 'block3',x: 696,y: 265,width: 454,height: 108,type: 'custom-node',label: '',strock: '#BCD0EE',shadowColor: 'rgba(54,78,128,0.1)',pieceList: [{type: 'rect',x: -227,y: -54,width: 26,height: 108,fill: '#4580D9',stroke: '',lineWidth: 0,radius: [4, 0, 0, 4],label: '一噸鋅錠成本',},{type: 'text',x: -220,y: -40,label: '一',fontSize: 12,align: 'left',fill: '#fff',weight: 400},{type: 'text',x: -220,y: -24,label: '噸',fontSize: 12,align: 'left',fill: '#fff',weight: 400},{type: 'text',x: -220,y: -8,label: '鋅',fontSize: 12,align: 'left',fill: '#fff',weight: 400},{type: 'text',x: -220,y: 8,label: '錠',fontSize: 12,align: 'left',fill: '#fff',weight: 400},{type: 'text',x: -220,y: 24,label: '成',fontSize: 12,align: 'left',fill: '#fff',weight: 400},{type: 'text',x: -220,y: 40,label: '本',fontSize: 12,align: 'left',fill: '#fff',weight: 400},{type: 'text',x: -191,y: -35,label: '原料成本:70%-80%、加工成本:20%-30%',fontSize: 12,align: 'left',fill: '#D91212',weight: 400},{type: 'text',x: -191,y: -11,label: '鋅精礦:1.042噸 用電量:3500-3700kwh 硫酸:300-400kg',fontSize: 12,align: 'left',fill: '#333',weight: 400},{type: 'text',x: -191,y: 11,label: '鋅輔料:250元 人工費:300-500元 鋅粉:(55-65kg)*40%',fontSize: 12,align: 'left',fill: '#333',weight: 400},{type: 'text',x: -191,y: 33,label: '其他成本:(20-30%) ',fontSize: 12,align: 'left',fill: '#333',weight: 400},]},{id: 'node1',x: 37,y: 89,width: 74,height: 40,label: '鋅礦石',text: '鋅礦石',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node2',x: 152,y: 89,width: 74,height: 40,label: '鋅精礦',text: '鋅精礦',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node3',x: 290,y: 89,width: 88,height: 40,label: '加工酸浸',text: '加工酸浸',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node4',x: 290,y: 159,width: 88,height: 40,label: '焙燒',text: '焙燒',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node5',x: 290,y: 230,width: 88,height: 40,label: '常壓酸浸',text: '常壓酸浸',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node6',x: 412,y: 159,width: 74,height: 40,label: '浸出液',text: '浸出液',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node7',x: 527,y: 159,width: 74,height: 40,label: '凈化',text: '凈化',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node8',x: 642,y: 159,width: 74,height: 40,label: '電積',text: '電積',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node9',x: 757,y: 159,width: 74,height: 40,label: '電解鋅',text: '電解鋅',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node10',x: 879,y: 159,width: 88,height: 40,label: '初級消費',text: '初級消費',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node11',x: 1155,y: 159,width: 88,height: 40,label: '終端消費',text: '終端消費',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node12',x: 754.5,y: 28,width: 147,height: 40,label: '鍍鋅 (30%)',text: '鍍鋅 (30%)',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',no_compute: true,fill: 'l(90) 0:#FBFCFF 1:#E9EDF3',strock: '#D4DBE7',},{id: 'node13',x: 754.5,y: 80,width: 147,height: 40,label: '壓鑄鋅合金 (30%)',text: '壓鑄鋅合金 (30%)',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',no_compute: true,fill: 'l(90) 0:#FBFCFF 1:#E9EDF3',strock: '#D4DBE7',},{id: 'node14',x: 899.5,y: 28,width: 119,height: 40,label: '黃銅 (22%)',text: '黃銅 (22%)',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',no_compute: true,fill: 'l(90) 0:#FBFCFF 1:#E9EDF3',strock: '#D4DBE7',},{id: 'node15',x: 899.5,y: 80,width: 119,height: 40,label: '氧化鋅 (22%)',text: '氧化鋅 (22%)',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',no_compute: true,fill: 'l(90) 0:#FBFCFF 1:#E9EDF3',strock: '#D4DBE7',},{id: 'node16',x: 1023.5,y: 28,width: 105,height: 40,label: '電池 (22%)',text: '電池 (22%)',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',no_compute: true,fill: 'l(90) 0:#FBFCFF 1:#E9EDF3',strock: '#D4DBE7',},{id: 'node17',x: 1023.5,y: 80,width: 105,height: 40,label: '其它 (22%)',text: '其它 (22%)',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',no_compute: true,fill: 'l(90) 0:#FBFCFF 1:#E9EDF3',strock: '#D4DBE7',},{id: 'node18',x: 1038.5,y: 239,width: 175,height: 40,label: '房地產及建筑業 (30%)',text: '房地產及建筑業 (30%)',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',no_compute: true,fill: 'l(90) 0:#FBFCFF 1:#E9EDF3',strock: '#D4DBE7',},{id: 'node19',x: 1038.5,y: 291,width: 175,height: 40,label: '基礎設施建設 (22%)',text: '基礎設施建設 (22%)',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',no_compute: true,fill: 'l(90) 0:#FBFCFF 1:#E9EDF3',strock: '#D4DBE7',},{id: 'node20',x: 1190.5,y: 239,width: 105,height: 40,label: '鋅合金 (22%)',text: '鋅合金 (22%)',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',no_compute: true,fill: 'l(90) 0:#FBFCFF 1:#E9EDF3',strock: '#D4DBE7',},{id: 'node21',x: 1190.5,y: 291,width: 105,height: 40,label: '汽車 (22%)',text: '汽車 (22%)',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',no_compute: true,fill: 'l(90) 0:#FBFCFF 1:#E9EDF3',strock: '#D4DBE7',},{id: 'node22',x: 1307.5,y: 239,width: 105,height: 40,label: '化工 (22%)',text: '化工 (22%)',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',no_compute: true,fill: 'l(90) 0:#FBFCFF 1:#E9EDF3',strock: '#D4DBE7',},{id: 'node23',x: 1307.5,y: 291,width: 105,height: 40,label: '其它 (22%)',text: '其它 (22%)',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',no_compute: true,fill: 'l(90) 0:#FBFCFF 1:#E9EDF3',strock: '#D4DBE7',},],edges: [{ source: 'node1', target: 'node2' },{ source: 'node2', target: 'node3' },{ source: 'node2', target: 'node4' },{source: 'node3',target: 'node6',sourceAnchor: 1,targetAnchor: 0,type: 'hvh3',corner: true,},{ source: 'node4', target: 'node5', type: 'hvh3' },{ source: 'node4', target: 'node6' },{source: 'node5',target: 'node6',sourceAnchor: 1,targetAnchor: 2,type: 'hvh2',corner: true,},{ source: 'node6', target: 'node7' },{ source: 'node7', target: 'node8' },{ source: 'node8', target: 'node9' },{ source: 'node9', target: 'node10' },{ source: 'node10', target: 'node11' },{ source: 'node10', target: 'block1', type: 'hvh2' },{ source: 'node11', target: 'block2', type: 'hvh3' },],},NI: {//鎳mapHeight: 362,mapPadding: 40,desc: '<span>鎳產業鏈邏輯:</span>鎳按照生產原料的不同可分為原生鎳和再生鎳,原生鎳的生產原料來自于 鎳礦,再生鎳的生產原料來自于含鎳廢料。按照鎳金屬的含量,原生鎳可以分為 四大產品系列,分別是電解鎳、含鎳生鐵、鎳鐵、其它(鎳鹽、通用鎳等)。',nodes: [{id: 'block1',x: 152.5,y: 184,width: 305,height: 350,type: 'block-rect',label: '上游',labelCfg: { style: { width: 42, height: 20 } },},{id: 'block2',x: 644.5,y: 184,width: 657,height: 350,type: 'block-rect',label: '中游',labelCfg: { style: { width: 40, height: 20 } },},{id: 'block3',x: 1145.5,y: 184,width: 323,height: 350,type: 'block-rect',label: '下游',labelCfg: { style: { width: 40, height: 20 } },},{id: 'block4',x: 56,y: 115,width: 88,height: 56,type: 'custom-node',label: '',strock: '#BCD0EE',shadowColor: 'rgba(54,78,128,0.1)',fill: 'rgba(255,255,255,0.9)',pieceList: [{type: 'text',x: 0,y: -11,label: '自有礦 (19%)',fontSize: 12,align: 'center',fill: '#333',weight: 400},{type: 'text',x: 0,y: 11,label: '進口礦 (81%)',fontSize: 12,align: 'center',fill: '#333',weight: 400},]},{id: 'block5',x: 868,y: 330,width: 177,height: 34,type: 'custom-node',label: '',strock: '#BCD0EE',shadowColor: 'rgba(54,78,128,0.1)',fill: 'rgba(255,255,255,0.9)',pieceList: [{type: 'text',x: 0,y: 0,label: '進口 (30%) 國內產量 (70%)',fontSize: 12,align: 'center',fill: '#333',weight: 400},]},{id: 'node1',x: 56,y: 195,width: 74,height: 40,label: '鎳礦',text: '鎳礦',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node2',x: 229,y: 127,width: 128,height: 50,label: '硫化鋰礦',text: '硫化鋰礦',subLabel: '(全球產量占36%)',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node3',x: 229,y: 261,width: 128,height: 54,label: '氧化鋰礦',text: '氧化鋰礦',subLabel: '(全球產量占64%)',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node4',x: 389,y: 127,width: 102,height: 50,label: '采礦',text: '采礦',subLabel: '(含鎳1.5%)',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node5',x: 389,y: 261,width: 102,height: 50,label: '采礦',text: '采礦',subLabel: '(含鎳1%-2%)',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node6',x: 546,y: 127,width: 102,height: 50,label: '鎳精礦',text: '鎳精礦',subLabel: '(含鎳7-10%)',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node7',x: 703,y: 127,width: 102,height: 50,label: '高冰鎳',text: '高冰鎳',subLabel: '(含鎳70%)',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node8',x: 868,y: 94,width: 114,height: 50,label: '鎳鹽',text: '鎳鹽',subLabel: '(含鎳22%)',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node9',x: 868,y: 156,width: 114,height: 50,label: '電解鎳',text: '電解鎳',subLabel: '(含鎳99.96%)',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node10',x: 868,y: 261,width: 114,height: 40,label: '鎳鐵',text: '鎳鐵',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node11',x: 1040,y: 156,width: 74,height: 40,label: '原生鎳',text: '原生鎳',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',fill: 'l(90) 0:#FBFCFF 1:#E9EDF3',strock: '#D4DBE7',},{id: 'node12',x: 1217,y: 52,width: 156,height: 40,label: '不銹鋼 (84%)',text: '不銹鋼 (84%)',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',fill: 'l(90) 0:#FBFCFF 1:#E9EDF3',strock: '#D4DBE7',no_compute: true,},{id: 'node13',x: 1217,y: 104,width: 156,height: 40,label: '電池 (4%)',text: '電池 (4%)',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',fill: 'l(90) 0:#FBFCFF 1:#E9EDF3',strock: '#D4DBE7',no_compute: true,},{id: 'node14',x: 1217,y: 156,width: 156,height: 40,label: '電鍍 (4%)',text: '電鍍 (4%)',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',fill: 'l(90) 0:#FBFCFF 1:#E9EDF3',strock: '#D4DBE7',no_compute: true,},{id: 'node15',x: 1217,y: 208,width: 156,height: 40,label: '鎳造和鎳合金 (5%)',text: '鎳造和鎳合金 (5%)',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',fill: 'l(90) 0:#FBFCFF 1:#E9EDF3',strock: '#D4DBE7',no_compute: true,},{id: 'node16',x: 1217,y: 260,width: 156,height: 40,label: '其他 (2%)',text: '其他 (2%)',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',fill: 'l(90) 0:#FBFCFF 1:#E9EDF3',strock: '#D4DBE7',no_compute: true,},],edges: [{ source: 'node1', target: 'block4', type: 'hvh2',lineDash: [2,2]},// 自定義虛線模式 { source: 'node1', target: 'node2' },{ source: 'node1', target: 'node3' },{ source: 'node2', target: 'node4' },{ source: 'node3', target: 'node5' },{source: 'node4', target: 'node6', label: '選礦',subLabel: '',labelCfg: { style: { fontSize: 12, fill: '#245A9A' } },subLabelCfg: { style: { fontSize: 12, fill: '#245A9A' } },},{source: 'node4', target: 'node9', sourceAnchor: 2,type: 'hvh_custom',direction: 'top',path: [[389, 201],[868, 201],],targetAnchor: 2, label: '濕法',subLabel: '',labelCfg: { style: { fontSize: 12, fill: '#245A9A' }, startPoint: { x: 389, y: 201 }, endPoint: { x: 868, y: 201 } },//自定義節點傳文本所在邊的起始點和終點subLabelCfg: { style: { fontSize: 12, fill: '#245A9A' } },},{source: 'node5', target: 'node10', label: '火法',subLabel: '',labelCfg: { style: { fontSize: 12, fill: '#245A9A' } },subLabelCfg: { style: { fontSize: 12, fill: '#245A9A' } },},{source: 'node6', target: 'node7', label: '濕法',subLabel: '',labelCfg: { style: { fontSize: 12, fill: '#245A9A' } },subLabelCfg: { style: { fontSize: 12, fill: '#245A9A' } },},{ source: 'node7', target: 'node8' },{ source: 'node7', target: 'node9' },{ source: 'node8', target: 'node11' },{ source: 'node9', target: 'node11' },{ source: 'node10', target: 'node11' },{ source: 'node10', target: 'block5', type: 'hvh3',lineDash: [2,2] },{source: 'node11', target: 'node12', sourceAnchor: 1,targetAnchor: 3,},{ source: 'node11', target: 'node13' },{ source: 'node11', target: 'node14' },{ source: 'node11', target: 'node15' },{source: 'node11', target: 'node16', sourceAnchor: 1,targetAnchor: 3,},]}
}
//默認黑色品種
export const defaultData = {mapHeight: 366,mapPadding: 0,desc: '',nodes: [{id: 'block1',x: 487,y: 117,width: 972,height: 232,type: 'block-rect',label: '長流程',},{id: 'block2',x: 670,y: 304,width: 604,height: 122,type: 'block-rect',label: '短流程',},{id: 'node1',x: 78,y: 42,label: '焦煤',breedCode: 'JM',indexCode: 'FU00008663',text: '焦煤',dataValue: '8302',chg: '0.16',anchorPoints: [[0, 0.5],[1, 0.5],],},{id: 'node2',x: 244,y: 42,label: '焦炭',breedCode: 'J',indexCode: 'FU00010732',text: '焦炭',dataValue: '8302',chg: '0.16',anchorPoints: [[0, 0.5],[1, 0.5],],},{id: 'node3',x: 244,y: 115,label: '鐵礦石',breedCode: 'I',indexCode: 'FU00005559',text: '鐵礦石',dataValue: '8302',chg: '-0.82',anchorPoints: [[0, 0.5],[1, 0.5],],},{id: 'node4',x: 466,y: 81,label: '高爐煉鐵',dataValue: '8302',chg: '0.16',type: 'breed-rect',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node5',x: 394,y: 189,label: '硅鐵',breedCode: 'SF',indexCode: 'FU00000314',text: '硅鐵',dataValue: '8302',chg: '0',anchorPoints: [[0, 0],[0.5, 0],],},{id: 'node6',x: 540,y: 189,label: '硅錳',breedCode: 'SM',indexCode: 'FU00000202',text: '硅錳',dataValue: '8302',chg: '-0.16',anchorPoints: [[0, 0.5],[0.5, 0],],},{id: 'node7',x: 669,y: 81,dataValue: '8302',chg: '0.16',anchorPoints: [[0, 0.5],[1, 0.5],],codes: [{label: '產能利用率',chg: '88.54',desc: '歷史低位',indexCode: 'ID00183114',text: '高爐煉鐵-產能利用率',},{label: '開工率',chg: '88.54',desc: '歷史低位',indexCode: 'ID00183109',text: '高爐煉鐵-開工率',},{label: '鋼廠盈利率',chg: '88.54',desc: '歷史低位',indexCode: 'ID00183126',text: '高爐煉鐵-鋼廠盈利率',},],type: 'rate-rect',},{id: 'node8',x: 886,y: 81,label: '生鐵產量',indexCode: 'ID00184088',text: '生鐵產量',dataValue: '6669.9',chg: '2.3',type: 'ratio-rect',desc: '高于近一年平均增速',anchorPoints: [[0, 0.5],[1, 0.5],],},{id: 'node9',x: 466,y: 284,label: '廢鋼',indexCode: 'OFFRDE0554363373',text: '廢鋼',dataValue: '8302',chg: '0.16',type: 'breed-rect',desc1: '相對高位',desc2: '利好',desc3: '獨立電爐企業',anchorPoints: [[0, 0.5],[1, 0.5],],},{id: 'node10',x: 660,y: 284,label: '電爐煉鋼',dataValue: '8302',chg: '0.16',type: 'breed-rect',anchorPoints: [[0, 0.5],[1, 0.5],],},{id: 'node11',x: 854,y: 284,label: '',codes: [{label: '產能利用率',chg: '88.54',desc: '歷史低位',indexCode: 'ID01302473',text: '電爐煉鋼-產能利用率',},{label: '電爐煉鋼利潤',chg: '88.54',desc: '歷史低位',indexCode: 'ID01040556',text: '電爐煉鋼-電爐煉鋼利率',},],type: 'rate-rect',anchorPoints: [[0, 0.5],[1, 0.5],],},{id: 'node12',x: 1100,y: 188,label: '粗鋼',indexCode: 'ID00182958',text: '粗鋼',dataValue: '6669.9',chg: '3.3',type: 'ratio-rect',desc: '高于近一年平均增速',anchorPoints: [[0, 0.5],[1, 0.5],],},{id: 'node13',x: 1307,y: 42,label: '螺紋鋼',breedCode: 'RB',indexCode: 'FU00001454',text: '螺紋鋼',dataValue: '8302',chg: '0.16',anchorPoints: [[0, 0.5],[1, 0.5],],},{id: 'node14',x: 1307,y: 115,label: '線材',breedCode: 'WR',indexCode: 'FU00005821',noClick: true, //是否節點可點擊text: '線材',dataValue: '8302',chg: '0.16',anchorPoints: [[0, 0.5],[1, 0.5],],},{id: 'node15',x: 1307,y: 188,label: '熱軋板卷',breedCode: 'HC',indexCode: 'FU00002440',text: '熱軋板卷',dataValue: '8302',chg: '0.16',anchorPoints: [[0, 0.5],[1, 0.5],],},{id: 'node16',x: 1307,y: 261,label: '不銹鋼',breedCode: 'SS',indexCode: 'FU00000075',text: '不銹鋼',dataValue: '8302',chg: '0.16',anchorPoints: [[0, 0.5],[1, 0.5],],},{id: 'node17',x: 1307,y: 324,label: '其他',dataValue: '8302',chg: '0.16',type: 'breed-rect',anchorPoints: [[0, 0.5],[1, 0.5],],},],edges: [{ source: 'node1', target: 'node2' },{ source: 'node2', target: 'node4' },{ source: 'node3', target: 'node4' },{ source: 'node5', target: 'node4', type: 'hvh2' },{ source: 'node6', target: 'node4', type: 'hvh2' },{ source: 'node4', target: 'node7', disableArrow: true },{ source: 'node7', target: 'node8' },{ source: 'node9', target: 'node10' },{ source: 'node10', target: 'node11', disableArrow: true },{ source: 'node8', target: 'node12' },{ source: 'node11', target: 'node12' },{ source: 'node12', target: 'node13' },{ source: 'node12', target: 'node14' },{ source: 'node12', target: 'node15' },{ source: 'node12', target: 'node16' },{ source: 'node12', target: 'node17' },],
}
?圖譜組件link-map.vue:
<template><div class="link-map"><div class="link-title">{{ breedName + props.elementName }}</div><div class="link-desc" v-if="desc !== ''" v-html="desc"></div><gl-spin :spinning="mapLoading"><divid="mountNode":style="{height: mapHeight + 'px',padding: isBlank ? '' : `0 ${mapPadding}px`,maxHeight: maxHeight + 'px',}"></div></gl-spin></div>
</template>
<script setup>
import { onMounted, getCurrentInstance } from 'vue'
import { formatNumValue } from '@/utils/index'
import G6 from '@antv/g6/dist/g6.min'
import { mapData, defaultData } from './mapData'
import { map } from 'lodash'
const { proxy } = getCurrentInstance()
const route = useRoute()
const props = defineProps({secCode: {type: String,default: '',},elementName: {type: String,default: '',},elementCode: {type: String,default: '',},
})
const emit = defineEmits(['breed-select'])
const nodes = ref([])
const edges = ref([])
const mapLoading = ref(false)
const graph2 = ref(null)
const color_breed = ref(['CU', 'AL', 'PB', 'ZN', 'SN', 'NI', 'LC', 'SI', 'AO']) //銅、鋁、鉛、鋅、錫、鎳、碳酸鋰、工業硅、氧化鋁
const mapHeight = ref(mapData[window.breedCode]? mapData[window.breedCode].mapHeight: defaultData.mapHeight
)
const maxHeight = ref(mapData[window.breedCode]? mapData[window.breedCode].mapHeight: defaultData.mapHeight
)
const isBlank = ref(color_breed.value.includes(window.breedCode) ? false : true) //是否黑色品種
const mapPadding = ref(mapData[window.breedCode]? mapData[window.breedCode].mapPadding: defaultData.mapPadding
)
const breedName = ref(window.breedName)
const isDragging = ref(false)
const desc = ref('')const tong_nodes = ref([{id: 'node1',x: 138,y: 136,width: 176,height: 61,label: '全球銅礦山產能',breedCode: 'JM',indexCode: 'OFFRDE0678557898',text: '全球銅礦山產能',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node2',x: 138,y: 209,width: 176,height: 61,label: '全球銅礦產能利用率',breedCode: 'JM',indexCode: 'ID00303168',text: '全球銅礦產能利用率',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node3',x: 394,y: 172,width: 134,height: 61,label: '全球銅礦供應',breedCode: 'JM',indexCode: 'OFFRDE0789849953',text: '全球銅礦供應',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node4',x: 394,y: 264,width: 134,height: 61,label: '加工費',breedCode: 'JM',indexCode: 'OFFRDE0407946063',text: '加工費',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node5',x: 394,y: 357,width: 134,height: 61,label: '國內銅礦供應',breedCode: 'JM',indexCode: 'OFFRDE0503146446',text: '國內銅礦供應',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node6',x: 591,y: 172,width: 158,height: 61,label: '精煉銅供應',breedCode: 'JM',indexCode: 'ID00407927',text: '精煉銅供應',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node7',x: 591,y: 234,width: 158,height: 39,label: '再生(廢雜)銅供應',text: '各類政策因素',breedCode: 'JM',text: '再生(廢雜)銅供應',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node8',x: 591,y: 286,width: 158,height: 39,label: '各類政策因素',text: '各類政策因素',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node9',x: 838,y: 31,width: 134,height: 61,label: '全球社會庫存',text: '全球社會庫存',breedCode: 'JM',indexCode: 'OFFRDE0416122129',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node10',x: 984,y: 31,width: 134,height: 61,label: 'LME銅庫存',text: 'LME銅庫存',breedCode: 'JM',indexCode: 'OFFRDE0099802675',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node11',x: 1130,y: 31,width: 134,height: 61,label: 'SHFE銅庫存',text: 'SHFE銅庫存',breedCode: 'JM',indexCode: 'OFFRDE0900823051',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node12',x: 1281,y: 31,width: 145,height: 61,label: 'COMEX銅庫存',text: 'COMEX銅庫存',breedCode: 'JM',indexCode: 'OFFRDE0470038275',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node13',x: 838,y: 136,width: 134,height: 61,label: '總庫存變化',breedCode: 'JM',indexCode: 'OFFRDE0704512926',text: '總庫存變化',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node14',x: 838,y: 234,width: 134,height: 61,label: '銅現貨價',breedCode: 'JM',indexCode: 'ID00303957',text: '銅現貨價',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node15',x: 838,y: 326,width: 134,height: 61,label: '比價與價差',text: '比價與價差',indexCode: 'FU00015882',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node16',x: 838,y: 418,width: 134,height: 61,label: '銅期貨價',text: '銅期貨價',indexCode: 'FU00015764',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node17',x: 1023,y: 136,width: 134,height: 61,label: '庫存消費比',breedCode: 'JM',indexCode: 'OFFRDE0881777811',text: '庫存消費比',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node18',x: 1023,y: 234,width: 134,height: 61,label: '表觀需求',breedCode: 'JM',indexCode: 'ID01167294',text: '表觀需求',dataValue: '-',chg: '-',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node19',x: 1023,y: 326,width: 134,height: 39,label: '貿易流向',text: '貿易流向',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node20',x: 1023,y: 418,width: 134,height: 39,label: '資金因素',text: '資金因素',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],type: 'word-rect',},{id: 'node21',x: 1257,y: 157,width: 134,height: 39,label: '房地產開工',text: '房地產開工',type: 'word-rect',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node22',x: 1257,y: 209,width: 134,height: 39,label: '汽車產銷',text: '汽車產銷',type: 'word-rect',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node23',x: 1257,y: 261,width: 134,height: 39,label: '基建投資',text: '基建投資',type: 'word-rect',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},{id: 'node24',x: 1257,y: 313,width: 134,height: 39,label: '家電等終端',text: '家電等終端',type: 'word-rect',anchorPoints: [[0.5, 0], // 上[1, 0.5], // 右[0.5, 1], // 下[0, 0.5], // 左],},
])
const tong_edges = ref([{ source: 'node1', target: 'node3' },{ source: 'node2', target: 'node3' },{ source: 'node3', target: 'node4', type: 'hvh3' },{ source: 'node4', target: 'node5', type: 'hvh3' },{ source: 'node3', target: 'node6' },{ source: 'node6', target: 'node14' },{ source: 'node7', target: 'node14' },{ source: 'node8', target: 'node14' },{ source: 'node9', target: 'node13', type: 'hvh3' },{source: 'node10',target: 'node13',type: 'hvh3',sourceAnchor: 2,targetAnchor: 0,},{source: 'node11',target: 'node13',type: 'hvh3',sourceAnchor: 2,targetAnchor: 0,},{source: 'node12',target: 'node13',type: 'hvh3',sourceAnchor: 2,targetAnchor: 0,},{ source: 'node13', target: 'node17' },{ source: 'node13', target: 'node14', type: 'hvh3' },{ source: 'node14', target: 'node18' },{ source: 'node14', target: 'node15', type: 'hvh3' },{ source: 'node15', target: 'node19' },{ source: 'node15', target: 'node16', type: 'hvh3' },{ source: 'node16', target: 'node20' },{ source: 'node18', target: 'node21' },{ source: 'node18', target: 'node22' },{ source: 'node18', target: 'node23' },{ source: 'node18', target: 'node24' },
])
const getSvg = (type, iconColor) => {// 動態生成SVG內容const generateSVG1 = (iconColor) => {return `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="14px" height="14px" viewBox="0 0 14 14" version="1.1"><title>Icon/漲</title><g id="頁面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><g id="Q2_5_4期限分析_供給分析_最小寬度1180" transform="translate(-388.000000, -226.000000)"><g id="價格" transform="translate(164.000000, 102.000000)"><g id="編組-13" transform="translate(46.000000, 116.000000)"><g id="產業鏈/期貨/漲備份-3" transform="translate(70.000000, 0.000000)"><g id="Icon/漲" transform="translate(108.000000, 8.000000)"><rect id="矩形" x="0" y="0" width="14" height="14"/><path d="M13.234199,3.55970481 C13.5098844,3.54382543 13.7462444,3.75443985 13.7621238,4.03012528 C13.7633238,4.05095907 13.7632183,4.07184754 13.761808,4.09266815 L13.5387743,7.38534552 C13.5201122,7.66085657 13.2816378,7.86907379 13.0061267,7.8504117 C12.8875582,7.84238031 12.775727,7.7923795 12.6906807,7.70937277 L11.522514,6.56902231 C11.5039313,6.59161598 11.4837258,6.61329794 11.4619021,6.63390921 L7.52440214,10.3526592 C7.19748321,10.661416 6.66840549,10.5862535 6.44041171,10.1986641 L4.67251566,7.193375 L1.15091069,10.1604378 C0.879839379,10.3887084 0.486186576,10.3759255 0.230649525,10.1444346 L0.164577825,10.075895 C-0.0844446196,9.78018087 -0.0465935113,9.33858461 0.249120641,9.08956216 L4.40537064,5.58956216 C4.73689384,5.31038473 5.23987001,5.39651159 5.45961961,5.77008591 L7.20126566,8.731625 L10.5006292,5.61609079 L10.525,5.59589343 L9.5175239,4.6123147 C9.3199065,4.41943657 9.31606456,4.10287739 9.5089427,3.90525999 C9.59608394,3.81597757 9.71345538,3.76249833 9.83800849,3.75532412 L13.234199,3.55970481 Z" id="形狀結合" fill="${iconColor}" fill-rule="nonzero"/></g></g></g></g></g></g></svg>`}// 下跌const generateSVG2 = (iconColor) => {return `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="14px" height="14px" viewBox="0 0 14 14" version="1.1"><title>Icon/跌</title><g id="頁面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><g id="Q2_5_4期限分析_供給分析_最小寬度1180" transform="translate(-547.000000, -226.000000)"><g id="價格" transform="translate(164.000000, 102.000000)"><g id="編組-13" transform="translate(46.000000, 116.000000)"><g id="產業鏈/期貨/跌備份-4" transform="translate(229.000000, 0.000000)"><g id="Icon/跌" transform="translate(108.000000, 8.000000)"><rect id="矩形" x="0" y="0" width="14" height="14"/><path d="M13.234199,3.50481138 C13.5098844,3.48893201 13.7462444,3.69954643 13.7621238,3.97523186 C13.7633238,3.99606564 13.7632183,4.01695412 13.761808,4.03777472 L13.5387743,7.3304521 C13.5201122,7.60596314 13.2816378,7.81418036 13.0061267,7.79551827 C12.8875582,7.78748688 12.775727,7.73748607 12.6906807,7.65447934 L11.522514,6.51412888 C11.5039313,6.53672256 11.4837258,6.55840451 11.4619021,6.57901578 L7.52440214,10.2977658 C7.19748321,10.6065225 6.66840549,10.5313601 6.44041171,10.1437707 L4.67251566,7.13848157 L1.15091069,10.1055444 C0.879839379,10.333815 0.486186576,10.3210321 0.230649525,10.0895412 L0.164577825,10.0210016 C-0.0844446196,9.72528744 -0.0465935113,9.28369118 0.249120641,9.03466874 L4.40537064,5.53466874 C4.73689384,5.25549131 5.23987001,5.34161816 5.45961961,5.71519249 L7.20126566,8.67673157 L10.5006292,5.56119737 L10.525,5.541 L9.5175239,4.55742128 C9.3199065,4.36454314 9.31606456,4.04798397 9.5089427,3.85036657 C9.59608394,3.76108415 9.71345538,3.70760491 9.83800849,3.70043069 L13.234199,3.50481138 Z" id="形狀結合" fill="${iconColor}" fill-rule="nonzero" transform="translate(6.883798, 6.994464) scale(1, -1) translate(-6.883798, -6.994464) "/></g></g></g></g></g></g></svg>`}// 持平const generateSVG3 = (iconColor) => {return `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="14px" height="14px" viewBox="0 0 14 14" version="1.1"><title>Icon/跌</title><g id="頁面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><g id="Q2_5_4期限分析_供給分析_最小寬度1180" transform="translate(-706.000000, -226.000000)"><g id="價格" transform="translate(164.000000, 102.000000)"><g id="編組-13" transform="translate(46.000000, 116.000000)"><g id="產業鏈/期貨/跌備份-3" transform="translate(388.000000, 0.000000)"><g id="Icon/跌" transform="translate(108.000000, 8.000000)"><rect id="矩形" x="0" y="0" width="14" height="14"/><path d="M2.8,6 L11.2,6 C11.6418278,6 12,6.3581722 12,6.8 C12,7.2418278 11.6418278,7.6 11.2,7.6 L2.8,7.6 C2.3581722,7.6 2,7.2418278 2,6.8 C2,6.3581722 2.3581722,6 2.8,6 Z" id="矩形" fill="${iconColor}"/></g></g></g></g></g></g></svg>`}return ('data:image/svg+xml;charset=utf-8,' +encodeURIComponent(type > 0? generateSVG1(iconColor): type === 0? generateSVG3(iconColor): generateSVG2(iconColor)))
}
const linkData = ref({link1: {indexCode: 'FU00008663',text: '焦煤',dataValue: '',dataChg: '',desc: '',},link2: {indexCode: 'FU00010732',text: '焦炭',dataValue: '',dataChg: '',desc: '',},link3: {indexCode: 'FU00005559',text: '鐵礦石',dataValue: '',dataChg: '',desc: '',},link4: {indexCode: 'FU00000314',text: '硅鐵',dataValue: '',dataChg: '',desc: '',},link5: {indexCode: 'FU00000202',text: '硅錳',dataValue: '',dataChg: '',desc: '',},link6: {indexCode: 'ID00183114',text: '高爐煉鐵-產能利用率',dataValue: '',dataChg: '',desc: '',},link7: {indexCode: 'ID00183109',text: '高爐煉鐵-開工率',dataValue: '',dataChg: '',desc: '',},link8: {indexCode: 'ID00183126',text: '高爐煉鐵-鋼廠盈利率',dataValue: '',dataChg: '',desc: '',},link9: {indexCode: 'ID00184088',text: '生鐵產量',dataValue: '',dataChg: '',desc: '',},link10: {indexCode: 'OFFRDE0554363373',text: '廢鋼',dataValue: '',dataChg: '',desc: '',},link11: {indexCode: 'ID01302473',text: '電爐煉鋼-產能利用率',dataValue: '',dataChg: '',desc: '',},link12: {indexCode: 'ID01040556',text: '電爐煉鋼-電爐煉鋼利率',dataValue: '',dataChg: '',desc: '',},link13: {indexCode: 'ID00182958',text: '粗鋼',dataValue: '',dataChg: '',desc: '',},link14: {indexCode: 'FU00001454',text: '螺紋鋼',dataValue: '',dataChg: '',desc: '',},link15: {indexCode: 'FU00005821',text: '線材',dataValue: '',dataChg: '',desc: '',},link16: {indexCode: 'FU00002440',text: '熱軋板卷',dataValue: '',dataChg: '',desc: '',},link17: {indexCode: 'FU00000075',text: '不銹鋼',dataValue: '',dataChg: '',desc: '',},
})
//查詢指定品種下鏈路圖數據
const loadGraphData = (menuCode) => {mapLoading.value = trueproxy.$request.get(`/futures-api/api/futures/data/chain?breedCode=${window.breedCode}&elementCode=${props.elementCode}`).then((res) => {console.log('品種下鏈路圖數據', res)mapLoading.value = falseif (res.data) {const data = res.data// if (!isBlank.value) {// console.log('顯示銅產業鏈')// edges.value = tong_edges.value// nodes.value = tong_nodes.value// }console.log('nodes.value', nodes.value)nodes.value.forEach((val) => {if (val.indexCode) {let list = data.filter((item) => item.indexCode == val.indexCode)if (list.length > 0) {val.dataValue = list[0].dataValueval.chg = list[0].dataChgval.desc = list[0].descval.unit = list[0].unitval.sumYoy = list[0].sumYoyif (val.indexCode == 'OFFRDE0554363373') {let descList = list[0].desc.replace(';<br>', '').split(' ')val.desc1 = descList[0]val.desc2 = descList[1]val.desc3 = descList[2]}}} else if (val.codes) {val.codes.forEach((ele) => {if (ele.indexCode) {let list = data.filter((item) => item.indexCode == ele.indexCode)if (list.length > 0) {ele.dataValue = list[0].dataValueele.chg = list[0].dataChgele.desc = list[0].descele.unit = list[0].unit}}})}})nextTick(() => {initGrah()})}})
}
const initGrah = () => {//創建模塊節點G6.registerNode('block-rect', {draw(cfg, group) {// 主矩形配置const width = cfg.widthconst height = cfg.heightconst fill = '#FAFCFF'const stroke = '#4376CE'// 創建主矩形const mainRect = group.addShape('rect', {attrs: {x: -width / 2,y: -height / 2,width,height,stroke,fill,lineDash: [2, 2], // 激活狀態用實線,非激活用虛線lineWidth: 1,radius: [4, 4, 4, 4],padding: 0,zIndex: -99,},name: 'main-rect',})if (cfg.label == '長流程') {group.addShape('rect', {attrs: {x: -width / 2 + 12,y: height / 2 - 10,width: 52,height: 20,fill: '#4580D9',stroke: '',lineWidth: 0,radius: [2, 2, 2, 2],zIndex: -99,},name: 'top-rect',})group.addShape('text', {attrs: {x: -width / 2 + 37,y: height / 2 + 6,text: '長流程',textAlign: 'center',fill: '#fff',fontSize: 12,zIndex: -99,},name: 'text1',})}if (cfg.label == '短流程') {group.addShape('rect', {attrs: {x: -width / 2 - 26,y: -10,width: 52,height: 20,fill: '#4580D9',stroke: '',lineWidth: 0,radius: [2, 2, 2, 2],zIndex: -99,},name: 'top-rect',})group.addShape('text', {attrs: {x: -width / 2,y: 7,text: '短流程',textAlign: 'center',fill: '#fff',fontSize: 12,zIndex: -99,},name: 'text1',})}let list = ['上游','中游','下游','原料端','冶煉端','初端下游產品','終端需求',]if (list.includes(cfg.label)) {group.addShape('rect', {attrs: {x: -(cfg.labelCfg?.style?.width / 2 || 20),y: -height / 2 - (cfg.labelCfg?.style?.height / 2 || 10),width: cfg.labelCfg?.style?.width || 40,height: cfg.labelCfg?.style?.height || 20,fill: '#4580D9',stroke: '#4580D9',lineWidth: 1,radius: [2, 2, 2, 2],zIndex: -99,},name: 'top-rect',})group.addShape('text', {attrs: {x: 0,y: -height / 2 + 6,text: cfg.label,textAlign: 'center',fill: '#fff',fontSize: 12,zIndex: -99,},name: 'text1',})}return mainRect},})//創建上下分割節點G6.registerNode('split-rect', {draw(cfg, group) {// 主矩形配置const width = 135const height = 60const fill = cfg.chg > 0 ? '#FBEAEC' : cfg.chg < 0 ? '#DFF5EB' : '#F1F2FA'const stroke =cfg.chg > 0 ? '#F8DDE0' : cfg.chg < 0 ? '#B8DDCC' : '#D7DCEA'// 創建主矩形const mainRect = group.addShape('rect', {attrs: {x: -width / 2,y: -height / 2,width,height,fill,stroke,lineWidth: 1,radius: [4, 4, 4, 4],padding: 12,},name: 'main-rect',})// 添加分割線(水平中線)group.addShape('line', {attrs: {x1: -width / 2 + 12,y1: 0,x2: width / 2 - 12,y2: 0,stroke: cfg.chg > 0 ? '#E6C5C6' : cfg.chg < 0 ? '#ACD5C3' : '#D3D9E8',lineWidth: 1,cursor: cfg.text !== '線材' ? 'pointer' : '',},name: 'divider-line',})// 添加上半部分小矩形group.addShape('rect', {attrs: {x: -width / 2,y: -height / 2,width: width,height: 30,fill: '',stroke: '#666',lineWidth: 0,radius: [4, 4, 0, 0],cursor: cfg.text !== '線材' ? 'pointer' : '',},name: 'top-rect',})// 添加下半部分小矩形group.addShape('rect', {attrs: {x: -width / 2,y: 0, // 從分割線下方開始width: width,height: 30,fill: '',stroke: '',lineWidth: 0,radius: [0, 0, 4, 4],cursor: cfg.text !== '線材' ? 'pointer' : '',},name: 'bottom-rect',})if (cfg.label) {group.addShape('text', {attrs: {text: cfg.label,x: -width / 2 + 12,y: -8,textAlign: 'left',fill: '#333',fontSize: 12,fontWeight: 600,cursor: cfg.text !== '線材' ? 'pointer' : '',},name: 'text1',})// 添加SVG圖像group.addShape('image', {attrs: {x: width / 2 - 24,y: -22,width: 14,height: 14,img:cfg.chg > 0? getSvg(1, '#D91212'): cfg.chg < 0? getSvg(-1, '#12A96E'): getSvg(0, '#999'),cursor: cfg.text !== '線材' ? 'pointer' : '',},name: 'img-1',})group.addShape('text', {attrs: {text: formatNumValue(cfg.dataValue),x: -width / 2 + 12,y: 22,textAlign: 'left',fill: cfg.chg > 0 ? '#D91212' : cfg.chg < 0 ? '#12A96E' : '#666',fontSize: 12,fontWeight: 600,cursor: cfg.text !== '線材' ? 'pointer' : '',},name: 'text3',})group.addShape('text', {attrs: {text: (cfg.chg > 0 ? '+' : cfg.chg < 0 ? '' : '') + cfg.chg + '%',x: width / 2 - 12,y: 22,textAlign: 'right',fill: cfg.chg > 0 ? '#D91212' : cfg.chg < 0 ? '#12A96E' : '#666',fontSize: 12,fontWeight: 600,cursor: cfg.text !== '線材' ? 'pointer' : '',},name: 'text4',})}return mainRect},// 響應狀態變化setState(name, value, item) {// console.log('name', name, value, item)let cfg = item._cfg.modelif (name === 'highlight') {const group = item.getContainer()const main_rect = group.find((ele) => ele.get('name') === 'main-rect')main_rect.attr('stroke',value? cfg.chg > 0? '#D12323': cfg.chg < 0? '#12A96E': '#8E92A1': cfg.chg > 0? '#F8DDE0': cfg.chg < 0? '#B8DDCC': '#D7DCEA')main_rect.attr('cursor', 'pointer')main_rect.attr('lineWidth', value ? 2 : 1)const top_rect = group.find((ele) => ele.get('name') === 'top-rect')// 改變背景色top_rect.attr('fill',value? cfg.chg > 0? '#D12323': cfg.chg < 0? '#12A96E': '#8E92A1': '')const bottom_rect = group.find((ele) => ele.get('name') === 'bottom-rect')// 改變背景色bottom_rect.attr('fill',value? cfg.chg > 0? '#FFF6F7': cfg.chg < 0? '#E9FBF3': '#F8F9FE': '')const text1 = group.find((ele) => ele.get('name') === 'text1')text1.attr('fill', value ? '#FFF' : '#333')const img_1 = group.find((ele) => ele.get('name') === 'img-1')img_1.attr('img',value? cfg.chg > 0? getSvg(1, '#fff'): cfg.chg < 0? getSvg(-1, '#fff'): getSvg(0, '#fff'): cfg.chg > 0? getSvg(1, '#D91212'): cfg.chg < 0? getSvg(-1, '#12A96E'): getSvg(0, '#999'))}if (name === 'hover' && cfg.text != '線材') {const group = item.getContainer()const main_rect = group.find((ele) => ele.get('name') === 'main-rect')main_rect.attr('stroke',value || item.getStates().includes('highlight')? cfg.chg > 0? '#D12323': cfg.chg < 0? '#12A96E': '#8E92A1': cfg.chg > 0? '#F8DDE0': cfg.chg < 0? '#B8DDCC': '#D7DCEA')main_rect.attr('cursor', 'pointer')}},getAnchorPoints() {return [[0.5, 0],[1, 0.5],[0.5, 1],[0, 0.5], // 四邊中點]},})//創建品種文本節點G6.registerNode('breed-rect', {draw(cfg, group) {// 主矩形配置const width = cfg.width ? cfg.width : cfg.label == '其他' ? 134 : 120const height = cfg.height ? cfg.height : 40const fill = '#FFF'const stroke = '#C3CDE8'// 創建主矩形const mainRect = group.addShape('rect', {attrs: {x: -width / 2,y: -height / 2,width,height,fill,stroke,lineWidth: 1,radius: [4, 4, 4, 4],padding: 0,shadowOffsetX: 0,shadowOffsetY: 2,shadowBlur: 6,spread: 2,shadowColor: 'rgba(149,157,174,0.1)',},name: 'main-rect',})if (cfg.label) {group.addShape('text', {attrs: {text: cfg.label,x: 0,y: 7,textAlign: 'center',fill: '#333',fontSize: 14,fontWeight: 600,},name: 'text1',})if (cfg.label == '廢鋼') {group.addShape('text', {attrs: {text: `螺廢差:${cfg.dataValue}`,x: -width / 2,y: 46,textAlign: 'left',fill: '#333',fontSize: 12,},name: 'text2',})group.addShape('text', {attrs: {text: `(${cfg.desc1})`,x: -width / 2 + (4 * 12 + (cfg.dataValue.length + '') * 6) + 8,y: 46,textAlign: 'left',fill: '#D91212',fontSize: 12,},name: 'text2-desc1',})group.addShape('text', {attrs: {text: `${cfg.desc2}:`,x: -width / 2,y: 68,textAlign: 'left',fill: '#D91212',fontSize: 12,},name: 'text2-desc2',})group.addShape('text', {attrs: {text: `${cfg.desc3}`,x: -width / 2 + cfg.desc2.length * 12 + 8,y: 68,textAlign: 'left',fill: '#333',fontSize: 12,},name: 'text2-desc3',})}}return mainRect},setState(name, value, item) {if (name === 'hover') {const group = item.getContainer()const main_rect = group.find((ele) => ele.get('name') === 'main-rect')main_rect.attr('shadowColor',value ? 'rgba(149,157,174,0.2)' : 'rgba(149,157,174,0.1)')}},})//創建文本利率節點G6.registerNode('rate-rect', {draw(cfg, group) {// 主矩形配置const width = cfg.codes && cfg.codes.length > 2 ? 204 : 212const height = 12 + cfg.codes.length * 22const fill = '#FFF'const stroke = '#fff'// 創建主矩形const mainRect = group.addShape('rect', {attrs: {x: -width / 2,y: -height / 2,width,height,fill,stroke,lineWidth: 0,radius: [4, 4, 4, 4],padding: 0,shadowOffsetX: 0,shadowOffsetY: 2,shadowBlur: 6,spread: 2,shadowColor: 'rgba(54,78,128,0.1)',},name: 'main-rect',})if (cfg.codes) {cfg.codes.forEach((item, index) => {group.addShape('text', {attrs: {text: `${item.label}: ${item.chg}%`,x: -width / 2 + 12,y: -height / 2 + 24 + 22 * index,textAlign: 'left',fill: '#333',fontSize: 12,},name: `text-${index + 1}`,})group.addShape('text', {attrs: {text: `(${item.desc})`,x:-width / 2 +12 +((item.label.length + 1) * 12 +((item.chg + '').length + 1) * 6) +12,y: -height / 2 + 24 + 22 * index,textAlign: 'left',fill: '#D91212',fontSize: 12,},name: `text-${index + 1}-desc`,})})}return mainRect},})//創建產量同比節點G6.registerNode('ratio-rect', {draw(cfg, group) {// 主矩形配置const width = 147const height = 86const fill = '#FFF'const stroke = '#C3CDE8'// 創建主矩形const mainRect = group.addShape('rect', {attrs: {x: -width / 2,y: -height / 2,width,height,fill,stroke,lineWidth: 1,radius: [4, 4, 4, 4],padding: 0,shadowOffsetX: 0,shadowOffsetY: 2,shadowBlur: 6,spread: 2,shadowColor: 'rgba(149,157,174,0.1)',},name: 'main-rect',})group.addShape('text', {attrs: {text: cfg.label,x: 0,y: -height / 2 + 24,textAlign: 'center',fill: '#333',fontSize: 14,fontWeight: 600,},name: 'text1',})group.addShape('line', {attrs: {x1: -width / 2 + 12,y1: -14,x2: width / 2 - 12,y2: -14,stroke: '#DDE3F2',lineWidth: 1,},name: 'divider-line',})group.addShape('text', {attrs: {text: `${cfg.dataValue}`,x: 16,y: -height / 2 + 55,textAlign: 'right',fill: '#333',fontSize: 16,fontWeight: 600,},name: 'text2',})group.addShape('text', {attrs: {text: `${cfg.unit}`,x: 20,y: -height / 2 + 53,textAlign: 'left',fill: '#666',fontSize: 12,},name: 'text2',})group.addShape('text', {attrs: {text: `累計同比${cfg.sumYoy > 0 ? '上漲' : cfg.sumYoy < 0 ? '下降' : '持平'}`,x: -width / 2 + 12,y: -height / 2 + 75,textAlign: 'left',fill: '#666',fontSize: 12,},name: 'text3',})group.addShape('text', {attrs: {text: `${Math.abs(cfg.sumYoy).toFixed(2)}%`,x: width / 2 - 14,y: -height / 2 + 76,textAlign: 'right',fill:cfg.sumYoy > 0 ? '#D91212' : cfg.sumYoy < 0 ? '#12A96E' : '#666666',fontSize: 14,fontWeight: 600,},name: 'text3-chg',})group.addShape('text', {attrs: {text: `${cfg.desc}`,x: 0,y: -height / 2 + 85 + 22,textAlign: 'center',fill: '#D91212',fontSize: 12,},name: 'text4',})return mainRect},setState(name, value, item) {if (name === 'hover') {const group = item.getContainer()const main_rect = group.find((ele) => ele.get('name') === 'main-rect')main_rect.attr('shadowColor',value ? 'rgba(149,157,174,0.2)' : 'rgba(149,157,174,0.1)')}},})//創建產量價格節點G6.registerNode('product-rect', {draw(cfg, group) {// 主矩形配置const width = cfg.width ? cfg.width : 134const height = cfg.height ? cfg.height : 60const fill = cfg.chg > 0 ? '#FBEAEC' : cfg.chg < 0 ? '#DFF5EB' : '#F1F2FA'const stroke =cfg.chg > 0 ? '#F8DDE0' : cfg.chg < 0 ? '#B8DDCC' : '#D7DCEA'// 創建主矩形const mainRect = group.addShape('rect', {attrs: {x: -width / 2,y: -height / 2,width,height,fill,stroke,lineWidth: 1,radius: [4, 4, 4, 4],padding: 12,},name: 'main-rect',})// 添加分割線(水平中線)group.addShape('line', {attrs: {x1: -width / 2 + 12,y1: 0,x2: width / 2 - 12,y2: 0,stroke: cfg.chg > 0 ? '#E6C5C6' : cfg.chg < 0 ? '#ACD5C3' : '#D3D9E8',lineWidth: 1,},name: 'divider-line',})// 添加上半部分小矩形group.addShape('rect', {attrs: {x: -width / 2,y: -height / 2,width: width,height: 30,fill: '',stroke: '#666',lineWidth: 0,radius: [4, 4, 0, 0],},name: 'top-rect',})// 添加下半部分小矩形group.addShape('rect', {attrs: {x: -width / 2,y: 0, // 從分割線下方開始width: width,height: 30,fill: '',stroke: '',lineWidth: 0,radius: [0, 0, 4, 4],},name: 'bottom-rect',})if (cfg.label) {group.addShape('text', {attrs: {text: cfg.label,x: -width / 2 + 12,y: -8,textAlign: 'left',fill: '#333',fontSize: 12,fontWeight: 600,},name: 'text1',})// 添加SVG圖像group.addShape('image', {attrs: {x: width / 2 - 24,y: -22,width: 14,height: 14,img:cfg.chg > 0? getSvg(1, '#D91212'): cfg.chg < 0? getSvg(-1, '#12A96E'): getSvg(0, '#999'),cursor: cfg.text !== '線材' ? 'pointer' : '',},name: 'img-1',})group.addShape('text', {attrs: {text: formatNumValue(cfg.dataValue),x: -width / 2 + 12,y: 22,textAlign: 'left',fill: cfg.chg > 0 ? '#D91212' : cfg.chg < 0 ? '#12A96E' : '#666',fontSize: 12,fontWeight: 600,},name: 'text3',})group.addShape('text', {attrs: {text:(cfg.chg > 0 ? '+' : cfg.chg < 0 ? '' : '') +cfg.chg +(cfg.chg && cfg.chg != '-' ? '%' : ''),x: width / 2 - 12,y: 22,textAlign: 'right',fill: cfg.chg > 0 ? '#D91212' : cfg.chg < 0 ? '#12A96E' : '#666',fontSize: 12,fontWeight: 600,},name: 'text4',})}return mainRect},})//創建文本節點G6.registerNode('word-rect', {draw(cfg, group) {// 主矩形配置const width = cfg.width ? cfg.width : 120const height = cfg.height ? cfg.height : 40let fill = cfg.fill ? cfg.fill : 'l(90) 0:#F5F9FF 1:#E0EDFF'const stroke = cfg.strock ? cfg.strock : '#BCD0EE'// 創建主矩形const mainRect = group.addShape('rect', {attrs: {x: -width / 2,y: -height / 2,width,height,fill: fill,stroke,lineWidth: 1,radius: [4, 4, 4, 4],padding: 0,shadowOffsetX: 0,shadowOffsetY: 2,shadowBlur: 6,spread: 2,shadowColor: 'rgba(149,157,174,0.1)',},name: 'main-rect',})//no_compute,是否不需要計算換行//如果文本長度大于矩形寬度,則進行換行if (cfg.label.length * 16 > cfg.width && !cfg.no_compute) {let startLength = Math.floor((cfg.width - 20) / 16)let lines = Math.ceil(cfg.label.length / startLength)let startTop = (cfg.height - 16 * lines + 2 * (lines - 1)) / 2for (let i = 0; i < lines; i++) {group.addShape('text', {attrs: {x: 0,y: -height / 2 + 6 + startTop + i * 18,text: cfg.label.substring(i * startLength, (i + 1) * startLength),fontSize: 14,textAlign: 'center',textBaseline: 'middle',fill: '#333',fontSize: 14,fontWeight: 600,},name: 'text-shape',})}} else {group.addShape('text', {attrs: {text: cfg.label,x: 0,y: cfg.subLabel ? -2 : 8,textAlign: 'center',fill: '#333',fontSize: 14,fontWeight: 600,},name: 'text1',})if (cfg.subLabel) {group.addShape('text', {attrs: {text: cfg.subLabel,x: 0,y: 17,textAlign: 'center',fill: cfg.subLabel?.style?.fill || '#666',fontSize: cfg.subLabel?.style?.fontSize || 12,fontWeight: cfg.subLabel?.style?.weight || 400,},name: 'text2',})}}return mainRect},setState(name, value, item) {if (name === 'hover') {const group = item.getContainer()const main_rect = group.find((ele) => ele.get('name') === 'main-rect')main_rect.attr('shadowColor',value ? 'rgba(149,157,174,0.2)' : 'rgba(149,157,174,0.1)')}},})//創建自定義節點G6.registerNode('custom-node', {draw(cfg, group) {// 主矩形配置const width = cfg.widthconst height = cfg.heightconst fill = cfg.fill || '#fff'const stroke = cfg.strock// 創建主矩形const mainRect = group.addShape('rect', {attrs: {x: -width / 2,y: -height / 2,width,height,fill: fill,stroke,lineWidth: cfg.lineWidth || 1,radius: cfg.radius || [4, 4, 4, 4],padding: 0,shadowOffsetX: 0,shadowOffsetY: 2,shadowBlur: 6,spread: 2,shadowColor: cfg.shadowColor || 'rgba(149,157,174,0.1)',},name: 'main-rect',})cfg.pieceList &&cfg.pieceList.forEach((e, i) => {if (e.type == 'rect') {group.addShape('rect', {attrs: {x: e.x,y: e.y,width: e.width,height: e.height,fill: e.fill || '#fff',stroke: e.strock || '#fff',lineWidth: e.lineWidth || 0,radius: e.radius,},name: 'top-rect' + i,})}if (e.type == 'text') {group.addShape('text', {attrs: {x: e.x,y: e.y,text: e.label,fontSize: e.fontSize,textAlign: e.align,textBaseline: 'middle',fill: e.fill,fontWeight: e.weight,},name: 'text-shape',})}})return mainRect},setState(name, value, item) {if (name === 'hover') {const group = item.getContainer()const main_rect = group.find((ele) => ele.get('name') === 'main-rect')main_rect.attr('shadowColor',value ? 'rgba(149,157,174,0.2)' : 'rgba(149,157,174,0.1)')}},})//從左往右的箭頭G6.registerEdge('hvh', {draw(cfg, group) {const startPoint = cfg.startPointconst endPoint = cfg.endPointconst shape = group.addShape('path', {attrs: {stroke: '#8993AA',path: [['M', startPoint.x, startPoint.y],['L', endPoint.x / 2 + (1 / 2) * startPoint.x, startPoint.y], // 二分之一處['L', endPoint.x / 2 + (1 / 2) * startPoint.x, endPoint.y], // 二分之一處['L', endPoint.x, endPoint.y],],lineWidth: 1,lineDash: cfg.lineDash ? cfg.lineDash : '', // 自定義虛線模式zIndex: 10, // 確保邊在頂部// startArrow: {// path: "M 10,0 L -10,-10 L -10,10 Z",// d: 10,// },// endArrow: {// path: "M 10,0 L -10,-10 L -10,10 Z",// d: 5,// },// endArrow: {// path: G6.Arrow.triangle(10, 12, 25), // 三角形箭頭// fill: "#333", // 填充顏色// stroke: "#333", // 邊框顏色// },},})// 計算箭頭方向const angle = Math.atan2(endPoint.y - startPoint.y,endPoint.x - startPoint.x)// 自定義箭頭路徑生成方法function getArrowPath(x, y, angle) {const length = 9 // 箭頭長度const width = 4 // 箭頭寬度// 計算箭頭三個點的坐標const x1 = x - length * Math.cos(angle)const y1 = y - length * Math.sin(angle)const x2 = x1 - width * Math.cos(angle + Math.PI / 2)const y2 = y1 - width * Math.sin(angle + Math.PI / 2)const x3 = x1 - width * Math.cos(angle - Math.PI / 2)const y3 = y1 - width * Math.sin(angle - Math.PI / 2)return [['M', x, y], ['L', x2, y2], ['L', x3, y3], ['Z']]}//是否不需要顯示箭頭if (!cfg.disableArrow) {// 在終點繪制自定義箭頭group.addShape('path', {attrs: {path: getArrowPath(endPoint.x, endPoint.y, 0),fill: '#8993AA',stroke: '#8993AA',lineWidth: 1,},})}// //在邊上畫循環點const circle = group.addShape('ellipse', {attrs: {x: cfg.startPoint.x,y: cfg.startPoint.y,fill: 'l(0) 0:rgba(102,212,255,0.7) 1:#1A56FF',rx: 4,ry: 1,shadowColor: '#1A56FF',shadowBlur: 4,shadowOffsetY: 1,},name: 'circle-shape',})const time =(Math.abs(cfg.endPoint.x - cfg.startPoint.x) +Math.abs(cfg.endPoint.y - cfg.startPoint.y)) /0.05circle.show()circle.animate((ratio) => {const tmpPoint = shape.getPoint(ratio)const pos = G6.Util.getLabelPosition(shape, ratio)let matrix = [1, 0, 0, 0, 1, 0, 0, 0, 1]matrix = G6.Util.transform(matrix, [['t', -tmpPoint.x, -tmpPoint.y],['r', pos.angle],['t', tmpPoint.x, tmpPoint.y],])return {x: tmpPoint.x,y: tmpPoint.y,matrix,}},{repeat: true,duration: time,easing: 'easeLinear',delay: 0,})// 計算邊的中點const midX = (startPoint.x + endPoint.x) / 2const midY = (startPoint.y + endPoint.y) / 2// 計算邊的角度(用于文本旋轉)const angle2 = Math.atan2(endPoint.y - startPoint.y,endPoint.x - startPoint.x)// 添加上方文本if (cfg.label) {group.addShape('text', {attrs: {x: midX,y: midY - 6, // 上方偏移text: cfg.label,fill: cfg.labelCfg?.style?.fill || '#333',fontSize: cfg.labelCfg?.style?.fontSize || 12,textAlign: 'center',textBaseline: 'bottom',rotate: angle2,},})}// 添加下方文本if (cfg.subLabel) {group.addShape('text', {attrs: {x: midX,y: midY + 6, // 下方偏移text: cfg.subLabel,fill: cfg.subLabelCfg?.style?.fill || '#666',fontSize: cfg.subLabelCfg?.style?.fontSize || 12,textAlign: 'center',textBaseline: 'top',rotate: angle2,},})}return shape},})//從下往上的邊G6.registerEdge('hvh2', {draw(cfg, group) {const startPoint = cfg.startPointconst endPoint = cfg.endPoint//默認顯示2個拐角let shape = nullif (cfg.corner) {//只顯示一個拐角shape = group.addShape('path', {attrs: {stroke: '#8993AA',path: [['M', startPoint.x, startPoint.y],['L', endPoint.x, startPoint.y],['L', endPoint.x, endPoint.y],],lineWidth: 1,lineDash: cfg.lineDash ? cfg.lineDash : '', // 自定義虛線模式zIndex: 10, // 確保邊在頂部},})} else {shape = group.addShape('path', {attrs: {stroke: '#8993AA',path: [['M', startPoint.x, startPoint.y],['L',startPoint.x,(2 / 3) * startPoint.y + (1 / 3) * endPoint.y,], // 三分之一處['L', endPoint.x, (2 / 3) * startPoint.y + (1 / 3) * endPoint.y], // 三分之二處['L', endPoint.x, endPoint.y],],lineWidth: 1,lineDash: cfg.lineDash ? cfg.lineDash : '', // 自定義虛線模式zIndex: 10, // 確保邊在頂部},})}// 計算箭頭方向const angle = Math.atan2(endPoint.y - startPoint.y,endPoint.x - startPoint.x)// 自定義箭頭路徑生成方法function getArrowPath(x, y, angle) {const length = 9 // 箭頭長度const width = 4 // 箭頭寬度// 計算箭頭三個點的坐標const x1 = xconst y1 = yconst x2 = x1 - widthconst y2 = y1 + lengthconst x3 = x1 + widthconst y3 = y1 + lengthreturn [['M', x, y], ['L', x2, y2], ['L', x3, y3], ['Z']]}// 在終點繪制自定義箭頭group.addShape('path', {attrs: {path: getArrowPath(endPoint.x, endPoint.y, 0),fill: '#8993AA',stroke: '#8993AA',lineWidth: 1,},})// //在邊上畫循環點const circle = group.addShape('ellipse', {attrs: {x: cfg.startPoint.x,y: cfg.startPoint.y,fill: 'l(0) 0:rgba(102,212,255,0.7) 1:#1A56FF',rx: 4,ry: 1,shadowColor: '#1A56FF',shadowBlur: 4,shadowOffsetY: 1,},name: 'circle-shape',})const time =(Math.abs(cfg.endPoint.x - cfg.startPoint.x) +Math.abs(cfg.endPoint.y - cfg.startPoint.y)) /0.05circle.show()circle.animate((ratio) => {const tmpPoint = shape.getPoint(ratio)const pos = G6.Util.getLabelPosition(shape, ratio)let matrix = [1, 0, 0, 0, 1, 0, 0, 0, 1]matrix = G6.Util.transform(matrix, [['t', -tmpPoint.x, -tmpPoint.y],['r', pos.angle],['t', tmpPoint.x, tmpPoint.y],])return {x: tmpPoint.x,y: tmpPoint.y,matrix,}},{repeat: true,duration: time,easing: 'easeLinear',delay: 0,})return shape},})//從上往下的邊G6.registerEdge('hvh3', {draw(cfg, group) {const startPoint = cfg.startPointconst endPoint = cfg.endPoint//默認顯示2個拐角let shape = nullif (cfg.corner) {//只顯示一個拐角shape = group.addShape('path', {attrs: {stroke: '#8993AA',path: [['M', startPoint.x, startPoint.y],['L', endPoint.x, startPoint.y],['L', endPoint.x, endPoint.y],],lineWidth: 1,lineDash: cfg.lineDash ? cfg.lineDash : '', // 自定義虛線模式},})} else {shape = group.addShape('path', {attrs: {stroke: '#8993AA',path: [['M', startPoint.x, startPoint.y],['L',startPoint.x,(2 / 3) * startPoint.y + (1 / 3) * endPoint.y,], // 三分之一處['L', endPoint.x, (2 / 3) * startPoint.y + (1 / 3) * endPoint.y], // 三分之二處['L', endPoint.x, endPoint.y],],lineWidth: 1,lineDash: cfg.lineDash ? cfg.lineDash : '', // 自定義虛線模式},})}// 計算箭頭方向const angle = Math.atan2(endPoint.y - startPoint.y,endPoint.x - startPoint.x)// 自定義箭頭路徑生成方法function getArrowPath(x, y, angle) {const length = 9 // 箭頭長度const width = 4 // 箭頭寬度// 計算箭頭三個點的坐標const x1 = xconst y1 = yconst x2 = x1 - widthconst y2 = y1 - lengthconst x3 = x1 + widthconst y3 = y1 - lengthreturn [['M', x, y], ['L', x2, y2], ['L', x3, y3], ['Z']]}// 在終點繪制自定義箭頭group.addShape('path', {attrs: {path: getArrowPath(endPoint.x, endPoint.y, 0),fill: '#8993AA',stroke: '#8993AA',lineWidth: 1,},})// //在邊上畫循環點const circle = group.addShape('ellipse', {attrs: {x: cfg.startPoint.x,y: cfg.startPoint.y,fill: 'l(0) 0:rgba(102,212,255,0.7) 1:#1A56FF',rx: 4,ry: 1,shadowColor: '#1A56FF',shadowBlur: 4,shadowOffsetY: 1,},name: 'circle-shape',})const time =(Math.abs(cfg.endPoint.x - cfg.startPoint.x) +Math.abs(cfg.endPoint.y - cfg.startPoint.y)) /0.05circle.show()circle.animate((ratio) => {const tmpPoint = shape.getPoint(ratio)const pos = G6.Util.getLabelPosition(shape, ratio)let matrix = [1, 0, 0, 0, 1, 0, 0, 0, 1]matrix = G6.Util.transform(matrix, [['t', -tmpPoint.x, -tmpPoint.y],['r', pos.angle],['t', tmpPoint.x, tmpPoint.y],])return {x: tmpPoint.x,y: tmpPoint.y,matrix,}},{repeat: true,duration: time < 1000 ? 1000 : time,easing: 'easeLinear',delay: 0,})return shape},})//從右往左的邊G6.registerEdge('hvh4', {draw(cfg, group) {const startPoint = cfg.startPointconst endPoint = cfg.endPointconst shape = group.addShape('path', {attrs: {stroke: '#8993AA',path: [['M', startPoint.x, startPoint.y],['L', startPoint.x - 20, startPoint.y], // 三分之一處['L',startPoint.x - 20,(1 / 3) * startPoint.y + (2 / 3) * endPoint.y,], // 三分之二處['L', endPoint.x, (1 / 3) * startPoint.y + (2 / 3) * endPoint.y], // 三分之二處['L', endPoint.x, endPoint.y],],lineWidth: 1,lineDash: cfg.lineDash ? cfg.lineDash : '', // 自定義虛線模式},})// 計算箭頭方向const angle = Math.atan2(endPoint.y - startPoint.y,endPoint.x - startPoint.x)// 自定義箭頭路徑生成方法function getArrowPath(x, y, angle) {const length = 9 // 箭頭長度const width = 4 // 箭頭寬度// 計算箭頭三個點的坐標const x1 = xconst y1 = yconst x2 = x1 - widthconst y2 = y1 - lengthconst x3 = x1 + widthconst y3 = y1 - lengthreturn [['M', x, y], ['L', x2, y2], ['L', x3, y3], ['Z']]}// 在終點繪制自定義箭頭group.addShape('path', {attrs: {path: getArrowPath(endPoint.x, endPoint.y, 0),fill: '#8993AA',stroke: '#8993AA',lineWidth: 1,},})// //在邊上畫循環點const circle = group.addShape('ellipse', {attrs: {x: cfg.startPoint.x,y: cfg.startPoint.y,fill: 'l(0) 0:rgba(102,212,255,0.7) 1:#1A56FF',rx: 4,ry: 1,shadowColor: '#1A56FF',shadowBlur: 4,shadowOffsetY: 1,},name: 'circle-shape',})const time =(Math.abs(cfg.endPoint.x - cfg.startPoint.x) +Math.abs(cfg.endPoint.y - cfg.startPoint.y)) /0.05circle.show()circle.animate((ratio) => {const tmpPoint = shape.getPoint(ratio)const pos = G6.Util.getLabelPosition(shape, ratio)let matrix = [1, 0, 0, 0, 1, 0, 0, 0, 1]matrix = G6.Util.transform(matrix, [['t', -tmpPoint.x, -tmpPoint.y],['r', pos.angle],['t', tmpPoint.x, tmpPoint.y],])return {x: tmpPoint.x,y: tmpPoint.y,matrix,}},{repeat: true,duration: time,easing: 'easeLinear',delay: 0,})return shape},})//自定義邊G6.registerEdge('hvh_custom', {draw(cfg, group) {const startPoint = cfg.startPointconst endPoint = cfg.endPointlet path = []//默認連接起始點和終端,中間的線段通過傳入的數組連接path.push(['M', startPoint.x, startPoint.y])for (let i = 0; i < cfg.path.length; i++) {path.push(['L', cfg.path[i][0], cfg.path[i][1]])}path.push(['L', endPoint.x, endPoint.y])const shape = group.addShape('path', {attrs: {stroke: '#8993AA',path: path,lineWidth: 1,lineDash: cfg.lineDash ? cfg.lineDash : '', // 自定義虛線模式},})// 自定義箭頭路徑生成方法function getArrowPath(x, y, direction) {const length = 9 // 箭頭長度const width = 4 // 箭頭寬度// 計算箭頭三個點的坐標const x1 = xconst y1 = ylet x2, y2, x3, y3if (direction == 'top') {x2 = x1 - widthy2 = y1 + lengthx3 = x1 + widthy3 = y1 + length} else if (direction == 'right') {x2 = x1 - lengthy2 = y1 - widthx3 = x1 - lengthy3 = y1 + width} else if (direction == 'bottom') {x2 = x1 - widthy2 = y1 - lengthx3 = x1 + widthy3 = y1 - length} else {//默認箭頭往左x2 = x1 + lengthy2 = y1 - widthx3 = x1 + lengthy3 = y1 + width}return [['M', x, y], ['L', x2, y2], ['L', x3, y3], ['Z']]}// 在終點繪制自定義箭頭group.addShape('path', {attrs: {path: getArrowPath(endPoint.x, endPoint.y, cfg.direction),fill: '#8993AA',stroke: '#8993AA',lineWidth: 1,},})// //在邊上畫循環點const circle = group.addShape('ellipse', {attrs: {x: cfg.startPoint.x,y: cfg.startPoint.y,fill: 'l(0) 0:rgba(102,212,255,0.7) 1:#1A56FF',rx: 4,ry: 1,shadowColor: '#1A56FF',shadowBlur: 4,shadowOffsetY: 1,},name: 'circle-shape',})const time =(Math.abs(cfg.endPoint.x - cfg.startPoint.x) +Math.abs(cfg.endPoint.y - cfg.startPoint.y)) /0.05circle.show()circle.animate((ratio) => {const tmpPoint = shape.getPoint(ratio)const pos = G6.Util.getLabelPosition(shape, ratio)let matrix = [1, 0, 0, 0, 1, 0, 0, 0, 1]matrix = G6.Util.transform(matrix, [['t', -tmpPoint.x, -tmpPoint.y],['r', pos.angle],['t', tmpPoint.x, tmpPoint.y],])return {x: tmpPoint.x,y: tmpPoint.y,matrix,}},{repeat: true,duration: time,easing: 'easeLinear',delay: 0,})// 計算邊的中點let midX = (startPoint.x + endPoint.x) / 2let midY = (startPoint.y + endPoint.y) / 2//自定義邊傳入的起始點及結束點if (cfg.labelCfg && cfg.labelCfg.startPoint && cfg.labelCfg.endPoint) {midX = (cfg.labelCfg.startPoint.x + cfg.labelCfg.endPoint.x) / 2midY = (cfg.labelCfg.startPoint.y + cfg.labelCfg.endPoint.y) / 2}// 計算邊的角度(用于文本旋轉)const angle2 = Math.atan2(endPoint.y - startPoint.y,endPoint.x - startPoint.x)// 添加上方文本if (cfg.label) {group.addShape('text', {attrs: {x: midX,y: midY - 6, // 上方偏移text: cfg.label,fill: cfg.labelCfg?.style?.fill || '#333',fontSize: cfg.labelCfg?.style?.fontSize || 12,textAlign: 'center',textBaseline: 'bottom',rotate: angle2,},})}// 添加下方文本if (cfg.subLabel) {group.addShape('text', {attrs: {x: midX,y: midY + 6, // 下方偏移text: cfg.subLabel,fill: cfg.subLabelCfg?.style?.fill || '#666',fontSize: cfg.subLabelCfg?.style?.fontSize || 12,textAlign: 'center',textBaseline: 'top',rotate: angle2,},})}return shape},})const graph = new G6.Graph({container: 'mountNode',width: 1380,height: mapHeight.value,minZoom: 0.4,maxZoom: 1,modes: {default: ['click-select',{ type: 'drag-canvas', enableOptimize: true },{type: 'zoom-canvas',optimizeZoom: true,shouldUpdate: () => false,onWheel: (e) => {e.preventDefault()const currentZoom = graph.getZoom()let ratio =e.wheelDelta > 0? Math.min(currentZoom + 0.1, 1): Math.max(currentZoom - 0.1, 0.4)graph.zoomTo(ratio, {x: graph.getWidth() / 2,y: graph.getHeight() / 2,})if (e.wheelDelta > 0 && ratio >= graph.getMaxZoom()) {graph.moveTo(0, 0)}},},],},// defaultNode: {// type: 'split-rect',// size: [120, 80],// style: { fill: '#FBEAEC', stroke: '#F8DDE0' },// label: '',// },defaultNode: {type: 'product-rect',size: [120, 80],style: { fill: '#FBEAEC', stroke: '#F8DDE0' },label: '',},defaultEdge: {type: 'hvh',zIndex: 2,},})graph.data({edges: edges.value,nodes: nodes.value,})graph.render()nextTick(() => {const edgeGroup = graph.get('edgeGroup')edgeGroup.toFront()graph.paint()})// 提取公共方法function resetNodeStates() {graph.getNodes().forEach((node) => {if (node.getStates().includes('highlight')) {node.clearStates('highlight')}})}function handleNodeClick(evt) {console.log('handleNodeClick')const { item } = evtconst model = item.getModel()if (item._cfg.currentShape === 'split-rect' && !item._cfg.model.noClick) {resetNodeStates()item.setState('highlight', true)if (item._cfg.model?.breedCode) {emit('breed-select', item._cfg.model.breedCode)}}}function handleNodeHover(ev, state) {const { item } = evif (['split-rect', 'breed-rect', 'ratio-rect', 'word-rect'].includes(item._cfg.currentShape)) {graph.setItemState(item, 'hover', state)}}graph.on('node:click', handleNodeClick)graph.on('node:mouseenter', (ev) => {graph.setAutoPaint(false)handleNodeHover(ev, true)graph.paint()graph.setAutoPaint(true)})graph.on('node:mouseleave', (ev) => {handleNodeHover(ev, false)})let startX = 0let startY = 0graph.on('node:mousedown', (e) => {if (e.item._cfg.currentShape === 'block-rect') {isDragging.value = truestartX = e.canvasXstartY = e.canvasY}})graph.on('node:mousemove', (e) => {if (isDragging.value) {const dx = e.canvasX - startXconst dy = e.canvasY - startYgraph.translate(dx, dy, false, { duration: 500, easing: 'easeLinear' })startX = e.canvasXstartY = e.canvasY}})graph.on('node:mouseup', () => {console.log('node:mouseup')isDragging.value = false//document.removeEventListener('mousemove', initDrag)})graph.on('canvas:mousemove', () => {isDragging.value = false//document.removeEventListener('mousemove', initDrag)})graph.on('canvas:mouseup', () => {isDragging.value = false//document.removeEventListener('mousemove', initDrag)})graph.on('viewportchange', () => {graph.refresh()graph.paint()})//默認選中品種graph.getNodes().forEach((node) => {// console.log('node', node._cfg.model.label)if (node._cfg.model.breedCode == window.breedCode) {node.setState('highlight', true)}})graph2.value = graphnextTick(() => {mapResize()})
}
const mapResize = () => {console.log('mapResize')nextTick(() => {let parentWidth = document.querySelector('.supply-analysis').clientWidthlet width = parentWidthlet autoHeight =((!isBlank.value? mapData[window.breedCode].mapHeight: defaultData.mapHeight) *width) /1426mapHeight.value = autoHeightmapPadding.value =((!isBlank.value? mapData[window.breedCode].mapPadding: defaultData.mapPadding) *width) /1376console.log('縮小比例', width / 1426)let ratio = document.getElementById('mountNode').clientWidth / 1376console.log('ratio', ratio)graph2.value &&graph2.value.zoomTo(ratio, {x: graph2.value.getWidth() / 2,y: graph2.value.getHeight() / 2,})graph2.value && graph2.value.moveTo(0, 0)})
}
//在移動節點過程中有時會丟失鼠標狀態,因此通過頁面監聽鼠標移動事件獲取鼠標狀態
const initDrag = (e) => {//console.log('initDrag', e)if (e) {if (e.which == 0) {isDragging.value = false}}
}
onMounted(() => {console.log('mapData', mapData)if (!isBlank.value) {//console.log('顯示銅產業鏈')edges.value = mapData[window.breedCode].edgesnodes.value = mapData[window.breedCode].nodesmapHeight.value = mapData[window.breedCode].mapHeightmapPadding.value = mapData[window.breedCode].mapPaddingdesc.value = mapData[window.breedCode].desc} else {edges.value = defaultData.edgesnodes.value = defaultData.nodesmapHeight.value = defaultData.mapHeightmapPadding.value = defaultData.mapPadding}const { menuCode } = route.querymenuCode && loadGraphData(menuCode)//通用模塊監聽事件proxy.$bus.on('echartResize', mapResize)document.addEventListener('mousemove', initDrag)
})
onBeforeUnmount(() => {proxy.$bus.off('echartResize', mapResize)document.removeEventListener('mousemove', initDrag)
})
</script>
<style lang="less" scoped>
.link-map {padding: 12px;.link-title {font-weight: 600;font-size: 16px;color: #333333;line-height: 24px;text-align: center;margin-bottom: 12px;}.link-desc {font-size: 12px;margin-top: -4px;margin-bottom: 12px;:deep(span:nth-child(1)) {color: #245a9a;}}
}
#mountNode {width: 100%;height: 449px;// border: 1px solid #efefef;position: relative;overflow: hidden;max-width: 1376px;margin: 0 auto;//max-height: 379.299px;
}
</style>