物管理前端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

791 lines
50 KiB

  1. const e="d772ad91-66dd-434d-8044-4e99d126c1cb",n="custom-3d-circle-pie",t="3d立体环形图",a='<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1697505891514" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="22469" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M485.179 112.66c-233.873 0-423.464 189.591-423.464 423.464s189.591 423.464 423.464 423.464 423.464-189.591 423.464-423.464S719.052 112.66 485.179 112.66z m0 712.663c-159.72 0-289.199-129.479-289.199-289.199s129.479-289.199 289.199-289.199 289.199 129.479 289.199 289.199-129.479 289.199-289.199 289.199z" fill="#0CA294" p-id="22470"></path><path d="M711.686 536.125h248.512c-0.148-261.822-212.44-474.024-474.296-474.024v248.51c124.608 0 225.636 100.941 225.784 225.514z" fill="#D73949" p-id="22471"></path></svg>',i="svg",o="动态",l="图表组件",p=!1,c=!0,r="时间",s=`{"type":"page","id":"u:270584784ce1","name":"page1","asideResizor":false,"style":{"boxShadow":" 0px 0px 0px 0px transparent"},"pullRefresh":{"disabled":true},"body":[{"type":"tabs","name":"tab","tabs":[{"title":"样式","icon":"fa fa-th-large","body":[{"type":"form","title":"","name":"basicPropForm","body":[{"type":"input-text","label":"名称","name":"nodeAlias","id":"u:6b126f0520cb","size":"full","mode":"horizontal","inputControlClassName":"w-100","className":"m-b"},{"type":"input-text","label":"ID&nbsp;&nbsp;&nbsp;&nbsp;","name":"id","id":"u:6232710ac003","size":"full","mode":"horizontal","inputControlClassName":"w-100","className":"m-b"},{"type":"grid","id":"u:c605398a724c","className":"m-b","columns":[{"body":[{"type":"input-number","label":"宽度","name":"width","keyboard":true,"id":"u:dcc0c21d16f6","step":1,"suffix":"px","placeholder":"组件左边距","size":"full","mode":"horizontal","className":"m-b","value":200,"labelAlign":"left","precision":2,"inputClassName":"w-full","labelClassName":"w-8"}],"id":"u:14cc19d6ffb0","md":6},{"body":[{"type":"input-number","label":"高度","name":"height","keyboard":true,"id":"u:cd6fdff9ca88","step":1,"suffix":"px","placeholder":"组件上边距","size":"full","mode":"horizontal","className":"m-b","value":200,"labelAlign":"left","precision":2,"inputClassName":"w-full","labelClassName":"w-8"}],"id":"u:4931801ca9b8","md":6}]},{"type":"grid","id":"u:da449a94908a","className":"m-b","columns":[{"body":[{"type":"input-number","label":"X 轴","name":"x","keyboard":true,"id":"u:29852d093d9d","step":1,"suffix":"px","placeholder":"组件左边距","size":"full","mode":"horizontal","className":"m-b","value":200,"labelAlign":"left","precision":2,"inputClassName":"w-full","labelClassName":"w-8"}],"id":"u:1b561d652acc","md":6},{"body":[{"type":"input-number","label":"Y 轴","name":"y","keyboard":true,"id":"u:dc8c1daed8ed","step":1,"suffix":"px","placeholder":"组件上边距","size":"full","mode":"horizontal","className":"m-b","value":200,"labelAlign":"left","precision":2,"inputClassName":"w-full","labelClassName":"w-8"}],"id":"u:9672575193ac","md":6}]},{"type":"grid","id":"u:a332a7bf83c1","className":"m-b","columns":[{"body":[{"type":"input-number","label":"旋转","name":"rotation","id":"u:f6a2dbb518f9","placeholder":"组件旋转角度","mode":"horizontal","size":"full","className":"","keyboard":true,"step":1,"suffix":"deg","value":0,"labelAlign":"left","inputClassName":"w-full"}],"id":"u:646cd98b7955","md":6},{"body":[{"type":"input-number","label":"透明","name":"opacity","id":"u:cf80f59d8d42","placeholder":"组件透明度","mode":"horizontal","size":"full","className":"m-b","keyboard":true,"step":0,"suffix":"","value":1,"inputClassName":"w-full","precision":2}],"id":"u:51ddf54ac749","md":6}],"gap":""},{"type":"grid","columns":[],"id":"u:235f153e5ad5","className":"m-b"},{"type":"grid","columns":[{"body":[{"type":"input-color","label":"图例颜色","name":"legendFontColor","id":"u:dcdc031da477","format":"hex","mode":"horizontal","inputClassName":"w-full myColorPick"}],"id":"u:656bda4e655b"},{"body
  2. "nodes": [
  3. {
  4. "id": "4b101b77-1d42-4894-8776-a3bbc4fa219f",
  5. "type": "custom-3d-circle-pie",
  6. "x": 200,
  7. "y": 200,
  8. "text": {
  9. "value": "",
  10. "x": 200,
  11. "y": 200
  12. },
  13. "properties": {
  14. "id": "4b101b77-1d42-4894-8776-a3bbc4fa219f",
  15. "width": 420,
  16. "height": 200,
  17. "x": 200,
  18. "y": 200,
  19. "rotation": 0,
  20. "opacity": 1,
  21. "codeConfig": "return option;",
  22. "nodeAlias": "3d立体环形图",
  23. "showDefaultValue": false,
  24. "showUnit": false,
  25. "valueColor": "rgba(245, 166, 35, 1)",
  26. "fontSize": 12,
  27. "legendFontColor": "#50e3c2",
  28. "labelTextColor": "#50e3c2",
  29. "unit": "kWh",
  30. "itemColors": [
  31. {
  32. "ratio": 0,
  33. "color": "#F6B54A"
  34. },
  35. {
  36. "color": "#CB5003"
  37. },
  38. {
  39. "color": "#0375AA"
  40. },
  41. {
  42. "color": "#8FC31F"
  43. },
  44. {
  45. "color": "#29ee92"
  46. }
  47. ],
  48. "tooltip": {
  49. "borderColor": "rgba(0, 141, 255, 0.6)",
  50. "backgroundColor": "rgba(70,94,144,0.6)",
  51. "style": {
  52. "color": "rgba(255, 255, 255, 1)"
  53. },
  54. "borderWidth": 1,
  55. "borderRadius": 6
  56. },
  57. "dynamic": {
  58. "normalData": {
  59. "dataPoint": "",
  60. "compareType": "",
  61. "conditionVariables": [],
  62. "defaultValue": "",
  63. "unit": "",
  64. "renderIntervalEnabled": true,
  65. "legendNameType": "attrName",
  66. "dataShowTypes": "oneThingOneAttr"
  67. }
  68. }
  69. }
  70. }
  71. ]
  72. }`,javascript:`const { createApp, createVNode, render } = Vue;
  73. const app = createApp({})
  74. const macaronColors = [
  75. "#FFC0CB", // 粉红色
  76. "#FFF44F", // 柠檬黄色
  77. "#87CEEB", // 天蓝色
  78. "#8A2BE2", // 紫罗兰色
  79. "#FFA500", // 橙色
  80. "#8DB600", // 绿苹果色
  81. "#FF007F", // 玫瑰红色
  82. "#9400D3", // 深紫色
  83. "#32CD32", // 青柠绿色
  84. "#FF9A8A", // 桃红色
  85. "#00008B", // 深蓝色
  86. "#20B2AA", // 青绿色
  87. "#8B0000", // 深红色
  88. "#32CD9A", // 柠檬绿色
  89. "#E6E6FA", // 浅紫色
  90. "#FF7F50", // 珊瑚橙色
  91. "#90EE90", // 浅绿色
  92. "#ADD8E6", // 浅蓝色
  93. "#FFDAB9", // 桃红色
  94. "#800080" // 紫色
  95. ];
  96. const defaultSocketValue = [];
  97. let myChart = null;
  98. // 修改3d饼图绘制过程
  99. var each = Highcharts.each,
  100. round = Math.round,
  101. cos = Math.cos,
  102. sin = Math.sin,
  103. deg2rad = Math.deg2rad;
  104. Highcharts.wrap(Highcharts.seriesTypes.pie.prototype, "translate", function (proceed) {
  105. proceed.apply(this, [].slice.call(arguments, 1));
  106. // Do not do this if the chart is not 3D
  107. if (!this.chart.is3d()) {
  108. return;
  109. }
  110. // 如果是右边当月用能占比饼图,则不执行此操作。
  111. if (this.chart.container.closest(".pie-3d-container")) {
  112. return;
  113. }
  114. let chart = this.chart,
  115. options = chart.options,
  116. seriesOptions = this.options,
  117. depth = seriesOptions.depth || 0,
  118. options3d = options.chart.options3d,
  119. alpha = options3d.alpha,
  120. beta = options3d.beta,
  121. z = seriesOptions.stacking ? (seriesOptions.stack || 0) * depth : this._i * depth;
  122. z += depth / 2;
  123. if (seriesOptions.grouping !== false) {
  124. z = 0;
  125. }
  126. var series = this.center;
  127. each(this.data, function (point) {
  128. var shapeArgs = point.shapeArgs,
  129. angle;
  130. point.shapeType = "arc3d";
  131. var ran = point.options.h;
  132. shapeArgs.z = z;
  133. shapeArgs.depth = depth * 0.75 + ran;
  134. shapeArgs.alpha = alpha;
  135. shapeArgs.beta = beta;
  136. shapeArgs.center = series;
  137. shapeArgs.ran = ran;
  138. angle = (shapeArgs.end + shapeArgs.start) / 2;
  139. point.slicedTranslation = {
  140. translateX: round(cos(angle) * seriesOptions.slicedOffset * cos(alpha * deg2rad)),
  141. translateY: round(sin(angle) * seriesOptions.slicedOffset * cos(alpha * deg2rad))
  142. };
  143. });
  144. });
  145. (function (H) {
  146. H.wrap(Highcharts.SVGRenderer.prototype, "arc3dPath", function (proceed) {
  147. // Run original proceed method
  148. var ret = proceed.apply(this, [].slice.call(arguments, 1));
  149. ret.zTop = (ret.zOut + 0.5) / 100;
  150. return ret;
  151. });
  152. })(Highcharts);
  153. // 图例格式化
  154. const assembleLegend = (api, thingKey, attrkey, dataShowTypes, legendNameType, datas) => {
  155. if (api) {
  156. const infos = window.totalDeviceInfos[api];
  157. const thing = infos[datas[0].thingCode];
  158. const thingName = thing.entityName;
  159. const attrName = thing.attrs[attrkey].name;
  160. if (dataShowTypes.value === 'oneThingOneAttr') {
  161. switch (legendNameType.value) {
  162. case "thingName":
  163. return thing.entityName;
  164. case "thingCode":
  165. return thingKey;
  166. case "attrName":
  167. return attrName;
  168. case "attrCode":
  169. return attrkey;
  170. case "thingNameAttrName":
  171. return thingName + '-' + attrName;
  172. case "thingCodeAttrCode":
  173. return thingKey + '-' + attrkey;
  174. }
  175. } else if (dataShowTypes.value === 'oneThingManyAttr') {
  176. switch (legendNameType.value) {
  177. case "attrName":
  178. return thing.attrs[attrkey].name;
  179. case "attrCode":
  180. return attrkey;
  181. case "thingNameAttrName":
  182. return thingName + '-' + attrName;
  183. case "thingCodeAttrCode":
  184. return thingKey + '-' + thingKey
  185. }
  186. } else if (dataShowTypes.value === 'manyThingManyAttr') {
  187. switch (legendNameType.value) {
  188. case "thingNameAttrName":
  189. const attrName = thing.attrs[attrKey].name
  190. return thingName + '-' + attrName;
  191. case "thingCodeAttrCode":
  192. return thingKey + '-' + thingKey;
  193. }
  194. } else if (dataShowTypes.value === 'manyThingOneAttr') {
  195. switch (legendNameType.value) {
  196. case "thingName":
  197. return thingName;
  198. case "thingCode":
  199. return thingKey;
  200. case "thingNameAttrName":
  201. const attrName = thing.attrs[attrKey].name
  202. return thingName + '-' + attrName;
  203. case "thingCodeAttrCode":
  204. return thingKey + '-' + thingKey;
  205. }
  206. }
  207. } else {
  208. return attrkey;
  209. }
  210. }
  211. const PieChartCircle3D = {
  212. template: '<div :id="lineId" :style="getStyle" class="highcharts-wrapper pie-3d-circle-chart"></div>',
  213. props: {
  214. lineId: {
  215. type: String,
  216. default: ''
  217. },
  218. historyDatas: {
  219. type: Array,
  220. default: () => []
  221. },
  222. width: {
  223. type: Number,
  224. default: 350
  225. },
  226. height: {
  227. type: Number,
  228. default: 150
  229. },
  230. codeConfig: {
  231. type: String,
  232. default: ''
  233. },
  234. legendFontColor: {
  235. type: String,
  236. default: ''
  237. },
  238. labelTextColor: {
  239. type: String,
  240. default: ''
  241. },
  242. valueColor: {
  243. type: String,
  244. default: ''
  245. },
  246. unit: {
  247. type: String,
  248. default: ''
  249. },
  250. dataShowTypes: {
  251. type: String,
  252. default: 'oneThingManyAttr',
  253. },
  254. legendNameType: {
  255. type: String,
  256. default: 'attrName',
  257. },
  258. apiid: {
  259. type: String,
  260. default: '',
  261. },
  262. itemColors: {
  263. type: Array,
  264. default: () => [
  265. {
  266. "ratio":
  267. 0,
  268. "color":
  269. "#F6B54A"
  270. },
  271. {
  272. "color":
  273. "#CB5003"
  274. },
  275. {
  276. "color":
  277. "#0375AA"
  278. },
  279. {
  280. "color":
  281. "#8FC31F"
  282. },
  283. {
  284. "color":
  285. "#29ee92"
  286. }
  287. ]
  288. },
  289. tooltip: {
  290. type: Object,
  291. default: () => ({
  292. backgroundColor: "rgba(70,94,144,0.6)",
  293. borderColor: "rgba(0, 141, 255, 0.6)",
  294. borderRadius: 6,
  295. borderWidth: 1,
  296. style: {
  297. color: "#fff"
  298. }
  299. })
  300. }
  301. },
  302. computed: {
  303. getStyle() {
  304. return {
  305. width: \`\${this.width}px\`,
  306. height: \`\${this.height}px\`
  307. }
  308. }
  309. },
  310. setup(props) {
  311. const { onMounted, nextTick, toRefs, watch } = Vue;
  312. const { historyDatas, codeConfig, dataShowTypes, legendNameType, apiid, itemColors, tooltip, unit } = toRefs(props);
  313. const initChart = (datas) => {
  314. // 基于准备好的dom,初始化echarts实例
  315. const dom = document.getElementById(props.lineId);
  316. if (dom) {
  317. if (myChart) {
  318. myChart.destroy();
  319. myChart = null;
  320. }
  321. if (datas) {
  322. let totalDatas = [];
  323. let totalAmount = 0;
  324. let legends = [];
  325. if (datas.length > 0) {
  326. const thingGrouped = window._.groupBy(datas, 'thingCode');
  327. for (const thingKey in thingGrouped) {
  328. const attrGrouped = window._.groupBy(thingGrouped[thingKey], 'attrKey')
  329. for (const key in attrGrouped) {
  330. let serieData = attrGrouped[key];
  331. const legendKey = assembleLegend(apiid.value, thingKey, key, dataShowTypes, legendNameType, serieData);
  332. legends.push(legendKey);
  333. totalDatas.push({ name: legendKey, h: 0, y: Number(serieData[0].val), bfb: 0, unit: unit.value });
  334. totalAmount += Number(serieData[0].val);
  335. }
  336. }
  337. totalDatas = totalDatas.map(i => {
  338. i.h = Number(((i.y / totalAmount) * 100).toFixed(0));
  339. return i;
  340. })
  341. } else {
  342. totalDatas = [
  343. {
  344. name: "红草莓",
  345. y: 10254,
  346. h: 30,
  347. bfb: 0
  348. },
  349. {
  350. name: "白草莓",
  351. y: 6894,
  352. h: 18,
  353. bfb: 0
  354. },
  355. {
  356. name: "红颜草莓",
  357. y: 7667,
  358. h: 20,
  359. bfb: 0
  360. },
  361. {
  362. name: "甜宝草莓",
  363. y: 4287,
  364. h: 12,
  365. bfb: 0
  366. },
  367. ]
  368. }
  369. const serieColors = itemColors.value.concat(macaronColors).map(i => {
  370. return {
  371. // 注意!!!如果是柱状图请使用color,如果是面积图请使用fillColor
  372. linearGradient: {
  373. x1: 0,
  374. y1: 1,
  375. x2: 1,
  376. y2: 0
  377. },
  378. stops: [
  379. [0, i.color || i],
  380. [1, i.color || i]
  381. ]
  382. }
  383. })
  384. // 指定图表的配置项和数据
  385. var option = {
  386. chart: {
  387. type: "pie",
  388. accessibility: {
  389. enabled: false
  390. },
  391. reflow: true,
  392. backgroundColor: "rgba(0, 0, 0, 0)",
  393. events: {
  394. load: function () {
  395. const each = Highcharts.each;
  396. const points = this.series[0].points;
  397. each(points, function (p, i) {
  398. p.graphic.attr({
  399. translateY: -p.shapeArgs.ran
  400. });
  401. p.graphic.side1.attr({
  402. translateY: -p.shapeArgs.ran
  403. });
  404. p.graphic.side2.attr({
  405. translateY: -p.shapeArgs.ran
  406. });
  407. });
  408. }
  409. },
  410. options3d: {
  411. enabled: true,
  412. alpha: 65,
  413. beta: 0
  414. }
  415. },
  416. navigation: {
  417. align: 'right'
  418. },
  419. legend: {
  420. enabled: false,
  421. layout: 'horizontal',
  422. itemHoverStyle: { color: "#34dcfc" },
  423. symbolWidth: 16,
  424. symbolHeight: 14,
  425. symbolRadius: 3,
  426. },
  427. tooltip: {
  428. animation: true,
  429. formatter: function () {
  430. return \`<span style="color:\${tooltip.value.style.color}">\${this.point.name} : \${this.point.y} </span>\`;
  431. },
  432. // pointFormat: \`<b>{series.name}: {point.percentage:.1f}%</b>\`,
  433. ...tooltip.value
  434. },
  435. exporting: {
  436. enabled: false
  437. },
  438. credits: {
  439. enabled: false
  440. },
  441. title: {
  442. show: "false",
  443. text: ""
  444. },
  445. subtitle: {
  446. text: ""
  447. },
  448. plotOptions: {
  449. pie: {
  450. depth: 35,
  451. allowPointSelect: false,
  452. cursor: "pointer",
  453. innerSize: 68,
  454. size: "85%",
  455. dataLabels: {
  456. enabled: true,
  457. // format: \`<b>{point.name}</b> + <b style='color: #ffffff'>{point.percentage:.1f} %</b><\\n><\`,
  458. formatter: function () {
  459. return \`<span style='color: \${props.labelTextColor};font-size:12px;'>\${this.point.name} </span><span style='color: \${props.valueColor};font-size:12px;'>\${this.point.y} \${unit.value}</span>\`;
  460. // return "<span style='color: #ffffff'>" + this.point.name + "</span> " + "<span style='color: #2B95CC'>" + this.percentage.toFixed(2) + "%</span>";
  461. },
  462. connectorColor: "#02AAD0",
  463. style: {
  464. textOverflow: "ellipsis",
  465. textOutline: "none"
  466. }
  467. },
  468. // 显示图例
  469. showInLegend: true
  470. }
  471. },
  472. series: [
  473. {
  474. type: "pie",
  475. name: "",
  476. colorByPoint: true, // h 是高度 y是占的圆环长度
  477. colors: serieColors,
  478. data: totalDatas
  479. }
  480. ]
  481. };
  482. const func = new Function('option', 'datas', codeConfig.value);
  483. const opt = func(window._.cloneDeep(option), datas);
  484. // 使用刚指定的配置项和数据显示图表。
  485. nextTick(() => {
  486. myChart = Highcharts.chart(props.lineId, opt);
  487. myChart.unit = props.unit;
  488. Highcharts.addEvent(myChart, "redraw", function () {
  489. var each = Highcharts.each;
  490. const points = myChart.series[0].points;
  491. each(points, function (p, i) {
  492. // if (i !== 1 && i !== 2) {
  493. p.graphic.attr({
  494. translateY: -p.shapeArgs.ran
  495. });
  496. p.graphic.side1.attr({
  497. translateY: -p.shapeArgs.ran
  498. });
  499. p.graphic.side2.attr({
  500. translateY: -p.shapeArgs.ran
  501. });
  502. });
  503. setTimeout(() => {
  504. document.querySelector('.highcharts-scrollable-legend .highcharts-legend').setAttribute('transform', 'translate(0,0)');
  505. }, 1000)
  506. });
  507. myChart.reflow();
  508. setTimeout(() => {
  509. // 手动创建横向的滚动图例
  510. const frags = document.createDocumentFragment();
  511. totalDatas.forEach((i, index) => {
  512. const div = document.createElement('div');
  513. div.style = 'display: inline-block; margin-right: 10px;';
  514. const span = document.createElement('span');
  515. const color = serieColors[index].stops[0][1];
  516. span.style = \`display: inline-block;width: 12px; height: 12px; background-color: \${color}; border-radius: 2px; margin-right: 3px;\`;
  517. const span2 = document.createElement('span');
  518. span2.style = \`color: \${props.legendFontColor}\`;
  519. span2.innerHTML = i.name;
  520. div.appendChild(span);
  521. div.appendChild(span2);
  522. frags.appendChild(div)
  523. })
  524. const wrapper = document.createElement('div');
  525. wrapper.className = "my-highcharts-legend-wrapper"
  526. wrapper.style = "position: absolute; bottom: 0; left: 0; righit: 0; width: 100%; height: 16px; display: block; overflow-x: auto; overflow: hidden; padding: 0 32px 0px 16px; box-sizing: border-box;";
  527. const inner = document.createElement('div');
  528. inner.style = 'display: inline-block; width: max-content;';
  529. inner.className = 'my-highcharts-legend-inner';
  530. inner.appendChild(frags);
  531. wrapper.appendChild(inner);
  532. setTimeout(() => {
  533. if (wrapper.offsetWidth < inner.offsetWidth) {
  534. // 左箭头
  535. const leftArrow = document.createElement('span');
  536. leftArrow.style = \` position: absolute;
  537. left: 2px;
  538. top: 2px;
  539. display: inline-block;
  540. width:8px;
  541. height: 8px;
  542. border-right: 2px solid \${props.legendFontColor};
  543. border-bottom: 2px solid \${props.legendFontColor};
  544. -webkit-transform: rotate(135deg);cursor: pointer;\`
  545. const rightArrow = document.createElement('span');
  546. rightArrow.style = \`position: absolute;
  547. right: 2px;
  548. top: 2px;
  549. display: inline-block;
  550. width:8px;
  551. height: 8px;
  552. border-right: 2px solid \${props.legendFontColor};
  553. border-bottom: 2px solid \${props.legendFontColor};
  554. -webkit-transform: rotate(-45deg);cursor: pointer\`;
  555. wrapper.appendChild(leftArrow);
  556. wrapper.appendChild(rightArrow);
  557. let translation = 0;
  558. const prev = () => {
  559. if (translation >= 0) {
  560. return;
  561. } else {
  562. translation += 20;
  563. inner.style.transform = \`translateX(\${translation}px)\`;
  564. }
  565. }
  566. const next = () => {
  567. if (inner.offsetWidth - wrapper.offsetWidth <= Math.abs(translation)) {
  568. return;
  569. } else {
  570. translation -= 20;
  571. inner.style.transform = \`translateX(\${translation}px)\`;
  572. }
  573. }
  574. leftArrow.addEventListener('click', prev);
  575. rightArrow.addEventListener('click', next);
  576. }
  577. }, 500)
  578. const compWrapper = document.getElementById(props.lineId);
  579. compWrapper.style.position = 'relative';
  580. compWrapper.appendChild(wrapper);
  581. })
  582. })
  583. }
  584. }
  585. }
  586. watch(historyDatas, (val) => {
  587. if (val) {
  588. nextTick(() => {
  589. initChart(val);
  590. })
  591. }
  592. }, {
  593. immediate: true
  594. })
  595. }
  596. }
  597. class Custom3DPieCircleNode extends HtmlResize.view {
  598. chartRendered = false
  599. historyDatas = []
  600. oldProperties = {}
  601. setHtml(rootEl) {
  602. if (!rootEl) return;
  603. const { properties, width, height, } = this.props.model;
  604. const { nodeAlias, grid, title, legend, tooltip, xAxis, yAxis, codeConfig, legendFontColor, labelTextColor, valueColor, unit, apiid, itemColors } = properties;
  605. const { normalData } = properties.dynamic || {};
  606. const { dataShowTypes, legendNameType } = normalData || {};
  607. const el = document.createElement('div');
  608. rootEl.innerHTML = '';
  609. const instance = createVNode(PieChartCircle3D, {
  610. name: nodeAlias,
  611. lineId: \`line-\${properties.id}\`,
  612. historyDatas: this.historyDatas,
  613. width,
  614. height,
  615. grid, title, legend, tooltip, xAxis, yAxis,
  616. codeConfig,
  617. legendFontColor,
  618. labelTextColor,
  619. valueColor, unit,
  620. dataShowTypes, legendNameType, apiid,
  621. itemColors,
  622. tooltip,
  623. })
  624. instance.appContext = app._context
  625. render(instance, el)
  626. rootEl.appendChild(el);
  627. }
  628. sameProps(properties) {
  629. const isSame = window._.isEqual(this.oldProperties, properties);
  630. if (isSame) return true;
  631. this.oldProperties = properties;
  632. return false
  633. }
  634. filterHistoryData(thingCodeArr, dataPointArr, apiid, renderIntervalEnabled) {
  635. if (dataPointArr && dataPointArr.length > 0) {
  636. let datas = []
  637. if (renderIntervalEnabled) {
  638. datas = window.totalHistoryDatas[apiid];
  639. } else {
  640. if (window.globalDashboardDatas[apiid]) {
  641. datas = window.globalDashboardDatas[apiid].values;
  642. }
  643. }
  644. if (datas && datas.length > 0) {
  645. const gotValues = datas.filter((val) => thingCodeArr.includes(val.thingCode) && dataPointArr.includes(val.attrKey))
  646. this.historyDatas = gotValues
  647. this.chartRendered = true;
  648. }
  649. }
  650. }
  651. // 生命周期 支持重写内容, 但格式需一致
  652. shouldUpdate() {
  653. const { properties } = this.props.model;
  654. const { apiid } = properties;
  655. const { normalData } = properties.dynamic || {};
  656. const { thingCodeArr, dataPointArr, defaultValue } = normalData || {}
  657. if (normalData && !normalData.dataPoint && !normalData.defaultValue) {
  658. this.historyDatas = defaultSocketValue;
  659. return true
  660. } else if (normalData && !normalData.dataPoint && normalData.defaultValue) {
  661. this.historyDatas = JSON.parse(defaultValue);
  662. return true
  663. }
  664. const propertiesBack = window._.cloneDeep(properties);
  665. if (propertiesBack.dynamic.normalData) {
  666. propertiesBack.dynamic.normalData.defaultValue = '';
  667. if (this.sameProps(propertiesBack) && this.chartRendered) {
  668. return false
  669. }
  670. if (dataPointArr && apiid && !this.chartRendered) {
  671. this.filterHistoryData(thingCodeArr, dataPointArr, apiid, normalData.renderIntervalEnabled);
  672. return true;
  673. }
  674. }
  675. return true;
  676. }
  677. updateHtml() {
  678. this.setHtml(this.rootEl);
  679. }
  680. componentDidMount() {
  681. const { properties } = this.props.model;
  682. const { normalData } = properties.dynamic || {};
  683. const { renderInterval, dataPointArr, thingCodeArr } = normalData || {};
  684. if (this.shouldUpdate()) {
  685. this.setHtml(this.rootEl);
  686. }
  687. const initRender = () => {
  688. // 第一次历史数据返回可能比较慢,轮询判断
  689. let times = 0
  690. const inter = setInterval(() => {
  691. if (window.totalHistoryDatas && window.totalHistoryDatas[properties.apiid]) {
  692. this.filterHistoryData(thingCodeArr, dataPointArr, properties.apiid, normalData.renderIntervalEnabled);
  693. this.setHtml(this.rootEl);
  694. clearInterval(inter);
  695. }
  696. if (times > 20) {
  697. clearInterval(inter)
  698. }
  699. times++;
  700. }, 1000)
  701. }
  702. initRender();
  703. let inters = parseInt(renderInterval || '300000')
  704. if (normalData && !normalData.renderIntervalEnabled) {
  705. inters = 1000
  706. }
  707. setInterval(() => {
  708. if (window.totalHistoryDatas[properties.apiid]) {
  709. this.filterHistoryData(thingCodeArr, dataPointArr, properties.apiid, normalData.renderIntervalEnabled);
  710. this.setHtml(this.rootEl);
  711. }
  712. }, inters)
  713. // 防止拖动时候频繁渲染图表
  714. this.updateHtmlDebounced = window._.debounce(this.updateHtml.bind(this), 500);
  715. }
  716. componentDidUpdate() {
  717. if (this.shouldUpdate()) {
  718. this.updateHtmlDebounced();
  719. }
  720. }
  721. }
  722. class Custom3DPieCircleModel extends HtmlResize.model {
  723. initNodeData(data) {
  724. // 自定义组件,需最开始重置一下text 。
  725. data.text = {
  726. value: "",
  727. x: data.x,
  728. y: data.y,
  729. };
  730. super.initNodeData(data);
  731. const { properties } = this;
  732. this.width = properties.width || 80;
  733. this.height = properties.height || 35;
  734. this.text.editable = false; // 不允许文本被编辑
  735. }
  736. setAttributes() {
  737. // 自定义组件需重置 text
  738. const { x, y, properties } = this;
  739. const { textHorizontalMove = 0, textVerticalMove = 0 } = properties;
  740. this.text = {
  741. ...this.text,
  742. x: x + textHorizontalMove,
  743. y: y + textVerticalMove,
  744. value: "",
  745. }
  746. }
  747. }
  748. lf.register({
  749. type: 'custom-3d-circle-pie',
  750. view: Custom3DPieCircleNode,
  751. model: Custom3DPieCircleModel,
  752. })`,css:`.pie-3d-circle-chart .highcharts-root {\r
  753. stroke: none;\r
  754. }\r
  755. .highcharts-legend {\r
  756. overflow-y: hidden !important;\r
  757. }`,fakeData:""},u={id:e,name:n,aliasName:t,image:a,imageType:i,groupName:o,groupType:l,isRemote:!1,isDefault:!0,sectionType:r,config:s,files:d};export{t as aliasName,s as config,u as default,d as files,o as groupName,l as groupType,e as id,a as image,i as imageType,c as isDefault,p as isRemote,n as name,r as sectionType};