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

459 lines
13 KiB

  1. const dataResolve = function () {
  2. return function (ret) {
  3. const {
  4. context, service, nodeId, dataPointStr, dynamicFlag,
  5. dataSource, deviceCode, devices, enableDataHandle, deviceAttrs, calcRules, uniquePoint, dataPoint, attrs, callBacks
  6. } = this.info
  7. if (!dataPoint)
  8. return
  9. // 寻找匹配的设备和属性
  10. const info = ret.data?.result.info || {}
  11. const apiValues = ret.data?.result.values || []
  12. let dataPointValue = ''
  13. const dataPointArr = dataPoint.split(',')
  14. const devicesArr = devices.split(',')
  15. const deviceIdCodeMap = {}
  16. const thingCodeArr = Object.keys(info).filter((code) => {
  17. if (devicesArr.includes(info[code].entityId)) {
  18. deviceIdCodeMap[info[code].entityId] = code
  19. return true
  20. }
  21. else {
  22. return false
  23. }
  24. })
  25. if (dataPointArr.length > 0) {
  26. const gotValues = apiValues.filter((val) => thingCodeArr.includes(val.thingCode) && dataPointArr.includes(val.attrKey))
  27. if (enableDataHandle) {
  28. dataPointValue = window.dataProcessFn({ info: this.info, apiid: this.apiid, defaultValueIndex: this.defaultValueIndex, values: gotValues, deviceIdCodeMap })
  29. } else {
  30. dataPointValue = JSON.stringify(gotValues)
  31. }
  32. }
  33. if (dataPointValue && dataPointValue === '[]') {
  34. return
  35. }
  36. const properties = context.getProperties(nodeId)
  37. // console.log('dataPointValue', dataPointValue)
  38. const defaultValueIndex = this.defaultValueIndex
  39. if (defaultValueIndex !== undefined) {
  40. const comboFlag = dynamicFlag === 'animationData' ? 'animationCombo' : 'hiddenCombo'
  41. if (properties.dynamic[dynamicFlag][comboFlag]) {
  42. properties.dynamic[dynamicFlag][comboFlag] = properties.dynamic[dynamicFlag][comboFlag].map((combo, idx) => {
  43. if (idx === defaultValueIndex) {
  44. combo.defaultValue = dataPointValue
  45. combo.dataPointArr = dataPointArr
  46. combo.thingCodeArr = thingCodeArr
  47. }
  48. return combo
  49. })
  50. context.setProperties(nodeId, {
  51. ...properties,
  52. apiid: this.apiid,
  53. dynamic: {
  54. ...properties.dynamic,
  55. [dynamicFlag]: {
  56. ...properties.dynamic[dynamicFlag],
  57. },
  58. },
  59. })
  60. }
  61. }
  62. else {
  63. context.setProperties(nodeId, {
  64. ...properties,
  65. apiid: this.apiid,
  66. dynamic: {
  67. ...properties.dynamic,
  68. [dynamicFlag]: {
  69. ...properties.dynamic[dynamicFlag],
  70. defaultValue: dataPointValue,
  71. dataPointArr,
  72. thingCodeArr,
  73. },
  74. },
  75. })
  76. }
  77. callBacks.forEach(fn => {
  78. fn(window.lf, nodeId)
  79. });
  80. }
  81. }
  82. // 绑定数据点处理到socket
  83. let socketMap = {};
  84. const bindSocket = (apiid, info, eventHandler) => {
  85. if (!socketMap[apiid])
  86. socketMap[apiid] = {}
  87. if (socketMap[apiid]) {
  88. if (!socketMap[apiid][info.nodeId])
  89. socketMap[apiid][info.nodeId] = {}
  90. socketMap[apiid][info.nodeId][info.dynamicFlag] = eventHandler.bind({ defaultValueIndex: info.defaultValueIndex, apiid, info })
  91. }
  92. }
  93. // 处理socket 推送
  94. const handleSocket = (Handlers, parsedData) => {
  95. for (const nodeKey in Handlers) {
  96. const nodeHandler = Handlers[nodeKey]
  97. for (const dynamicKey in nodeHandler) {
  98. const dataHandler = nodeHandler[dynamicKey]
  99. if (typeof dataHandler === 'function') {
  100. try {
  101. dataHandler(parsedData)
  102. }
  103. catch (err) {
  104. // console.log('err', err)
  105. }
  106. }
  107. }
  108. }
  109. }
  110. // 开启socket
  111. const totalGlobalDatas = {};
  112. window.totalHistoryDatas = {};
  113. window.totalApiParams = {};
  114. window.totalDeviceInfos = {};
  115. window.historyDataApiIds = [];
  116. // 用历史数据给文本部件赋值(某些业务场景,socket 数据不适用)
  117. const filterHistoryDataToNode = function () {
  118. return (apiid, info, apiValues, devices, enableDataHandle, dataPoint, nodeInfo) => {
  119. if (!dataPoint)
  120. return
  121. if (!apiValues) {
  122. return;
  123. }
  124. // 寻找匹配的设备和属性
  125. let dataPointValue = '';
  126. const dataPointArr = dataPoint.split(',')
  127. const devicesArr = devices.split(',')
  128. const deviceIdCodeMap = {};
  129. const thingCodeArr = Object.keys(info).filter((code) => {
  130. if (devicesArr.includes(info[code].entityId)) {
  131. deviceIdCodeMap[info[code].entityId] = code
  132. return true
  133. }
  134. else {
  135. return false
  136. }
  137. })
  138. if (dataPointArr.length > 0) {
  139. const gotValues = apiValues.filter((val) => thingCodeArr.includes(val.thingCode) && dataPointArr.includes(val.attrKey))
  140. if (enableDataHandle)
  141. dataPointValue = (window).dataProcessFn({ info: nodeInfo, apiid, defaultValueIndex: 0, values: gotValues, deviceIdCodeMap })
  142. else
  143. dataPointValue = JSON.stringify(gotValues)
  144. }
  145. if (dataPointValue && dataPointValue === '[]')
  146. return
  147. return {
  148. dataPointValue,
  149. thingCodeArr,
  150. dataPointArr,
  151. }
  152. }
  153. }
  154. // 设置历史数据给部件
  155. var setHistoryData = function (apidid, context, nodeId, values, info, devices, enableDataHandle, dataPoint, nodeInfo) {
  156. const ret = filterHistoryDataToNode()(apidid, info, values, devices, enableDataHandle, dataPoint, nodeInfo)
  157. if(ret) {
  158. const { dataPointValue: dataPointVal, thingCodeArr, dataPointArr } = ret
  159. if (dataPointVal) {
  160. const properties = context.getProperties(nodeId)
  161. context.setProperties(nodeId, {
  162. ...properties,
  163. apiid: apidid,
  164. dynamic: {
  165. ...properties.dynamic,
  166. [nodeInfo.dynamicFlag]: {
  167. ...properties.dynamic[nodeInfo.dynamicFlag],
  168. defaultValue: dataPointVal,
  169. thingCodeArr,
  170. dataPointArr,
  171. },
  172. },
  173. })
  174. }
  175. }
  176. }
  177. // 获取历史数据
  178. var getHistoryDatas = async (apidid, service) => {
  179. const ret = await service.get(`/v1/api/telemetryById?id=${apidid}`);
  180. if (ret.data) {
  181. window.totalHistoryDatas[apidid] = ret.data.result.values;
  182. if (!window.totalApiParams[apidid]) {
  183. window.totalApiParams[apidid] = ret.data.param;
  184. }
  185. window.totalDeviceInfos[apidid] = ret.data.result.info;
  186. return ret.data.result.values;
  187. }
  188. }
  189. var startSocket = (apiid, scriptCallbacks, service, isHistoryData) => {
  190. if (!isHistoryData) {
  191. if (socketMap[apiid]) {
  192. return;
  193. }
  194. const host = window.isDeveloping ? '192.168.8.91:8080' : window.location.host;
  195. const token = sessionStorage.getItem('token') || '';
  196. const socketUrl = `ws://${host}/thing/websocket?token=${token}&apiId=${apiid}`;
  197. const socket = new WebSocket(socketUrl);
  198. socket.onopen = function (e) {
  199. if (!socketMap[apiid]) {
  200. socketMap[apiid] = {};
  201. };
  202. };
  203. socket.onmessage = function (event) {
  204. if (!event.data) {
  205. return;
  206. }
  207. const parsedData = JSON.parse(event.data);
  208. for (const apiKey in socketMap) {
  209. if (apiKey === apiid) {
  210. const Handlers = socketMap[apiKey]
  211. handleSocket(Handlers, parsedData)
  212. if (Object.keys(Handlers).length === 0) {
  213. setTimeout(() => {
  214. handleSocket(socketMap[apiKey], parsedData)
  215. }, 1000)
  216. }
  217. }
  218. }
  219. Promise.resolve().then(() => {
  220. totalGlobalDatas[apiid] = parsedData.data.result;
  221. // 全局设备信息挂载
  222. window.globalDashboardDatas = totalGlobalDatas;
  223. scriptCallbacks.forEach((callBack) => {
  224. callBack(totalGlobalDatas)
  225. })
  226. })
  227. };
  228. socket.onclose = function (event) {
  229. socketMap[apiid] = 0;
  230. if (event.wasClean) {
  231. // alert(`[close] Connection closed cleanly, code=${event.code} reason=${event.reason}`)
  232. }
  233. else {
  234. // 例如服务器进程被杀死或网络中断
  235. // 在这种情况下,event.code 通常为 1006
  236. // alert('[close] Connection died')
  237. }
  238. };
  239. socket.onerror = function (error) {
  240. socketMap[apiid] = 0
  241. // alert(`[error] ${error.message}`)
  242. };
  243. } else {
  244. window.historyDataApiIds.push(apiid);
  245. getHistoryDatas(apiid, service);
  246. setInterval(() => {
  247. getHistoryDatas(apiid, service)
  248. }, 30000)
  249. }
  250. }
  251. // 绑定 api 请求(下拉选择框请求会用到,或其它类似有api 请求的部件)
  252. const bindApiRequest = async (info) => {
  253. const { context, nodeId, service, dataPoint, dataFilterFn, requestMethod, requestParams = 'return {};' } = info
  254. if (!dataPoint)
  255. return
  256. // eslint-disable-next-line no-new-func
  257. const paramFn = new Function('', requestParams)
  258. const paramObj = paramFn()
  259. let ret = null
  260. if (!paramObj || window._.isEmpty(paramObj)) {
  261. ret = await service[requestMethod || 'get'](dataPoint)
  262. } else {
  263. ret = await service[requestMethod || 'get'](dataPoint, paramObj)
  264. }
  265. if (ret.code === 0 && (ret.data || ret.data.list)) {
  266. const datas = ret.data || ret.data.list
  267. if (datas) {
  268. try {
  269. let newDatas = []
  270. if (datas.length > 0) {
  271. // eslint-disable-next-line no-new-func
  272. const filterFn = new Function('datas', dataFilterFn)
  273. newDatas = filterFn(datas)
  274. } else if (datas.result && datas.result.info) {
  275. // eslint-disable-next-line no-new-func
  276. const filterFn = new Function('datas', dataFilterFn)
  277. newDatas = filterFn(datas.result.info)
  278. } else if (Object.prototype.toString.call(datas) === '[object Object]') {
  279. // eslint-disable-next-line no-new-func
  280. const filterFn = new Function('datas', dataFilterFn)
  281. newDatas = filterFn(datas)
  282. }
  283. const isEmptyData = (window)._.isEmpty(newDatas)
  284. if (!isEmptyData) {
  285. const properties = context.getProperties(nodeId)
  286. context.setProperties(nodeId, {
  287. ...properties,
  288. dynamic: {
  289. ...properties.dynamic,
  290. normalData: {
  291. ...properties.dynamic.normalData,
  292. defaultOptions: JSON.stringify(newDatas),
  293. customApiDatas: newDatas
  294. },
  295. },
  296. })
  297. }
  298. }
  299. catch (error) {
  300. }
  301. }
  302. } else {
  303. if (ret.code === 401) {
  304. window.createLoginDialog();
  305. }
  306. }
  307. }
  308. var dataPointsHandlers = async (context, service, nodeId, dataPointStr, dynamicFlag = 'normalData', callBacks, index) => {
  309. if (!dataPointStr)
  310. return
  311. if (window.isJSON(dataPointStr)) {
  312. const dataPointStrParsed = JSON.parse(dataPointStr || '{}')
  313. const { dataSource, deviceCode, dataPoint, attrs, devices, enableDataHandle, deviceAttrs, calcRules, uniquePoint } = dataPointStrParsed;
  314. const nodeInfo = {
  315. context,
  316. service,
  317. nodeId,
  318. dataPointStr,
  319. dynamicFlag,
  320. dataSource,
  321. deviceCode,
  322. devices,
  323. enableDataHandle,
  324. deviceAttrs,
  325. calcRules,
  326. uniquePoint,
  327. dataPoint,
  328. attrs,
  329. callBacks,
  330. defaultValueIndex: index,
  331. };
  332. // 如果是历史数据, 则直接请求数据
  333. if (window.historyDataApiIds.includes(dataSource)) {
  334. const values = window.totalHistoryDatas[dataSource]
  335. if (window.totalHistoryDatas[dataSource]) {
  336. const info = window.totalDeviceInfos[dataSource];
  337. setHistoryData(dataSource, context, nodeId, values, info, devices, enableDataHandle, dataPoint, nodeInfo);
  338. } else {
  339. const values = await getHistoryDatas(dataSource, service);
  340. const info = window.totalDeviceInfos[dataSource];
  341. setHistoryData(dataSource, context, nodeId, values, info, devices, enableDataHandle, dataPoint, nodeInfo)
  342. }
  343. } else {
  344. bindSocket(dataSource, nodeInfo, dataResolve())
  345. }
  346. } else {
  347. // 绑定 api 请求。
  348. const props = context.getProperties(nodeId);
  349. if (!props) return;
  350. const { normalData } = props.dynamic || {}
  351. if (normalData) {
  352. const { dataPoint, dataFilterFn, requestMethod, requestParams } = normalData;
  353. if (window.isJSON(dataPoint)) {
  354. return;
  355. }
  356. bindApiRequest({
  357. context,
  358. nodeId,
  359. service,
  360. dataPoint,
  361. dataFilterFn,
  362. requestMethod,
  363. requestParams,
  364. })
  365. }
  366. }
  367. }
  368. // 连线数据解析
  369. var edgeDataResolve = function () {
  370. return function (ret) {
  371. const {
  372. context, service, edgeId, dataPointStr, dynamicFlag,
  373. dataSource, deviceCode, dataPoint, attrs, callBacks,
  374. } = (this).info
  375. if (!dataPoint)
  376. return
  377. // 寻找匹配的设备和属性
  378. const apiValues = ret.data?.result.values || []
  379. let dataPointValue = ''
  380. if (dataPoint.length > 0) {
  381. const gotValues = apiValues.filter((val) => val.thingCode === deviceCode && dataPoint.includes(val.attrKey))
  382. dataPointValue = JSON.stringify(gotValues)
  383. }
  384. if (dataPointValue && dataPointValue === '[]')
  385. return
  386. const properties = context.getProperties(edgeId)
  387. context.setProperties(edgeId, {
  388. ...properties,
  389. defaultValue: dataPointValue,
  390. })
  391. }
  392. }
  393. // 连线数据处理
  394. var edgeDataPointHandler = (context, service, edgeId, dataPointStr, dynamicFlag) => {
  395. if (!edgeId)
  396. return
  397. if (!dataPointStr)
  398. return
  399. const dataPointStrParsed = JSON.parse(dataPointStr || '{}')
  400. const { dataSource, deviceCode, dataPoint, attrs, devices, enableDataHandle, deviceAttrs, calcRules, uniquePoint } = dataPointStrParsed
  401. bindSocket(dataSource, {
  402. context,
  403. service,
  404. edgeId,
  405. dataPointStr,
  406. dynamicFlag,
  407. dataSource,
  408. deviceCode,
  409. devices,
  410. enableDataHandle,
  411. deviceAttrs,
  412. calcRules,
  413. uniquePoint,
  414. dataPoint,
  415. attrs,
  416. defaultValueIndex: 0,
  417. }, edgeDataResolve())
  418. }