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

715 lines
71 KiB

  1. const e="be616a00-e2bc-4849-8b28-8cdd35cd190b",a="custom-line-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="1694569114379" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1510" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M240.8 803.68l-26.933333-25.813333 248.053333-258.613334 158.186667 158.186667 232-232 26.4 26.4-258.4 258.4-157.653334-157.653333-221.653333 231.093333z" fill="#23B8BA" p-id="1511"></path><path d="M852.106667 456.746667l15.093333 15.093333-247.093333 247.093333-152-152-5.76-5.76-5.653334 5.866667-216.16 225.333333-15.36-14.773333 236.853334-246.933333 152.426666 152.426666 5.653334 5.653334 5.653333-5.653334 226.346667-226.346666m0-11.306667L620.106667 677.333333 461.866667 519.253333l-248 258.613334 26.666666 25.813333 221.653334-231.093333 157.653333 157.653333 258.4-258.4-26.4-26.666667z" fill="#14A59E" p-id="1512"></path><path d="M240.8 537.44l-26.933333-25.866667 248.053333-258.613333 158.186667 158.186667 232-232 26.4 26.4-258.4 258.4-157.653334-157.6-221.653333 231.093333z" fill="#FFA800" p-id="1513"></path><path d="M852.106667 190.453333l15.093333 15.093334-247.093333 247.093333-152-151.946667-5.76-5.813333-5.653334 5.92L240.533333 526.08l-15.36-14.72 236.853334-246.933333 152.426666 152.373333 5.653334 5.653333 5.653333-5.653333 226.346667-226.346667m0-11.306666l-232 232L461.866667 252.96 213.866667 511.573333l26.666666 25.866667 221.92-231.093333L620.106667 464l258.4-258.4-26.4-26.4z" fill="#E29103" p-id="1514"></path><path d="M144 880V106.666667h-37.333333v810.666666h810.666666v-37.333333H144z" fill="#0985F6" p-id="1515"></path><path d="M136 114.666667v773.333333h773.333333v21.333333h-794.666666v-794.666666h21.333333M144 106.666667h-37.333333v810.666666h810.666666v-37.333333H144V106.666667z" fill="#006FC1" p-id="1516"></path><path d="M462.293333 294.56m-48 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0Z" fill="#FFA800" p-id="1517"></path><path d="M462.293333 254.56a40 40 0 1 1-40 40 40 40 0 0 1 40-40m0-8a48 48 0 1 0 48 48 48 48 0 0 0-48-48z" fill="#E29103" p-id="1518"></path><path d="M227.306667 524.48m-48 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0Z" fill="#FFA800" p-id="1519"></path><path d="M227.306667 484.48a40 40 0 1 1-40 40 40.053333 40.053333 0 0 1 40-40m0-8a48 48 0 1 0 48 48 48 48 0 0 0-48-48z" fill="#E29103" p-id="1520"></path><path d="M619.253333 432.426667m-48 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0Z" fill="#FFA800" p-id="1521"></path><path d="M619.253333 392.426667a40 40 0 1 1-40 40 40 40 0 0 1 40-40m0-8a48 48 0 1 0 48 48 48 48 0 0 0-48-48z" fill="#E29103" p-id="1522"></path><path d="M861.333333 192.8m-48 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0Z" fill="#FFA800" p-id="1523"></path><path d="M861.333333 152.8a40 40 0 1 1-40 40 40 40 0 0 1 40-40m0-8a48 48 0 1 0 48 48 48 48 0 0 0-48-48z" fill="#E29103" p-id="1524"></path><path d="M462.293333 560.8m-48 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0Z" fill="#23B8BA" p-id="1525"></path><path d="M462.293333 520.8a40 40 0 1 1-40 40 40.053333 40.053333 0 0 1 40-40m0-8a48 48 0 1 0 48 48 48 48 0 0 0-48-48z" fill="#14A59E" p-id="1526"></path><path d="M227.306667 790.773333m-48 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0Z" fill="#23B8BA" p-id="1527"></path><path d="M227.306667 750.773333a40 40 0 1 1-40 40 40 40 0 0 1 40-40m0-8a48 48 0 1 0 48 48 48 48 0 0 0-48-48z" fill="#14A59E" p-id="1528"></path><path d="M619.253333 698.666667m-48 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0Z" fill="#23B8BA" p-id="1529"></path><path d="M619.253333 658.666667a40 40 0 1 1-40 40 40.053333 40.053333 0 0 1 40-40m0-8a48 48 0 1 0 48 48 48 48 0 0 0-48-48z" fill="#14A59E" p-id="1530"></path><path d="M861.333333 457.6m-48 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0Z" fill="#23B8BA" p-id="1531"></path><path d="M861.333333 417.6a40 40 0 1 1-40 40 40 40 0 0 1 40-40m0-8a48 48 0 1 0 48 48 48 48 0 0 0-48-48z" fill="#14A59E" p-id="1532"></path></svg>',i="svg",l="动态",o="图表组件",u=!1,p=!0,s="时序",d=`{"type":"page","id":"u:270584784c
  2. "nodes": [
  3. {
  4. "id": "a3c0bb09-4bc9-4717-8adc-ff83e5eee086",
  5. "type": "custom-line-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": "5",
  26. "bottom": "20",
  27. "backgroundColor": ""
  28. },
  29. "title": {
  30. "show": true,
  31. "padding": "",
  32. "left": "30",
  33. "right": "2",
  34. "top": "2",
  35. "bottom": "2",
  36. "text": "kWh",
  37. "textAlign": "auto",
  38. "textVerticalAlign ": "middle"
  39. },
  40. "legend": {
  41. "show": true,
  42. "orient": "horizontal",
  43. "left": "center",
  44. "top": ""
  45. },
  46. "tooltip": {
  47. "show": true,
  48. "showContent": true,
  49. "trigger": "axis"
  50. },
  51. "xAxis": {
  52. "show": true,
  53. "axisLine": {
  54. "show": true
  55. },
  56. "axisTick": {
  57. "show": true
  58. },
  59. "axisLabel": {
  60. "show": true,
  61. "fontSize": 12
  62. },
  63. "splitLine": {
  64. "show": false
  65. },
  66. "type ": "category",
  67. "name": "",
  68. "nameColor": ""
  69. },
  70. "yAxis": {
  71. "show": true,
  72. "axisLine": {
  73. "show": true
  74. },
  75. "axisTick": {
  76. "show": true
  77. },
  78. "axisLabel": {
  79. "show": true,
  80. "fontSize": 12
  81. },
  82. "splitLine": {
  83. "show": false
  84. },
  85. "type ": "value"
  86. },
  87. "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 item.smooth = \\"true\\";\\r\\n // 区域风格,可配置\\r\\n // item.areaStyle = {};\\r\\n // 线条风格, 可自定义\\r\\n item.lineStyle = {\\r\\n width: 1\\r\\n };\\r\\n});\\r\\nreturn option;",
  88. "fontSize": 0,
  89. "showDefaultValue": false,
  90. "showUnit": false,
  91. "nodeAlias": "折线图",
  92. "renderMode": "canvas",
  93. "dynamic": {
  94. "normalData": {
  95. "dataPoint": "",
  96. "compareType": "",
  97. "conditionVariables": [],
  98. "defaultValue": "",
  99. "unit": "",
  100. "renderIntervalEnabled": true,
  101. "completeDatas": false,
  102. "legendNameType": "attrName",
  103. "customDatasource": false,
  104. "dataShowTypes": "oneThingManyAttr",
  105. "timeAxisFormatter": "HH",
  106. "requestMethod": "get",
  107. "requestParams": "return {};",
  108. "dataFilterFn": "// datas 数据处理\\n// ....\\n"
  109. }
  110. }
  111. }
  112. }
  113. ]
  114. }`,javascript:`const { createApp, createVNode, render } = Vue;
  115. const app = createApp({})
  116. const timeArr = new Array(24).fill('');
  117. const totals = [];
  118. timeArr.forEach((i, index) => { const t = window.dayjs().hour(index).valueOf(); totals.push({ val: Math.random(1000) * 100, ts: t, attrKey: "A29" }) });
  119. timeArr.forEach((i, index) => { const t = window.dayjs().hour(index).valueOf(); totals.push({ val: Math.random(1000) * 100, ts: t, attrKey: "A8" }) });
  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 LineChart = {
  212. template: '<div :id="lineId" :style="getStyle" class="custom-line-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. myChart = echarts.init(dom, null, {
  323. renderer: renderMode.value
  324. });
  325. if (datas) {
  326. let series = [];
  327. let legends = [];
  328. let xAxisData = [];
  329. let xAxisLabelFormatterBound = null;
  330. if (datas.length > 0) {
  331. const thingGrouped = window._.groupBy(datas, 'thingCode');
  332. for (const thingKey in thingGrouped) {
  333. const attrGrouped = window._.groupBy(thingGrouped[thingKey], 'attrKey')
  334. const keysLen = Object.keys(attrGrouped).length;
  335. for (const key in attrGrouped) {
  336. let serieData = attrGrouped[key];
  337. const legendKey = assembleLegend(apiid.value, thingKey, key, dataShowTypes, legendNameType, serieData);
  338. legends.push(legendKey);
  339. if (!xAxisLabelFormatterBound) {
  340. const first = serieData[0];
  341. const last = serieData[serieData.length - 1];
  342. if (first.ts > last.ts) {
  343. serieData = serieData.reverse()
  344. }
  345. const dayjs = window.dayjs;
  346. const firstDay = dayjs(+first.ts);
  347. const lastDay = dayjs(+last.ts);
  348. const days = firstDay.diff(lastDay, 'day');
  349. const months = firstDay.diff(lastDay, 'month');
  350. xAxisLabelFormatterBound = xAxisLabelFormatter.bind({
  351. months,
  352. days,
  353. timeAxisFormatter: timeAxisFormatter.value,
  354. timeCompare: completeDatas.value && timeCompare.value,
  355. })
  356. }
  357. if (completeDatas.value && totalTimes.value.length > 0) {
  358. // 如果需要补全一个区间内的缺失数据
  359. // console.log('serieData', serieData);
  360. if (timeCompare.value) {
  361. const splitTimes = window.splitTimes(totalTimes.value, timeCompare.value);
  362. const realIndexs = {}; // 正确数据索引
  363. const prevValues = splitTimes.prev.map((t, index) => {
  364. let tVal = null;
  365. if (timeCompare.value === 'day') {
  366. tVal = dayjs(t).format(timeAxisFormatter.value || 'HH:mm');
  367. } else if (timeCompare.value === 'month') {
  368. tVal = dayjs(t).format(timeAxisFormatter.value || 'DD');
  369. } else if (timeCompare.value === 'year') {
  370. tVal = dayjs(t).format(timeAxisFormatter.value || 'MM');
  371. }
  372. if (!xAxisData.includes(tVal)) {
  373. xAxisData.push(tVal);
  374. realIndexs[index] = true;
  375. const point = serieData.find(d => +d.ts === t);
  376. return (point && point.val) || 0
  377. }
  378. })
  379. const currValues = splitTimes.curr.map((t, index) => {
  380. if (xAxisData.length === 0) {
  381. let tVal = null;
  382. if (timeCompare.value === 'day') {
  383. tVal = dayjs(t).format(timeAxisFormatter.value || 'HH:mm');
  384. } else if (timeCompare.value === 'month') {
  385. tVal = dayjs(t).format(timeAxisFormatter.value || 'DD');
  386. } else if (timeCompare.value === 'year') {
  387. tVal = dayjs(t).format(timeAxisFormatter.value || 'MM');
  388. }
  389. if (!xAxisData.includes(tVal)) {
  390. xAxisData.push(tVal);
  391. const point = serieData.find(d => +d.ts === t);
  392. return (point && point.val) || 0
  393. }
  394. } else {
  395. if (realIndexs[index]) {
  396. const point = serieData.find(d => +d.ts === t);
  397. return (point && point.val) || 0
  398. }
  399. }
  400. })
  401. let legendPrev = '';
  402. let legendCurr = '';
  403. if (keysLen > 1) {
  404. legendPrev = \`\${legendKey}(\${timeCompareMap[timeCompare.value].prev})\`;
  405. legendCurr = \`\${legendKey}(\${timeCompareMap[timeCompare.value].curr})\`;
  406. } else if (keysLen === 1) {
  407. legendPrev = \`\${timeCompareMap[timeCompare.value].prev}\`;
  408. legendCurr = \`\${timeCompareMap[timeCompare.value].curr}\`;
  409. }
  410. legends.push(legendPrev);
  411. legends.push(legendCurr);
  412. series.push({
  413. name: legendPrev,
  414. type: 'line',
  415. data: prevValues.filter(Boolean)
  416. })
  417. series.push({
  418. name: legendCurr,
  419. type: 'line',
  420. data: currValues.filter(Boolean)
  421. })
  422. } else {
  423. const serieValues = totalTimes.value.map(t => {
  424. xAxisData.push(t);
  425. const point = serieData.find(d => +d.ts === t);
  426. return (point && point.val) || 0
  427. })
  428. series.push({
  429. name: legendKey,
  430. type: 'line',
  431. data: serieValues
  432. })
  433. }
  434. } else {
  435. const serieValues = serieData.map((point) => {
  436. xAxisData.push(+point.ts);
  437. return point.val;
  438. })
  439. series.push({
  440. name: legendKey,
  441. type: 'line',
  442. data: serieValues
  443. })
  444. }
  445. }
  446. }
  447. } else {
  448. legends = ['测试图例']
  449. xAxisData = [1, 2, 3, 4, 5, 6, 7, 8]
  450. series = [{
  451. type: 'line',
  452. name: '测试图例',
  453. data: [],
  454. }]
  455. }
  456. // xAxisData 去重
  457. xAxisData = [...new Set(xAxisData)].sort();
  458. const legendConfig = {
  459. ...legend.value,
  460. data: legends.filter(Boolean)
  461. }
  462. const xAxisConfig = {
  463. ...xAxis.value,
  464. axisLabel: {
  465. ...xAxis.value.axisLabel,
  466. formatter: (completeDatas.value && timeCompare.value) ? null : xAxisLabelFormatterBound
  467. },
  468. nameLocation: 'end',
  469. nameGap: 5,
  470. nameTextStyle: {
  471. color: xAxis.value.nameColor,
  472. verticalAlign: 'top',
  473. lineHeight: 28
  474. },
  475. data: xAxisData
  476. }
  477. // 指定图表的配置项和数据
  478. var option = {
  479. grid: grid.value,
  480. title: title.value,
  481. tooltip: {
  482. ...tooltip.value,
  483. formatter: tooltipFormatterBound,
  484. borderColor: tooltip.value.backgroundColor,
  485. textStyle: {
  486. ...tooltip.value.textStyle,
  487. align: 'left'
  488. }
  489. },
  490. legend: legendConfig,
  491. xAxis: xAxisConfig,
  492. yAxis: yAxis.value,
  493. series: series,
  494. };
  495. const func = new Function('option', 'datas', 'instance', codeConfig.value);
  496. const opt = func(window._.cloneDeep(option), datas, myChart);
  497. // 使用刚指定的配置项和数据显示图表。
  498. myChart.setOption(opt);
  499. }
  500. }
  501. }
  502. watch(historyDatas, (val) => {
  503. if (val) {
  504. nextTick(() => {
  505. initChart(val)
  506. })
  507. }
  508. }, {
  509. immediate: true
  510. })
  511. }
  512. }
  513. class CustomLineChartNode extends HtmlResize.view {
  514. chartRendered = false
  515. historyDatas = []
  516. oldProperties = "{}"
  517. setHtml(rootEl) {
  518. if (!rootEl) return;
  519. const { properties, width, height, } = this.props.model;
  520. const { nodeAlias, grid, title, legend, tooltip, xAxis, yAxis, codeConfig, dynamic, apiid, renderMode } = properties;
  521. const { normalData } = dynamic || {};
  522. const { timeAxisFormatter, completeDatas, timeCompare, dataShowTypes, legendNameType } = normalData || {};
  523. let totalTimes = [];
  524. if (completeDatas) {
  525. if (apiid) {
  526. const param = window.totalApiParams[apiid];
  527. const info = totalDeviceInfos[apiid];
  528. totalTimes = window.completeTimesForChart(param, info, this.historyDatas, apiid);
  529. }
  530. }
  531. const el = document.createElement('div');
  532. rootEl.innerHTML = '';
  533. const instance = createVNode(LineChart, {
  534. name: nodeAlias,
  535. lineId: \`line-\${properties.id}\`,
  536. historyDatas: this.historyDatas,
  537. width,
  538. height,
  539. grid, title, legend, tooltip, xAxis, yAxis,
  540. codeConfig,
  541. timeAxisFormatter, completeDatas,
  542. totalTimes,
  543. timeCompare,
  544. apiid, dataShowTypes, legendNameType,
  545. renderMode
  546. })
  547. instance.appContext = app._context
  548. render(instance, el)
  549. rootEl.appendChild(el);
  550. }
  551. sameProps(properties) {
  552. const isSame = window._.isEqual(JSON.parse(this.oldProperties), properties);
  553. if (isSame) return true;
  554. this.oldProperties = JSON.stringify(properties);
  555. return false
  556. }
  557. // 过滤历史数据
  558. filterHistoryData(thingCodeArr, dataPointArr, apiid, renderIntervalEnabled) {
  559. if (dataPointArr && dataPointArr.length > 0) {
  560. let datas = []
  561. if (renderIntervalEnabled) {
  562. datas = window.totalHistoryDatas[apiid];
  563. } else {
  564. if (window.globalDashboardDatas[apiid]) {
  565. datas = window.globalDashboardDatas[apiid].values;
  566. }
  567. }
  568. if (datas && datas.length > 0) {
  569. const gotValues = datas.filter((val) => thingCodeArr.includes(val.thingCode) && dataPointArr.includes(val.attrKey))
  570. this.historyDatas = gotValues
  571. this.chartRendered = true;
  572. }
  573. }
  574. }
  575. // 生命周期 支持重写内容, 但格式需一致
  576. shouldUpdate() {
  577. const { properties } = this.props.model;
  578. const { apiid } = properties;
  579. const { normalData } = properties.dynamic || {};
  580. const { dataPointArr, defaultValue, thingCodeArr, customApiDatas } = normalData || {}
  581. if (normalData && !normalData.dataPoint && !normalData.defaultValue) {
  582. this.historyDatas = defaultSocketValue;
  583. return true
  584. } else if (normalData && !normalData.dataPoint && normalData.defaultValue) {
  585. this.historyDatas = JSON.parse(defaultValue);
  586. return true
  587. }
  588. // 如果采用来自自定义数据源的数据
  589. if (customApiDatas) {
  590. this.historyDatas = customApiDatas;
  591. return true
  592. }
  593. const propertiesBack = window._.cloneDeep(properties);
  594. if (propertiesBack.dynamic.normalData) {
  595. propertiesBack.dynamic.normalData.defaultValue = '';
  596. if (this.sameProps(propertiesBack) && this.chartRendered) {
  597. return false
  598. }
  599. if (dataPointArr && apiid && !this.chartRendered) {
  600. this.filterHistoryData(thingCodeArr, dataPointArr, apiid, normalData.renderIntervalEnabled);
  601. return true;
  602. }
  603. }
  604. return true;
  605. }
  606. updateHtml() {
  607. this.setHtml(this.rootEl);
  608. }
  609. componentDidMount() {
  610. // 防止拖动时候频繁渲染图表
  611. this.updateHtmlDebounced = window._.debounce(this.updateHtml.bind(this), 500);
  612. const { properties } = this.props.model;
  613. const { normalData } = properties.dynamic || {};
  614. const { renderInterval, dataPointArr, thingCodeArr } = normalData || {};
  615. if (this.shouldUpdate()) {
  616. this.setHtml(this.rootEl);
  617. }
  618. const initRender = () => {
  619. // 第一次历史数据返回可能比较慢,轮询判断
  620. let times = 0
  621. const inter = setInterval(() => {
  622. if (window.totalHistoryDatas && window.totalHistoryDatas[properties.apiid]) {
  623. this.filterHistoryData(thingCodeArr, dataPointArr, properties.apiid, normalData.renderIntervalEnabled);
  624. this.setHtml(this.rootEl);
  625. clearInterval(inter);
  626. }
  627. if (times > 20) {
  628. clearInterval(inter)
  629. }
  630. times++;
  631. }, 1000)
  632. }
  633. initRender();
  634. let inters = parseInt(renderInterval || '300000')
  635. if (normalData && !normalData.renderIntervalEnabled) {
  636. inters = 1000
  637. }
  638. setInterval(() => {
  639. if (window.totalHistoryDatas[properties.apiid]) {
  640. this.filterHistoryData(thingCodeArr, dataPointArr, properties.apiid, normalData.renderIntervalEnabled);
  641. this.setHtml(this.rootEl);
  642. }
  643. }, inters)
  644. }
  645. componentDidUpdate() {
  646. if (this.shouldUpdate()) {
  647. this.updateHtmlDebounced();
  648. }
  649. }
  650. }
  651. class CustomLineChartModel extends HtmlResize.model {
  652. initNodeData(data) {
  653. // 自定义组件,需最开始重置一下text 。
  654. data.text = {
  655. value: "",
  656. x: data.x,
  657. y: data.y,
  658. };
  659. super.initNodeData(data);
  660. const { properties } = this;
  661. this.width = properties.width || 80;
  662. this.height = properties.height || 35;
  663. this.text.editable = false; // 不允许文本被编辑
  664. }
  665. setAttributes() {
  666. // 自定义组件需重置 text
  667. const { x, y, properties } = this;
  668. const { textHorizontalMove = 0, textVerticalMove = 0 } = properties;
  669. this.text = {
  670. ...this.text,
  671. x: x + textHorizontalMove,
  672. y: y + textVerticalMove,
  673. value: "",
  674. }
  675. }
  676. }
  677. lf.register({
  678. type: 'custom-line-chart',
  679. view: CustomLineChartNode,
  680. model: CustomLineChartModel,
  681. })`,css:`.custom-line-chart svg {\r
  682. stroke: none;\r
  683. }`,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,p as isDefault,u as isRemote,a as name,s as sectionType};