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

380 lines
31 KiB

  1. const e="e640d3bc-3f8e-4a5c-8c86-1d1fd8ba00fb",a="custom-liquidball-node",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="1695175838670" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6237" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M511.974273 512.025215m-486.3741 0a486.374101 486.374101 0 1 0 972.748201 0 486.374101 486.374101 0 1 0-972.748201 0Z" fill="#FFFFFF" p-id="6238"></path><path d="M149.958351 874.041137A511.972737 511.972737 0 1 1 511.974273 1023.997952a508.644915 508.644915 0 0 1-362.015922-149.956815zM51.19881 512.025215a460.775464 460.775464 0 1 0 460.775463-460.775464 461.313035 461.313035 0 0 0-460.775463 460.775464z m208.475298 252.325763v-504.651527h100.909827v50.454913h-50.454913v138.232639a205.966632 205.966632 0 0 1 201.845251 13.260094 206.01783 206.01783 0 0 0 201.870851 13.260094v-164.650432h-252.325764v-50.454913h302.806276v504.651527z" fill="#1890FF" p-id="6239"></path></svg>',l="svg",i="动态",o="图表组件",c=!1,u=!0,s="时序",r=`{"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:ef5ffa6a88c9","body":[{"type":"select","label":"水球类型","name":"liquidType","options":[{"label":"
  2. "nodes": [
  3. {
  4. "id": "ac05917b-d79b-4e78-952d-62cd68de1fe8",
  5. "type": "custom-liquidball-node",
  6. "x": 200,
  7. "y": 200,
  8. "text": {
  9. "value": "",
  10. "x": 200,
  11. "y": 200
  12. },
  13. "properties": {
  14. "id": "ac05917b-d79b-4e78-952d-62cd68de1fe8",
  15. "width": 230,
  16. "height": 230,
  17. "x": 200,
  18. "y": 200,
  19. "rotation": 0,
  20. "opacity": 1,
  21. "fontSize": 24,
  22. "showDefaultValue": false,
  23. "showUnit": false,
  24. "nodeAlias": "水球图",
  25. "fontColor": "#7ed321",
  26. "backgroundColor": "#e8e8e8",
  27. "waveOneColor": "#80FFA5",
  28. "waveTwoColor": "#00DDFF",
  29. "borderWidth": 2,
  30. "borderColor": "#50e3c2",
  31. "liquidType": "liquidball",
  32. "dynamic": {
  33. "normalData": {
  34. "dataPoint": "",
  35. "compareType": "",
  36. "conditionVariables": [],
  37. "defaultValue": "",
  38. "unit": ""
  39. }
  40. }
  41. }
  42. }
  43. ]
  44. }`,javascript:`const { createApp, createVNode, render } = Vue;
  45. const app = createApp({})
  46. const defaultValue = 100
  47. const defaultMaxValue = 1000
  48. const LiquidBall= {
  49. template: \`<div :id="chartId" :style="getStyle" class="liquidball-node">
  50. <div data-v-a6bbf8c4="" :style="liquidballBack" class="liquidballBackStyle">
  51. <div class="inner" :style="getPer">
  52. <svg xmlns="http://www.w3.org/2000/svg" version="1.0" viewBox="0 0 600 140" :style="waveOneFill" class="box-waves">
  53. <path d="M 0 70 Q 75 20,150 70 T 300 70 T 450 70 T 600 70 L 600 140 L 0 140 L 0 70Z"></path>
  54. </svg>
  55. <svg xmlns="http://www.w3.org/2000/svg" version="1.0" viewBox="0 0 600 140" :style="waveTwoFill" class="box-waves">
  56. <path d="M 0 70 Q 75 20,150 70 T 300 70 T 450 70 T 600 70 L 600 140 L 0 140 L 0 70Z"></path>
  57. </svg>
  58. </div>
  59. <div :style="getTextStyle" class="box-text">
  60. <div>
  61. <p style="margin-right: 5px;margin-bottom: 3px; font-size: 14px; text-align: center">{{attr}}</p>
  62. {{getRatio}}
  63. </div>
  64. </div>
  65. </div>
  66. </div>\`,
  67. props: {
  68. chartId: {
  69. type: String,
  70. default: ''
  71. },
  72. currentData: {
  73. type: String,
  74. default: ''
  75. },
  76. maxValue: {
  77. type: Number,
  78. default: 1000
  79. },
  80. width: {
  81. type: Number,
  82. default: 350
  83. },
  84. height: {
  85. type: Number,
  86. default: 150
  87. },
  88. chartProps: {
  89. type: Object,
  90. default: () => ({})
  91. },
  92. thingName: {
  93. type: String,
  94. default: ''
  95. },
  96. attr: {
  97. type: String,
  98. default: ''
  99. },
  100. },
  101. computed: {
  102. getStyle() {
  103. const properties = this.chartProps;
  104. if(properties.liquidType === 'liquidball') {
  105. return {
  106. width: \`\${this.width}px\`,
  107. height: \`\${this.height}px\`,
  108. border: \`\${properties.borderWidth}px solid \${properties.borderColor}\`,
  109. position: 'relative',
  110. 'border-radius': '50%',
  111. 'box-sizing': 'border-box',
  112. 'display': 'flex',
  113. 'justify-content': 'center',
  114. 'align-items': 'center',
  115. }
  116. } else if (properties.liquidType === 'liquidpool'){
  117. return {
  118. width: \`\${this.width}px\`,
  119. height: \`\${this.height}px\`,
  120. 'border-right': \`\${properties.borderWidth}px solid \${properties.borderColor}\`,
  121. 'border-bottom': \`\${properties.borderWidth}px solid \${properties.borderColor}\`,
  122. 'border-left': \`\${properties.borderWidth}px solid \${properties.borderColor}\`,
  123. position: 'relative',
  124. 'box-sizing': 'border-box',
  125. 'display': 'flex',
  126. 'justify-content': 'center',
  127. 'align-items': 'center',
  128. }
  129. }
  130. },
  131. liquidballBack () {
  132. const properties = this.chartProps;
  133. return {
  134. position: 'relative',
  135. overflow: 'hidden',
  136. 'background-color': properties.backgroundColor,
  137. width: \`calc(100% - \${properties.borderWidth * 2}px)\`,
  138. height: \`calc(100% - \${properties.borderWidth * 2}px)\`,
  139. 'border-radius': properties.liquidType === 'liquidball' ? '50%' : '2px'
  140. }
  141. },
  142. getTextStyle() {
  143. const properties = this.chartProps;
  144. const {fontColor, fontSize, fontFamily, fontStyle, lineHeight, letterSpacing } = properties;
  145. return {
  146. 'font-size': fontSize + 'px',
  147. 'font-family': fontFamily,
  148. 'font-style': fontStyle,
  149. 'line-height': lineHeight,
  150. 'letter-spacing': letterSpacing,
  151. 'color': fontColor,
  152. }
  153. },
  154. waveOneFill() {
  155. return {
  156. fill: this.chartProps.waveOneColor,
  157. }
  158. },
  159. waveTwoFill() {
  160. return {
  161. fill: this.chartProps.waveTwoColor,
  162. }
  163. },
  164. getPer() {
  165. const ratio = ((+this.currentData/this.maxValue) * 100).toFixed(0);
  166. const ratioStr = ratio + '%';
  167. return {
  168. '--per': ratioStr,
  169. 'background-color': this.chartProps.waveOneColor,
  170. }
  171. },
  172. getRatio() {
  173. const ratio = ((+this.currentData/this.maxValue) * 100).toFixed(2);
  174. const ratioStr = ratio + '%';
  175. return ratioStr
  176. }
  177. },
  178. }
  179. class CustomLiquidBallNode extends HtmlResize.view {
  180. realValue = defaultValue
  181. maxValue = defaultMaxValue
  182. oldProperties = "{}"
  183. chartRendered = false
  184. instance = null
  185. setHtml(rootEl) {
  186. if (!rootEl) return;
  187. const { properties, width, height, } = this.props.model;
  188. const { normalData } = properties.dynamic || {}
  189. let thingName = 'pressure';
  190. let attr = 'score';
  191. if(normalData && normalData.dataPoint) {
  192. const dataPointStrParsed = JSON.parse(normalData.dataPoint || '{}')
  193. const { deviceCode, dataPoint } = dataPointStrParsed;
  194. thingName = deviceCode;
  195. attr = dataPoint.split(',')[0];
  196. }
  197. if(this.instance) {
  198. // 实时数据不能推送一次就创建一次图表,可以在原有实例基础之上更改数据。
  199. Object.assign(this.instance.component.props,{
  200. name: properties.nodeAlias,
  201. chartId: \`liquid-\${properties.id}\`,
  202. currentData: this.realValue,
  203. width,
  204. height,
  205. chartProps: properties,
  206. thingName,
  207. attr,
  208. maxValue: normalData.maxValue || this.maxValue
  209. })
  210. return
  211. }
  212. const el = document.createElement('div');
  213. rootEl.innerHTML = '';
  214. const instance = createVNode(LiquidBall, {
  215. name: properties.nodeAlias,
  216. chartId: \`liquid-\${properties.id}\`,
  217. currentData: this.realValue,
  218. width,
  219. height,
  220. chartProps: properties,
  221. thingName,
  222. attr,
  223. maxValue: normalData.maxValue || this.maxValue
  224. })
  225. instance.appContext = app._context
  226. render(instance, el)
  227. rootEl.appendChild(el);
  228. this.instance = instance;
  229. }
  230. sameProps(properties) {
  231. const isSame = window._.isEqual(this.oldProperties, properties);
  232. if (isSame) return true;
  233. this.oldProperties = properties;
  234. return false
  235. }
  236. // 生命周期 支持重写内容, 但格式需一致
  237. shouldUpdate() {
  238. const { properties } = this.props.model;
  239. const { normalData } = properties.dynamic || {};
  240. if (normalData && !normalData.dataPoint && !normalData.defaultValue) {
  241. this.realValue = defaultValue;
  242. return true
  243. }
  244. if (normalData) {
  245. const { defaultValue } = normalData || {}
  246. if (defaultValue) {
  247. const realValue = window.resolveScadaNewValue(defaultValue)
  248. if(this.realValue !== Number(realValue)) {
  249. this.realValue = Number(realValue);
  250. return true;
  251. }
  252. }
  253. }
  254. const propertiesBack = window._.cloneDeep(properties);
  255. if (propertiesBack.dynamic.normalData) {
  256. const isSameProps = this.sameProps(propertiesBack);
  257. if (isSameProps && this.chartRendered) {
  258. return false
  259. } else {
  260. if (!this.chartRendered) {
  261. this.chartRendered = true
  262. return true
  263. }
  264. if(!isSameProps) {
  265. return true;
  266. }
  267. }
  268. }
  269. }
  270. updateHtml() {
  271. this.setHtml(this.rootEl);
  272. }
  273. componentDidMount() {
  274. if (this.shouldUpdate()) {
  275. this.setHtml(this.rootEl);
  276. }
  277. // 防止拖动时候频繁渲染图表
  278. this.updateHtmlDebounced = window._.debounce(this.updateHtml.bind(this), 500);
  279. }
  280. componentDidUpdate() {
  281. if (this.shouldUpdate()) {
  282. this.updateHtmlDebounced();
  283. }
  284. }
  285. }
  286. class CustomLiquidBallModel extends HtmlResize.model {
  287. initNodeData(data) {
  288. // 自定义组件,需最开始重置一下text 。
  289. data.text = {
  290. value: "",
  291. x: data.x,
  292. y: data.y,
  293. };
  294. super.initNodeData(data);
  295. const { properties } = this;
  296. this.width = properties.width || 80;
  297. this.height = properties.height || 35;
  298. this.text.editable = false; // 不允许文本被编辑
  299. }
  300. setAttributes() {
  301. // 自定义组件需重置 text
  302. const { x, y, properties } = this;
  303. const { textHorizontalMove = 0, textVerticalMove = 0 } = properties;
  304. this.text = {
  305. ...this.text,
  306. x: x + textHorizontalMove,
  307. y: y + textVerticalMove,
  308. value: "",
  309. }
  310. }
  311. }
  312. lf.register({
  313. type: 'custom-liquidball-node',
  314. view: CustomLiquidBallNode,
  315. model: CustomLiquidBallModel,
  316. })`,css:`@keyframes wave-move1 {\r
  317. 100% {\r
  318. transform: translate(0);\r
  319. }\r
  320. }\r
  321. @keyframes wave-move2 {\r
  322. 100% {\r
  323. transform: translate(-50%);\r
  324. }\r
  325. }\r
  326. .liquidball-node .box-text {\r
  327. position: absolute;\r
  328. left: 0;\r
  329. top: 0;\r
  330. z-index: 10;\r
  331. width: 100%;\r
  332. height: 100%;\r
  333. display: flex;\r
  334. display: -webkit-flex;\r
  335. align-items: center;\r
  336. justify-content: center;\r
  337. }\r
  338. .liquidball-node .liquidballBackStyle .inner {\r
  339. width: 100%;\r
  340. height: 100%;\r
  341. position: relative;\r
  342. /* 底部100% +波浪的实际高度,bottom: calc(-100% - 60px); */\r
  343. /* bottom: -128%; */\r
  344. /* 直接对bottom操作 */\r
  345. bottom: calc(-128% + var(--per));\r
  346. }\r
  347. .liquidball-node .liquidballBackStyle .inner .box-waves {\r
  348. position: absolute;\r
  349. left: 0;\r
  350. bottom: 100%;\r
  351. width: 300%;\r
  352. stroke: none;\r
  353. }\r
  354. .liquidball-node .liquidballBackStyle .inner .box-waves:nth-child(1) {\r
  355. transform: translate(-50%);\r
  356. z-index: 3;\r
  357. animation: wave-move1 1.5s linear infinite;\r
  358. margin-bottom: -2px;\r
  359. }\r
  360. .liquidball-node .liquidballBackStyle .inner .box-waves:nth-child(2) {\r
  361. transform: translate(0);\r
  362. z-index: 2;\r
  363. animation: wave-move2 3s linear infinite;\r
  364. }`,fakeData:""},p={id:e,name:a,aliasName:t,image:n,imageType:l,groupName:i,groupType:o,isRemote:!1,isDefault:!0,sectionType:s,config:r,files:d};export{t as aliasName,r as config,p as default,d as files,i as groupName,o as groupType,e as id,n as image,l as imageType,u as isDefault,c as isRemote,a as name,s as sectionType};