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

449 lines
115 KiB

  1. const A="3cd8adbd-53b0-46e8-8a82-b838f16cccee",e="custom-guage-outline-two",E="仪表板2",Q="data:image/png;base64,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
  2. "nodes": [
  3. {
  4. "id": "659b3546-395d-482b-b3c3-4019d1e001cf",
  5. "type": "custom-guage-outline-two",
  6. "x": 200,
  7. "y": 200,
  8. "text": {
  9. "value": "",
  10. "x": 200,
  11. "y": 200
  12. },
  13. "properties": {
  14. "id": "659b3546-395d-482b-b3c3-4019d1e001cf",
  15. "width": 420,
  16. "height": 420,
  17. "x": 200,
  18. "y": 200,
  19. "rotation": 0,
  20. "opacity": 1,
  21. "codeConfig": "return option",
  22. "nodeAlias": "仪表板2",
  23. "showDefaultValue": false,
  24. "showUnit": false,
  25. "valueColor": "rgba(245, 166, 35, 1)",
  26. "fontSize": 12,
  27. "range": {
  28. "startAngle": 225,
  29. "endAngle": -45,
  30. "min": 0,
  31. "max": 100
  32. },
  33. "guage": {
  34. "radius": 95,
  35. "axisTick": {
  36. "length": -8,
  37. "lineStyle": {
  38. "color": "#468EFD"
  39. }
  40. },
  41. "splitLine": {
  42. "length": -20,
  43. "lineStyle": {
  44. "color": "#468EFD"
  45. }
  46. },
  47. "axisLabel": {
  48. "color": "#4d5bd1",
  49. "distance": 30,
  50. "fontSize": 12
  51. },
  52. "pointer": {
  53. "width": 10,
  54. "length": 60
  55. },
  56. "detail": {
  57. "color": "#468EFD",
  58. "fontSize": 22
  59. }
  60. },
  61. "outline": {
  62. "radius": 75,
  63. "axisLine": {
  64. "lineStyle": {
  65. "bgColor": "#111F42",
  66. "width": 3
  67. }
  68. },
  69. "itemStyle": {
  70. "normal": {
  71. "color": "#468EFD"
  72. }
  73. }
  74. },
  75. "dynamic": {
  76. "normalData": {
  77. "dataPoint": "",
  78. "compareType": "",
  79. "conditionVariables": [],
  80. "defaultValue": "",
  81. "unit": ""
  82. }
  83. }
  84. }
  85. }
  86. ]
  87. }`,javascript:`const { createApp, createVNode, render } = Vue;
  88. const app = createApp({})
  89. const defaultVal = 45
  90. const GuageOutlineTwo = {
  91. template: '<div :id="chartId" :style="getStyle"></div>',
  92. props: {
  93. chartId: {
  94. type: String,
  95. default: ''
  96. },
  97. currentData: {
  98. type: Number,
  99. default: 100
  100. },
  101. width: {
  102. type: Number,
  103. default: 350
  104. },
  105. height: {
  106. type: Number,
  107. default: 150
  108. },
  109. chartProps: {
  110. type: Object,
  111. default: () => { }
  112. },
  113. thingName: {
  114. type: String,
  115. default: ''
  116. },
  117. attr: {
  118. type: String,
  119. default: ''
  120. },
  121. unit: {
  122. type: String,
  123. default: ''
  124. },
  125. },
  126. computed: {
  127. getStyle() {
  128. return {
  129. width: \`\${this.width}px\`,
  130. height: \`\${this.height}px\`
  131. }
  132. }
  133. },
  134. setup(props) {
  135. const { onMounted, nextTick, toRefs, watch } = Vue;
  136. const { chartProps, currentData, thingName, attr, width, height } = toRefs(props);
  137. let myChart = null;
  138. const initChart = (data, pros) => {
  139. // 基于准备好的dom,初始化echarts实例
  140. const dom = document.getElementById(props.chartId);
  141. if (dom) {
  142. if (!myChart) {
  143. myChart = echarts.init(dom);
  144. }
  145. // 由于实时推送时候不会重复创建实例,但是需更新画布大小。
  146. myChart.resize({
  147. width: width.value,
  148. height: height.value,
  149. })
  150. if (data != null) {
  151. const { codeConfig, range, guage, outline } = pros;
  152. const { startAngle, endAngle, min, max } = range;
  153. const outlineCloned = window._.cloneDeep(outline);
  154. const guageCloned = window._.cloneDeep(guage);
  155. outlineCloned.radius = outlineCloned.radius + '%';
  156. guageCloned.radius = guageCloned.radius + '%';
  157. // 指定图表的配置项和数据
  158. var color = outlineCloned.itemStyle.normal.color;
  159. var option = {
  160. backgroundColor: '',
  161. tooltip: {
  162. formatter: "{a} <br/>{c} {b}"
  163. },
  164. series: [
  165. {
  166. name: '',
  167. type: 'gauge',
  168. startAngle,
  169. endAngle,
  170. min,
  171. max,
  172. radius: guageCloned.radius,
  173. title: {
  174. show: false
  175. },
  176. detail: {
  177. show: true,
  178. fontFamily: 'DIN',
  179. fontWeight: '500',
  180. color: guageCloned.detail.color,
  181. offsetCenter: [0, '70%'],
  182. formatter: function (value) {
  183. return value
  184. },
  185. fontSize: guageCloned.detail.fontSize
  186. },
  187. axisLine: {
  188. show: false
  189. },
  190. axisTick: guageCloned.axisTick,
  191. splitLine: guageCloned.splitLine,
  192. axisLabel: {
  193. //数字离圆的距离
  194. distance: guageCloned.axisLabel.distance,
  195. borderRadius: 1,
  196. color: guageCloned.axisLabel.color,
  197. fontWeight: 600,
  198. padding: 1,
  199. fontFamily: 'Alibaba PuHuiTi',
  200. fontSize: guageCloned.axisLabel.fontSize
  201. },
  202. pointer: {
  203. ...guageCloned.pointer,
  204. length: guageCloned.pointer.length + '%'
  205. },
  206. itemStyle: {
  207. color: color,
  208. shadowColor: 'rgba(0,138,255,0.45)',
  209. shadowBlur: 10,
  210. shadowOffsetX: 2,
  211. shadowOffsetY: 2
  212. },
  213. data: [{
  214. value: data,
  215. name: '两区面积'
  216. }]
  217. },
  218. {
  219. name: "已到人数",
  220. type: 'gauge',
  221. radius: outlineCloned.radius,
  222. startAngle,
  223. endAngle,
  224. min,
  225. max,
  226. title: {
  227. show: false
  228. },
  229. detail: {
  230. show: false
  231. },
  232. axisLine: {
  233. show: true,
  234. lineStyle: {
  235. width: outlineCloned.axisLine.lineStyle.width,
  236. color: [
  237. [
  238. data / 100, color
  239. ],
  240. [
  241. 1, outlineCloned.axisLine.lineStyle.bgColor
  242. ]
  243. ],
  244. }
  245. },
  246. axisTick: {
  247. show: false,
  248. },
  249. splitLine: {
  250. show: false,
  251. },
  252. axisLabel: {
  253. show: false
  254. },
  255. pointer: {
  256. show: false,
  257. },
  258. itemStyle: {
  259. normal: {
  260. color: '#54F200',
  261. }
  262. },
  263. data: [{
  264. value: data,
  265. name: '年售电量情况'
  266. }]
  267. }
  268. ]
  269. }
  270. // console.log('option', option);
  271. const func = new Function('option', 'datas', codeConfig);
  272. const opt = func(window._.cloneDeep(option), data);
  273. // console.log('opt', opt);
  274. // 使用刚指定的配置项和数据显示图表。
  275. myChart.setOption(opt);
  276. }
  277. }
  278. }
  279. watch([currentData, chartProps], ([val, pros]) => {
  280. nextTick(() => {
  281. initChart(val, pros)
  282. })
  283. }, {
  284. immediate: true,
  285. deep: true,
  286. })
  287. }
  288. }
  289. class CustomGuageOutlineTwoNode extends HtmlResize.view {
  290. realValue = defaultVal
  291. oldProperties = {}
  292. chartRendered = false
  293. instance = null
  294. setHtml(rootEl) {
  295. if (!rootEl) return;
  296. const { properties, width, height } = this.props.model;
  297. const { normalData } = properties.dynamic || {}
  298. let thingName = 'pressure';
  299. let attr = 'score';
  300. if (normalData && normalData.dataPoint) {
  301. const dataPointStrParsed = JSON.parse(normalData.dataPoint || '{}')
  302. const { deviceCode, dataPoint } = dataPointStrParsed;
  303. thingName = deviceCode;
  304. attr = dataPoint.split(',')[0];
  305. }
  306. if (this.instance) {
  307. // 实时数据不能推送一次就创建一次图表,可以在原有实例基础之上更改数据。
  308. Object.assign(this.instance.component.props, {
  309. name: properties.nodeAlias,
  310. chartId: \`waterfill-\${properties.id}\`,
  311. currentData: this.realValue,
  312. width,
  313. height,
  314. chartProps: properties,
  315. thingName,
  316. attr,
  317. unit: normalData.unit || 'km/h'
  318. })
  319. return
  320. }
  321. const el = document.createElement('div');
  322. rootEl.innerHTML = '';
  323. const instance = createVNode(GuageOutlineTwo, {
  324. name: properties.nodeAlias,
  325. chartId: \`gauge-\${properties.id}\`,
  326. currentData: this.realValue,
  327. width,
  328. height,
  329. chartProps: properties,
  330. thingName,
  331. attr,
  332. unit: normalData.unit || 'km/h'
  333. })
  334. instance.appContext = app._context
  335. render(instance, el)
  336. rootEl.appendChild(el);
  337. this.instance = instance;
  338. }
  339. sameProps(properties) {
  340. const isSame = window._.isEqual(this.oldProperties, properties);
  341. if (isSame) return true;
  342. this.oldProperties = properties;
  343. return false
  344. }
  345. // 生命周期 支持重写内容, 但格式需一致
  346. shouldUpdate() {
  347. const { properties } = this.props.model;
  348. const { normalData } = properties.dynamic || {};
  349. if (normalData && !normalData.dataPoint && !normalData.defaultValue) {
  350. this.realValue = defaultVal;
  351. return true
  352. }
  353. if (normalData) {
  354. const { defaultValue } = normalData || {};
  355. if (defaultValue) {
  356. const realValue = window.resolveScadaNewValue(defaultValue)
  357. if (this.realValue !== Number(realValue)) {
  358. this.realValue = Number(realValue);
  359. return true;
  360. }
  361. }
  362. }
  363. const propertiesBack = window._.cloneDeep(properties);
  364. if (propertiesBack.dynamic.normalData) {
  365. const isSameProps = this.sameProps(propertiesBack);
  366. if (isSameProps && this.chartRendered) {
  367. return false
  368. } else {
  369. if (!this.chartRendered) {
  370. this.chartRendered = true
  371. return true
  372. }
  373. if (!isSameProps) {
  374. return true;
  375. }
  376. }
  377. }
  378. }
  379. updateHtml() {
  380. this.setHtml(this.rootEl);
  381. }
  382. componentDidMount() {
  383. // 防止拖动时候频繁渲染图表
  384. this.updateHtmlDebounced = window._.debounce(this.updateHtml.bind(this), 500);
  385. if (this.shouldUpdate()) {
  386. this.setHtml(this.rootEl);
  387. }
  388. }
  389. componentDidUpdate() {
  390. if (this.shouldUpdate()) {
  391. this.updateHtmlDebounced();
  392. }
  393. }
  394. }
  395. class CustomGuageOutlineTwoModel extends HtmlResize.model {
  396. initNodeData(data) {
  397. // 自定义组件,需最开始重���一下text 。
  398. data.text = {
  399. value: "",
  400. x: data.x,
  401. y: data.y,
  402. };
  403. super.initNodeData(data);
  404. const { properties } = this;
  405. this.width = properties.width || 80;
  406. this.height = properties.height || 35;
  407. this.text.editable = false; // 不允许文本被编辑
  408. }
  409. setAttributes() {
  410. // 自定义组件需重置 text
  411. const { x, y, properties } = this;
  412. const { textHorizontalMove = 0, textVerticalMove = 0 } = properties;
  413. this.text = {
  414. ...this.text,
  415. x: x + textHorizontalMove,
  416. y: y + textVerticalMove,
  417. value: "",
  418. }
  419. }
  420. }
  421. lf.register({
  422. type: 'custom-guage-outline-two',
  423. view: CustomGuageOutlineTwoNode,
  424. model: CustomGuageOutlineTwoModel,
  425. })`,css:"",fakeData:""},o={id:A,name:e,aliasName:E,image:Q,imageType:B,groupName:g,groupType:I,isRemote:!1,isDefault:!0,sectionType:t,config:C,files:n};export{E as aliasName,C as config,o as default,n as files,g as groupName,I as groupType,A as id,Q as image,B as imageType,i as isDefault,a as isRemote,e as name,t as sectionType};