物管理前端
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.

719 lines
68 KiB

  1. const e="be616a00-e2bc-4849-8b28-8cdd35cd198b",a="custom-bar-chart",t="柱状图",n='<?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="1694685702418" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4058" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M290.15 503.877l-149.461-2.114v333.16H290.15z" fill="#D73949" p-id="4059"></path><path d="M497.316 227.066l-149.462-3.883v611.74h149.462z" fill="#0CA294" p-id="4060"></path><path d="M704.481 368.468l-149.461-2.98v469.435h149.461z" fill="#35A0D6" p-id="4061"></path><path d="M911.647 638.005l-149.462-1.258v198.176h149.462z" fill="#D97B24" p-id="4062"></path><path d="M102.139 885.365V98.152H65.063v830.142h895.855v-42.929z" fill="#819292" p-id="4063"></path></svg>',i="svg",l="动态",o="图表组件",u=!1,c=!0,s="时序",d=`{"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":"radios","label":"渲染模式","name":"renderMode","options":[{"label":"canvas","value":"canvas"},{"label":"svg","value":"svg"}],"id":"u:047a1336613a","mode":"horizontal"},{"type":"fieldset","id":"u:2a93d8eee7a9","className":"","title":"布局","collapsable":true,"body":[{"type":"co
  2. "nodes": [
  3. {
  4. "id": "a3c0bb09-4bc9-4717-8adc-ff83e5eee086",
  5. "type": "custom-bar-chart",
  6. "x": 200,
  7. "y": 200,
  8. "text": {
  9. "value": "",
  10. "x": 200,
  11. "y": 200
  12. },
  13. "properties": {
  14. "id": "a3c0bb09-4bc9-4717-8adc-ff83e5eee086",
  15. "width": 350,
  16. "height": 250,
  17. "x": 200,
  18. "y": 200,
  19. "rotation": 0,
  20. "opacity": 1,
  21. "grid": {
  22. "show": false,
  23. "top": "25",
  24. "left": "30",
  25. "right": "15",
  26. "bottom": "20"
  27. },
  28. "title": {
  29. "show": true,
  30. "padding": "",
  31. "left": "30",
  32. "right": "2",
  33. "top": "2",
  34. "bottom": "2",
  35. "text": "kWh",
  36. "textAlign": "auto",
  37. "textVerticalAlign ": "middle"
  38. },
  39. "legend": {
  40. "show": true,
  41. "orient": "horizontal"
  42. },
  43. "tooltip": {
  44. "show": true,
  45. "showContent": true,
  46. "trigger": "axis",
  47. "backgroundColor": "rgba(0, 0, 0, 0.5)",
  48. "textStyle": {
  49. "color": "rgba(255, 255, 255, 1)"
  50. }
  51. },
  52. "xAxis": {
  53. "show": true,
  54. "axisLine": {
  55. "show": true
  56. },
  57. "axisTick": {
  58. "show": true
  59. },
  60. "axisLabel": {
  61. "show": true,
  62. "fontSize": 12
  63. },
  64. "splitLine": {
  65. "show": false
  66. },
  67. "type ": "category",
  68. "name": "",
  69. "nameColor": ""
  70. },
  71. "yAxis": {
  72. "show": true,
  73. "axisLine": {
  74. "show": true
  75. },
  76. "axisTick": {
  77. "show": true
  78. },
  79. "axisLabel": {
  80. "show": true,
  81. "fontSize": 12
  82. },
  83. "splitLine": {
  84. "show": false
  85. },
  86. "type ": "value"
  87. },
  88. "codeConfig": "option.color = ['#80FFA5', '#00DDFF', '#37A2FF', '#FF0087', '#FFBF00'];\\r\\n\\r\\n// 值保留为两位小数。\\r\\noption.valueFormatter = (value) => {\\r\\n if (typeof value === 'number') {\\r\\n return value.toFixed(2);\\r\\n } else {\\r\\n return value\\r\\n }\\r\\n};\\r\\n\\r\\noption.series.forEach((item) => {\\r\\n // item.stack = \\"total\\";\\r\\n})\\r\\n\\r\\n\\r\\n\\r\\nreturn option;",
  89. "fontSize": 0,
  90. "showDefaultValue": false,
  91. "showUnit": false,
  92. "nodeAlias": "柱状图",
  93. "renderMode": "canvas",
  94. "dynamic": {
  95. "normalData": {
  96. "dataPoint": "",
  97. "compareType": "",
  98. "conditionVariables": [],
  99. "defaultValue": "",
  100. "unit": "",
  101. "renderIntervalEnabled": true,
  102. "completeDatas": false,
  103. "legendNameType": "attrName",
  104. "customDatasource": false,
  105. "timeAxisFormatter": "",
  106. "dataShowTypes": "oneThingManyAttr",
  107. "requestMethod": "get",
  108. "requestParams": "return {};",
  109. "dataFilterFn": "// datas 数据处理\\n// .....\\n"
  110. }
  111. }
  112. }
  113. }
  114. ]
  115. }`,javascript:`const { createApp, createVNode, render } = Vue;
  116. const app = createApp({})
  117. const timeArr = new Array(24).fill('');
  118. const totals = [];
  119. timeArr.forEach((i, index) => { const t = window.dayjs().hour(index).valueOf(); totals.push({ val: Math.random(1000) * 100, ts: t, attrKey: "A29", thingCode: 'A001' }) });
  120. const defaultSocketValue = totals
  121. const xAxisLabelFormatter = function (val) {
  122. if (this.timeCompare) return;
  123. if (this.timeAxisFormatter) {
  124. return dayjs(+val).format(this.timeAxisFormatter);
  125. }
  126. const { months, days } = this;
  127. if (months === 0 && days === 0) {
  128. return dayjs(+val).format("HH:mm");
  129. } else if (months === 0 && days > 0) {
  130. return dayjs(+val).format("DD HH:mm");
  131. } else if (months > 0 && days >= 0) {
  132. return dayjs(+val).format("MM-DD HH:mm");
  133. }
  134. };
  135. // 工具提示格式化
  136. const tooltipFormatter = function (params) {
  137. let strs = "";
  138. const timeFormatterMap = {
  139. "HH": '时',
  140. "DD": '日',
  141. 'MM': '月'
  142. }
  143. const time = this.timeCompare ? params[0].name : window.dayjs.unix(+params[0].name / 1000).format(this.timeAxisFormatter || "YYYY-MM-DD HH:mm:ss");
  144. strs += \`<div>\${time} \${timeFormatterMap[this.timeAxisFormatter] || ''}</div>\`;
  145. params.forEach((param) => {
  146. strs += param.marker + "&nbsp" + param.seriesName + ":&nbsp&nbsp" + Number(param.value).toFixed(2) + "<br/>";
  147. })
  148. return strs;
  149. };
  150. // 图例格式化
  151. const assembleLegend = (api, thingKey, attrkey, dataShowTypes, legendNameType, datas) => {
  152. if (api) {
  153. const infos = window.totalDeviceInfos[api];
  154. if (!infos) return;
  155. if (!datas[0]) return;
  156. const thing = infos[datas[0].thingCode];
  157. if (!thing) return;
  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 BarChart = {
  212. template: '<div :id="lineId" :style="getStyle" class="custom-bar-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. grid: {
  231. type: Object,
  232. default: () => { }
  233. },
  234. title: {
  235. type: Object,
  236. default: () => { }
  237. },
  238. legend: {
  239. type: Object,
  240. default: () => { }
  241. },
  242. tooltip: {
  243. type: Object,
  244. default: () => { }
  245. },
  246. xAxis: {
  247. type: Object,
  248. default: () => { }
  249. },
  250. yAxis: {
  251. type: Object,
  252. default: () => { }
  253. },
  254. codeConfig: {
  255. type: String,
  256. default: ''
  257. },
  258. timeAxisFormatter: {
  259. type: String,
  260. default: ''
  261. },
  262. completeDatas: {
  263. type: Boolean,
  264. default: false
  265. },
  266. totalTimes: {
  267. type: Array,
  268. default: () => []
  269. },
  270. timeCompare: {
  271. type: String,
  272. default: '',
  273. },
  274. dataShowTypes: {
  275. type: String,
  276. default: 'oneThingManyAttr',
  277. },
  278. legendNameType: {
  279. type: String,
  280. default: 'attrName',
  281. },
  282. apiid: {
  283. type: String,
  284. default: '',
  285. },
  286. renderMode: {
  287. type: String,
  288. default: 'canvas',
  289. }
  290. },
  291. computed: {
  292. getStyle() {
  293. return {
  294. width: \`\${this.width}px\`,
  295. height: \`\${this.height}px\`
  296. }
  297. }
  298. },
  299. setup(props) {
  300. const { onMounted, nextTick, toRefs, watch } = Vue;
  301. const { grid, title, legend, tooltip, xAxis, yAxis, historyDatas, codeConfig, timeAxisFormatter, completeDatas, totalTimes, timeCompare, dataShowTypes, legendNameType, apiid, renderMode } = toRefs(props)
  302. const tooltipFormatterBound = tooltipFormatter.bind({ timeCompare: timeCompare.value, timeAxisFormatter: timeAxisFormatter.value });
  303. let myChart = null;
  304. let timeCompareMap = {
  305. 'day': {
  306. prev: '昨日',
  307. curr: '今日'
  308. },
  309. 'month': {
  310. prev: '上月',
  311. curr: '当月'
  312. },
  313. 'year': {
  314. prev: '去年',
  315. curr: '今年'
  316. },
  317. }
  318. const initChart = (datas) => {
  319. // 基于准备好的dom,初始化echarts实例
  320. const dom = document.getElementById(props.lineId);
  321. if (dom && !myChart) {
  322. if (!myChart) {
  323. myChart = echarts.init(dom, null, {
  324. renderer: renderMode.value
  325. });
  326. }
  327. if (datas) {
  328. let series = [];
  329. let legends = [];
  330. let xAxisData = [];
  331. let xAxisLabelFormatterBound = null;
  332. if (datas.length > 0) {
  333. const thingGrouped = window._.groupBy(datas, 'thingCode');
  334. for (const thingKey in thingGrouped) {
  335. const attrGrouped = window._.groupBy(thingGrouped[thingKey], 'attrKey')
  336. const keysLen = Object.keys(attrGrouped).length;
  337. for (const key in attrGrouped) {
  338. let serieData = attrGrouped[key];
  339. const legendKey = assembleLegend(apiid.value, thingKey, key, dataShowTypes, legendNameType, serieData);
  340. legends.push(legendKey);
  341. if (!xAxisLabelFormatterBound) {
  342. const first = serieData[0];
  343. const last = serieData[serieData.length - 1];
  344. if (first.ts > last.ts) {
  345. serieData = serieData.reverse()
  346. }
  347. const dayjs = window.dayjs;
  348. const firstDay = dayjs(+first.ts);
  349. const lastDay = dayjs(+last.ts);
  350. const days = firstDay.diff(lastDay, 'day');
  351. const months = firstDay.diff(lastDay, 'month');
  352. xAxisLabelFormatterBound = xAxisLabelFormatter.bind({
  353. months,
  354. days,
  355. timeAxisFormatter: timeAxisFormatter.value,
  356. timeCompare: completeDatas.value && timeCompare.value,
  357. })
  358. }
  359. if (completeDatas.value && totalTimes.value.length > 0) {
  360. // 如果需要补全一个区间内的缺失数据
  361. // console.log('serieData', serieData);
  362. if (timeCompare.value) {
  363. const splitTimes = window.splitTimes(totalTimes.value, timeCompare.value);
  364. const realIndexs = {}; // 正确数据索引
  365. const prevValues = splitTimes.prev.map((t, index) => {
  366. let tVal = null;
  367. if (timeCompare.value === 'day') {
  368. tVal = dayjs(t).format(timeAxisFormatter.value || 'HH:mm');
  369. } else if (timeCompare.value === 'month') {
  370. tVal = dayjs(t).format(timeAxisFormatter.value || 'DD');
  371. } else if (timeCompare.value === 'year') {
  372. tVal = dayjs(t).format(timeAxisFormatter.value || 'MM');
  373. }
  374. if (!xAxisData.includes(tVal)) {
  375. xAxisData.push(tVal);
  376. realIndexs[index] = true;
  377. const point = serieData.find(d => +d.ts === t);
  378. return (point && point.val) || 0
  379. }
  380. })
  381. const currValues = splitTimes.curr.map((t, index) => {
  382. if (xAxisData.length === 0) {
  383. let tVal = null;
  384. if (timeCompare.value === 'day') {
  385. tVal = dayjs(t).format(timeAxisFormatter.value || 'HH:mm');
  386. } else if (timeCompare.value === 'month') {
  387. tVal = dayjs(t).format(timeAxisFormatter.value || 'DD');
  388. } else if (timeCompare.value === 'year') {
  389. tVal = dayjs(t).format(timeAxisFormatter.value || 'MM');
  390. }
  391. if (!xAxisData.includes(tVal)) {
  392. xAxisData.push(tVal);
  393. const point = serieData.find(d => +d.ts === t);
  394. return (point && point.val) || 0
  395. }
  396. } else {
  397. if (realIndexs[index]) {
  398. const point = serieData.find(d => +d.ts === t);
  399. return (point && point.val) || 0
  400. }
  401. }
  402. })
  403. let legendPrev = '';
  404. let legendCurr = '';
  405. if (keysLen > 1) {
  406. legendPrev = \`\${legendKey}(\${timeCompareMap[timeCompare.value].prev})\`;
  407. legendCurr = \`\${legendKey}(\${timeCompareMap[timeCompare.value].curr})\`;
  408. } else if (keysLen === 1) {
  409. legendPrev = \`\${timeCompareMap[timeCompare.value].prev}\`;
  410. legendCurr = \`\${timeCompareMap[timeCompare.value].curr}\`;
  411. }
  412. legends.push(legendPrev);
  413. legends.push(legendCurr);
  414. series.push({
  415. name: legendPrev,
  416. type: 'bar',
  417. data: prevValues.filter(Boolean)
  418. })
  419. series.push({
  420. name: legendCurr,
  421. type: 'bar',
  422. data: currValues.filter(Boolean)
  423. })
  424. } else {
  425. const serieValues = totalTimes.value.map(t => {
  426. xAxisData.push(t);
  427. const point = serieData.find(d => +d.ts === t);
  428. return (point && point.val) || 0
  429. })
  430. series.push({
  431. name: legendKey,
  432. type: 'bar',
  433. data: serieValues
  434. })
  435. }
  436. } else {
  437. const serieValues = serieData.map((point) => {
  438. xAxisData.push(+point.ts);
  439. return point.val;
  440. })
  441. series.push({
  442. name: legendKey,
  443. type: 'bar',
  444. data: serieValues
  445. })
  446. }
  447. }
  448. }
  449. } else {
  450. legends = ['测试图例']
  451. xAxisData = [1, 2, 3, 4, 5, 6, 7, 8]
  452. series = [{
  453. type: 'bar',
  454. name: '测试图例',
  455. data: [],
  456. }]
  457. }
  458. // xAxisData 去重
  459. xAxisData = [...new Set(xAxisData)].sort();
  460. const legendConfig = {
  461. ...legend.value,
  462. data: legends.filter(Boolean)
  463. }
  464. const xAxisConfig = {
  465. ...xAxis.value,
  466. axisLabel: {
  467. ...xAxis.value.axisLabel,
  468. formatter: (completeDatas.value && timeCompare.value) ? null : xAxisLabelFormatterBound
  469. },
  470. nameLocation: 'end',
  471. nameGap: 5,
  472. nameTextStyle: {
  473. color: xAxis.value.nameColor,
  474. verticalAlign: 'top',
  475. lineHeight: 28
  476. },
  477. data: xAxisData
  478. }
  479. // 指定图表的配置项和数据
  480. var option = {
  481. grid: grid.value,
  482. title: title.value,
  483. tooltip: {
  484. ...tooltip.value,
  485. formatter: tooltipFormatterBound,
  486. borderColor: tooltip.value.backgroundColor,
  487. textStyle: {
  488. ...tooltip.value.textStyle,
  489. align: 'left'
  490. }
  491. },
  492. legend: legendConfig,
  493. xAxis: xAxisConfig,
  494. yAxis: yAxis.value,
  495. series: series,
  496. };
  497. const func = new Function('option', 'datas', 'instance', codeConfig.value);
  498. const opt = func(window._.cloneDeep(option), datas, myChart);
  499. // 使用刚指定的配置项和数据显示图表。
  500. myChart.setOption(opt);
  501. }
  502. }
  503. }
  504. watch(historyDatas, (val) => {
  505. if (val) {
  506. nextTick(() => {
  507. initChart(val)
  508. })
  509. }
  510. }, {
  511. immediate: true
  512. })
  513. }
  514. }
  515. class CustomBarChartNode extends HtmlResize.view {
  516. chartRendered = false
  517. historyDatas = []
  518. oldProperties = {}
  519. setHtml(rootEl) {
  520. if (!rootEl) return;
  521. const { properties, width, height, } = this.props.model;
  522. const { nodeAlias, grid, title, legend, tooltip, xAxis, yAxis, codeConfig, apiid, renderMode } = properties;
  523. const { normalData } = properties.dynamic || {};
  524. const { timeAxisFormatter, completeDatas, timeCompare, dataShowTypes, legendNameType } = normalData || {};
  525. let totalTimes = [];
  526. if (completeDatas) {
  527. if (apiid) {
  528. const param = window.totalApiParams[apiid];
  529. const info = totalDeviceInfos[apiid];
  530. totalTimes = window.completeTimesForChart(param, info, this.historyDatas);
  531. }
  532. }
  533. const el = document.createElement('div');
  534. rootEl.innerHTML = '';
  535. const instance = createVNode(BarChart, {
  536. apiid,
  537. name: nodeAlias,
  538. lineId: \`line-\${properties.id}\`,
  539. historyDatas: this.historyDatas,
  540. width,
  541. height,
  542. grid, title, legend, tooltip, xAxis, yAxis,
  543. codeConfig,
  544. timeAxisFormatter, completeDatas,
  545. totalTimes,
  546. timeCompare,
  547. dataShowTypes, legendNameType,
  548. renderMode
  549. })
  550. instance.appContext = app._context
  551. render(instance, el)
  552. rootEl.appendChild(el);
  553. }
  554. sameProps(properties) {
  555. const isSame = window._.isEqual(this.oldProperties, properties);
  556. if (isSame) return true;
  557. this.oldProperties = properties;
  558. return false
  559. }
  560. filterHistoryData(thingCodeArr, dataPointArr, apiid, renderIntervalEnabled) {
  561. if (dataPointArr && dataPointArr.length > 0) {
  562. let datas = []
  563. if (renderIntervalEnabled) {
  564. datas = window.totalHistoryDatas[apiid];
  565. } else {
  566. if (window.globalDashboardDatas[apiid]) {
  567. datas = window.globalDashboardDatas[apiid].values;
  568. }
  569. }
  570. if (datas && datas.length > 0) {
  571. const gotValues = datas.filter((val) => thingCodeArr.includes(val.thingCode) && dataPointArr.includes(val.attrKey));
  572. this.historyDatas = gotValues
  573. this.chartRendered = true;
  574. }
  575. }
  576. }
  577. // 生命周期 支持重写内容, 但格式需一致
  578. shouldUpdate() {
  579. const { properties } = this.props.model;
  580. const { apiid } = properties;
  581. const { normalData } = properties.dynamic || {};
  582. const { dataPointArr, defaultValue, thingCodeArr, customApiDatas } = normalData || {}
  583. if (normalData && !normalData.dataPoint && !normalData.defaultValue) {
  584. this.historyDatas = defaultSocketValue;
  585. return true
  586. } else if (normalData && !normalData.dataPoint && normalData.defaultValue) {
  587. this.historyDatas = JSON.parse(defaultValue);
  588. return true
  589. }
  590. // 如果采用来自自定义数据源的数据
  591. if (customApiDatas) {
  592. this.historyDatas = customApiDatas;
  593. return true
  594. }
  595. const propertiesBack = window._.cloneDeep(properties);
  596. if (propertiesBack.dynamic.normalData) {
  597. propertiesBack.dynamic.normalData.defaultValue = '';
  598. if (this.sameProps(propertiesBack) && this.chartRendered) {
  599. return false
  600. }
  601. if (dataPointArr && apiid && !this.chartRendered) {
  602. this.filterHistoryData(thingCodeArr, dataPointArr, apiid, normalData.renderIntervalEnabled);
  603. return true;
  604. }
  605. }
  606. return true;
  607. }
  608. updateHtml() {
  609. this.setHtml(this.rootEl);
  610. }
  611. componentDidMount() {
  612. // 防止拖动时候频繁渲染图表
  613. this.updateHtmlDebounced = window._.debounce(this.updateHtml.bind(this), 500);
  614. const { properties } = this.props.model;
  615. const { normalData } = properties.dynamic || {};
  616. const { renderInterval, dataPointArr, thingCodeArr } = normalData || {};
  617. if (this.shouldUpdate()) {
  618. this.setHtml(this.rootEl);
  619. }
  620. const initRender = () => {
  621. // 第一次历史数据返回可能比较慢,轮询判断
  622. let times = 0
  623. const inter = setInterval(() => {
  624. if (window.totalHistoryDatas && window.totalHistoryDatas[properties.apiid]) {
  625. this.filterHistoryData(thingCodeArr, dataPointArr, properties.apiid, normalData.renderIntervalEnabled);
  626. this.setHtml(this.rootEl);
  627. clearInterval(inter);
  628. }
  629. if (times > 20) {
  630. clearInterval(inter)
  631. }
  632. times++;
  633. }, 1000)
  634. }
  635. initRender();
  636. let inters = parseInt(renderInterval || '300000')
  637. if (normalData && !normalData.renderIntervalEnabled) {
  638. inters = 1000
  639. }
  640. setInterval(() => {
  641. if (window.totalHistoryDatas[properties.apiid]) {
  642. this.filterHistoryData(thingCodeArr, dataPointArr, properties.apiid, normalData.renderIntervalEnabled);
  643. this.setHtml(this.rootEl);
  644. }
  645. }, inters)
  646. }
  647. componentDidUpdate() {
  648. if (this.shouldUpdate()) {
  649. this.updateHtmlDebounced();
  650. }
  651. }
  652. }
  653. class CustomBarChartModel extends HtmlResize.model {
  654. initNodeData(data) {
  655. // 自定义组件,需最开始重置一下text 。
  656. data.text = {
  657. value: "",
  658. x: data.x,
  659. y: data.y,
  660. };
  661. super.initNodeData(data);
  662. const { properties } = this;
  663. this.width = properties.width || 80;
  664. this.height = properties.height || 35;
  665. this.text.editable = false; // 不允许文本被编辑
  666. }
  667. setAttributes() {
  668. // 自定义组件需重置 text
  669. const { x, y, properties } = this;
  670. const { textHorizontalMove = 0, textVerticalMove = 0 } = properties;
  671. this.text = {
  672. ...this.text,
  673. x: x + textHorizontalMove,
  674. y: y + textVerticalMove,
  675. value: "",
  676. }
  677. }
  678. }
  679. lf.register({
  680. type: 'custom-bar-chart',
  681. view: CustomBarChartNode,
  682. model: CustomBarChartModel,
  683. })`,css:`.custom-bar-chart svg {\r
  684. stroke: none;\r
  685. }`,fakeData:""},m={id:e,name:a,aliasName:t,image:n,imageType:i,groupName:l,groupType:o,isRemote:!1,isDefault:!0,sectionType:s,config:d,files:r};export{t as aliasName,d as config,m as default,r as files,l as groupName,o as groupType,e as id,n as image,i as imageType,c as isDefault,u as isRemote,a as name,s as sectionType};