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

470 lines
17 KiB

  1. var messageFn = (msg) => {
  2. layui.use('layer', function(){
  3. const layer = layui.layer;
  4. layer.msg(msg);
  5. });
  6. }
  7. const operateVariableFunc = (lfInstance, configObj, event, response) => {
  8. configObj.operateVariables.forEach((variable) => {
  9. const value = variable.selectedVariable.split('=')
  10. // eslint-disable-next-line no-new-func
  11. const func = new Function('inputParamsTable', 'globalInputParamsCalculated', 'response', 'event', variable.newValue)
  12. if (!configObj.globalInputParamsCalculated) {
  13. return;
  14. }
  15. if (Array.isArray(configObj.globalInputParamsCalculated)) {
  16. const globalInputParams = configObj.globalInputParamsCalculated.length > 0 ? configObj.globalInputParamsCalculated : configObj.inputParamsTable;
  17. const returnValue = func(configObj.inputParamsTable, globalInputParams, response, event)
  18. lfInstance.setProperties(value[0], {
  19. [value[1]]: returnValue,
  20. })
  21. }
  22. else {
  23. const len = Object.keys(configObj.globalInputParamsCalculated).length;
  24. const globalInputParams = len > 0 ? configObj.globalInputParamsCalculated : configObj.inputParamsTable;
  25. const returnValue = func(configObj.inputParamsTable, globalInputParams, response, event);
  26. lfInstance.setProperties(value[0], {
  27. [value[1]]: returnValue,
  28. })
  29. }
  30. })
  31. }
  32. const realParamsCalculated = async (configObj, event) => {
  33. let params = null
  34. if (configObj.inputParamsCalculate) {
  35. // 实时入参计算
  36. // eslint-disable-next-line no-new-func
  37. const func = new Function('deviceInfo', 'command', 'event', configObj.inputParamsCalculate)
  38. if (!(window).globalDashboardDatas)
  39. params = func(configObj.device, configObj.command, event)
  40. else
  41. params = func(configObj.device, configObj.command, event)
  42. }
  43. if (params.event && params.event instanceof PointerEvent) {
  44. params.event = ''
  45. }
  46. return params
  47. }
  48. const commandNextHandlers = (lfInstance, configObj, refreshFuncs, event, response) => {
  49. if (configObj.commandNext) {
  50. configObj.commandNext.forEach((next) => {
  51. if (next.value === 'refreshBoard') {
  52. // 刷新看板
  53. refreshFuncs.forEach((func) => {
  54. func()
  55. })
  56. }
  57. else if (next.value === 'operateVariable') {
  58. operateVariableFunc(lfInstance, configObj, event, response)
  59. }
  60. else if (next.value === 'showOrHide') {
  61. // eslint-disable-next-line no-new-func
  62. const fn = new Function('e', configObj.showHideNewValue)
  63. const comps = fn(event)
  64. if (comps && comps.toString() === '[object Object]') {
  65. for (const key in comps) {
  66. const nodeModel = lfInstance.getNodeModelById(key)
  67. nodeModel.visible = comps[key] === 'show'
  68. if (nodeModel.properties.showHideContainChildren) {
  69. const areaElements = window.calcInsideAreaElements(lfInstance, {
  70. nodes: [nodeModel],
  71. edges: [],
  72. })
  73. areaElements.forEach((cNode) => {
  74. cNode.visible = nodeModel.visible
  75. lfInstance.setProperties(cNode.id, {
  76. visible: nodeModel.visible,
  77. })
  78. })
  79. }
  80. }
  81. }
  82. }
  83. })
  84. }
  85. }
  86. const sendCommand = async (event, lfInstance, configObj, refreshFuncs) => {
  87. let headers = {}
  88. configObj.requestUrl = configObj.requestUrl.replace('/thing', '')
  89. if (configObj.requestHeader) {
  90. headers = configObj.requestHeader.reduce((prev, curr) => {
  91. prev[curr.key] = curr.value
  92. return prev
  93. }, {})
  94. }
  95. if (configObj.requestMethod === 'get') {
  96. let params = {}
  97. if (configObj.paramsTable) {
  98. params = configObj.paramsTable.reduce((prev, curr) => {
  99. prev[curr.key] = curr.value
  100. return prev
  101. }, {})
  102. const realParams = realParamsCalculated(configObj, event)
  103. if (realParams) {
  104. params = realParams
  105. }
  106. }
  107. service.get(configObj.requestUrl, params, headers).then((res) => {
  108. if (res.code !== 0)
  109. return messageFn(res.msg)
  110. commandNextHandlers(lfInstance, configObj, refreshFuncs, event, res)
  111. })
  112. }
  113. else if (configObj.requestMethod === 'post' || configObj.requestMethod === 'put') {
  114. let params = configObj.bodyJson
  115. const realParams = await realParamsCalculated(configObj, event)
  116. if (realParams) {
  117. params = realParams
  118. }
  119. const commandInfo = await service.get(`/device/control/${configObj.command.id}`);
  120. if (commandInfo.code !== 0) {
  121. return messageFn(res.msg)
  122. }
  123. const { userList } = commandInfo.data
  124. const cacheToken = sessionStorage.getItem('v1@CacheToken');
  125. if(!cacheToken) {
  126. return window.createLoginDialog();
  127. }
  128. const tokenParsed = JSON.parse(cacheToken || '{}');
  129. if (userList && !userList.includes(tokenParsed.userid)) {
  130. return messageFn('无用户权限')
  131. }
  132. service[configObj.requestMethod](configObj.requestUrl, params, {
  133. headers: {
  134. 'Content-Type': 'application/json',
  135. ...headers,
  136. },
  137. }).then((res) => {
  138. if (res.code !== 0)
  139. return messageFn(res.msg)
  140. messageFn(res.data)
  141. commandNextHandlers(lfInstance, configObj, refreshFuncs, event, res)
  142. }).catch(() => {})
  143. }
  144. }
  145. const eventsHandler = (event, eventConfig, lfInstance, refreshFuncs) => {
  146. const configObj = JSON.parse(eventConfig.config)
  147. if (configObj.eventAction === 'openLink') {
  148. let params = ''
  149. if (configObj.dataPointParamsCalculate) {
  150. let newDataPointTable = [];
  151. if (configObj.dataPointTable) {
  152. newDataPointTable = configObj.dataPointTable.map((param) => {
  153. const dataPoint = JSON.parse(param.dataPoint || '{}')
  154. return dataPoint
  155. })
  156. }
  157. // eslint-disable-next-line no-new-func
  158. const func = new Function('paramsList', newDataPointTable)
  159. const returnParams = func()
  160. if (Array.isArray(returnParams)) {
  161. params = returnParams.reduce((prev, curr) => {
  162. if (curr.key) {
  163. return `${prev}${prev ? '&' : ''}` + `${curr.key}=${curr.value}`
  164. }
  165. return prev
  166. }, '')
  167. }
  168. }
  169. let linkAddress = `${configObj.linkAddress}${params}`
  170. if (configObj.openMethod === 'openNewPage') {
  171. if (!linkAddress.includes('http'))
  172. linkAddress = `http://${linkAddress}`
  173. window.open(linkAddress, '_blank', ' ')
  174. }
  175. else {
  176. const origin = window.location.origin
  177. if (linkAddress.includes(origin)) {
  178. window.location.href = linkAddress
  179. } else {
  180. if (origin.includes('localhost'))
  181. window.location.href = origin + linkAddress
  182. else
  183. window.location.href = `${origin}/scada${linkAddress}`
  184. }
  185. }
  186. }
  187. else if (configObj.eventAction === 'openDialog') {
  188. window.layui.use('layer', () => {
  189. const layer = window.layui.layer
  190. const idx = layer.confirm(
  191. configObj.dialogContent,
  192. {
  193. btn: ['确认', '取消'], // 按钮
  194. },
  195. () => {
  196. sendCommand(event, lfInstance, configObj, refreshFuncs);
  197. layer.closeAll()
  198. },
  199. () => {
  200. layer.closeAll();
  201. }
  202. )
  203. // 重新设置标题
  204. layer.title(configObj.dialogTitle, idx)
  205. })
  206. }
  207. else if (configObj.eventAction === 'sendCommand') {
  208. if (configObj.sendCommandMethod === 'codes') {
  209. // eslint-disable-next-line no-new-func
  210. const func = new Function('context', 'service', 'command', 'event', configObj.commandContent)
  211. func(lfInstance, service, configObj.selectCommand, event)
  212. }
  213. else {
  214. sendCommand(event, lfInstance, configObj, refreshFuncs)
  215. }
  216. }
  217. else if (configObj.eventAction === 'operateVariable') {
  218. // 操作变量之前,获取实时入参计算
  219. const realParams = realParamsCalculated(configObj, event)
  220. if (realParams) {
  221. configObj.globalInputParamsCalculated = realParams
  222. }
  223. operateVariableFunc(lfInstance, configObj, event, null)
  224. }
  225. else if (configObj.eventAction === 'showHide') {
  226. // eslint-disable-next-line no-new-func
  227. const fn = new Function('e', configObj.showHideNewValue)
  228. const comps = fn(event)
  229. if (comps && comps.toString() === '[object Object]') {
  230. for (const key in comps) {
  231. const nodeModel = lfInstance.getNodeModelById(key)
  232. nodeModel.visible = comps[key] === 'show'
  233. if (nodeModel.properties.showHideContainChildren) {
  234. const areaElements = window.calcInsideAreaElements(lfInstance, {
  235. nodes: [nodeModel],
  236. edges: [],
  237. })
  238. areaElements.forEach((cNode) => {
  239. cNode.visible = nodeModel.visible
  240. lfInstance.setProperties(cNode.id, {
  241. visible: nodeModel.visible,
  242. })
  243. })
  244. }
  245. }
  246. }
  247. }
  248. }
  249. const eventsHandlerDebounced = window.myDebounce(eventsHandler, 200)
  250. var eventHandlers = (lfInstance, emit, refreshFuncs) => {
  251. // 单个节点点击
  252. lfInstance.on('myNode:click', ({ data, e }) => {
  253. const eventsData = data.properties.dynamic?.eventsData?.eventCombo || []
  254. const clickConfig = eventsData.find((ev) => ev.eventType === 'click')
  255. if (!clickConfig)
  256. return
  257. if (clickConfig.enable && clickConfig.config)
  258. eventsHandlerDebounced(e, clickConfig, lfInstance, refreshFuncs)
  259. })
  260. // 节点双击
  261. lfInstance.on('myNode:dbclick', ({ data, e }) => {
  262. const eventsData = data.properties.dynamic?.eventsData?.eventCombo || []
  263. const clickConfig = eventsData.find((ev) => ev.eventType === 'dblClick')
  264. if (!clickConfig)
  265. return
  266. if (clickConfig.enable && clickConfig.config)
  267. eventsHandlerDebounced(e, clickConfig, lfInstance, refreshFuncs)
  268. })
  269. // 节点值改变
  270. lfInstance.on('node:change', ({ data, e }) => {
  271. const oldProps = lfInstance.getProperties(data.id)
  272. lfInstance.setProperties(data.id, { event: e })
  273. const { normalData } = oldProps.dynamic || {}
  274. const { dataPoint } = normalData || {}
  275. const eventsData = data.properties.dynamic?.eventsData?.eventCombo || []
  276. const clickConfig = eventsData.find((ev) => ev.eventType === 'change')
  277. if (!clickConfig)
  278. return
  279. if (clickConfig.enable && clickConfig.config) {
  280. if (window.isJSON(clickConfig.config)) {
  281. eventsHandlerDebounced(e, clickConfig, lfInstance, refreshFuncs)
  282. } else {
  283. // 自定义函数代码处理
  284. // eslint-disable-next-line no-new-func
  285. const handlerFn = new Function('context', 'service', 'nodeId', 'event', clickConfig.config)
  286. try {
  287. handlerFn(lfInstance, service, data.id, e)
  288. } catch (err) {}
  289. }
  290. } else if (clickConfig.enable && !clickConfig.config) {
  291. if (clickConfig.targetNode && clickConfig.apiId) {
  292. const evVal = e.value || e;
  293. const apiParams = window.totalApiParams[clickConfig.apiId] || {}
  294. const requestParams = {
  295. entitys: window._.cloneDeep(apiParams.entitys),
  296. attrs: window._.cloneDeep(apiParams.attrs),
  297. }
  298. const isArr = Object.prototype.toString.call(evVal) === '[object Array]'
  299. if (clickConfig.targetParamsType === 'entitys') {
  300. if (!requestParams.entitys)
  301. requestParams.entitys = {}
  302. requestParams.entitys[clickConfig.targetParamsEntitys] = isArr ? evVal : [evVal]
  303. lfInstance.setProperties(clickConfig.targetNode, {
  304. requestParams,
  305. apiId: clickConfig.apiId
  306. })
  307. }
  308. else if (clickConfig.targetParamsType === 'attrs') {
  309. if (!requestParams.attrs)
  310. requestParams.attrs = {}
  311. if (clickConfig.targetParamsAttrsType === 'all') {
  312. requestParams.attrs.type = 'all'
  313. if (clickConfig.targetParamsAttrsKeysEntitys === 'keys')
  314. requestParams.attrs.keys = isArr ? evVal : [evVal]
  315. }
  316. else {
  317. requestParams.attrs.type = 'split'
  318. if (clickConfig.targetParamsAttrsKeysEntitys === 'entitys') {
  319. const newKeys = isArr ? evVal : [evVal]
  320. const findExactEntityAttrs = []
  321. newKeys.forEach((k) => {
  322. if (requestParams.attrs.entitys) {
  323. requestParams.attrs.entitys.forEach((item) => {
  324. if (item.entitys.includes(k)) {
  325. findExactEntityAttrs.push({
  326. entitys: [k],
  327. keys: item.keys,
  328. keyType: 'SQ',
  329. })
  330. }
  331. })
  332. }
  333. })
  334. requestParams.attrs.keys = findExactEntityAttrs
  335. }
  336. else if (clickConfig.targetParamsAttrsKeysEntitys === 'keys') {
  337. const newKeys = isArr ? evVal : [evVal]
  338. const findExactEntityAttrs = []
  339. newKeys.forEach((k) => {
  340. if (requestParams.attrs.keys) {
  341. requestParams.attrs.keys.forEach((item) => {
  342. if (item.keys.includes(k)) {
  343. findExactEntityAttrs.push({
  344. entitys: item.entitys,
  345. keys: [k],
  346. keyType: "SQ"
  347. })
  348. }
  349. })
  350. }
  351. })
  352. if (findExactEntityAttrs.length > 0) {
  353. requestParams.attrs.keys = findExactEntityAttrs
  354. } else {
  355. requestParams.attrs.keys = newKeys
  356. }
  357. }
  358. }
  359. lfInstance.setProperties(clickConfig.targetNode, {
  360. requestParams,
  361. apiId: clickConfig.apiId
  362. })
  363. }
  364. else if (clickConfig.targetParamsType === 'times') {
  365. requestParams.times = {}
  366. if (clickConfig.targetParamsTimesType === 'nearest') {
  367. requestParams.times.nearest = evVal
  368. }
  369. else if (clickConfig.targetParamsTimesType === 'range') {
  370. const isObj = typeof e === 'object'
  371. if (isObj) {
  372. requestParams.times.startTime = e.startTime || e.start || e.startDate
  373. requestParams.times.endTime = e.endTime || e.end || e.endDate
  374. }
  375. }
  376. else if (clickConfig.targetParamsTimesType === 'interval') {
  377. const isObj = typeof e === 'object'
  378. if (isObj) {
  379. const { duration, type } = e
  380. requestParams.times.duration = duration
  381. requestParams.times.type = type
  382. }
  383. }
  384. lfInstance.setProperties(clickConfig.targetNode, {
  385. requestParams,
  386. apiId: clickConfig.apiId
  387. })
  388. }
  389. // 请求数据
  390. // 给超级api 传参, 过滤出所需的物。数据源id 可以在看板左侧数据源那里复制得到。
  391. service.get(`/v1/api/telemetryById?id=${clickConfig.apiId}&reqParams=${encodeURIComponent(JSON.stringify(requestParams))}`).then((res) => {
  392. if (res.code === 0) {
  393. if (res.data.result?.values) {
  394. const resDatas = res.data.result.values
  395. // 用返回值给目标部件赋值。目标部件的id 需替换成对应部件的id.
  396. const properties = lfInstance.getProperties(clickConfig.targetNode)
  397. if (!properties)
  398. return
  399. lfInstance.setProperties(clickConfig.targetNode, {
  400. ...properties,
  401. apiid: clickConfig.apiId, // apiid 一定要传入
  402. dynamic: {
  403. ...properties.dynamic,
  404. normalData: {
  405. ...properties.dynamic.normalData,
  406. defaultValue: JSON.stringify(resDatas), // 数据传入
  407. },
  408. },
  409. })
  410. }
  411. }
  412. })
  413. // 更多界面操作
  414. if (clickConfig.moreOperation) {
  415. // eslint-disable-next-line no-new-func
  416. const handlerFn = new Function('context', 'service', 'nodeId', 'event', clickConfig.moreOperation)
  417. try {
  418. handlerFn(lfInstance, service, data.id, e)
  419. }
  420. catch (err) {}
  421. }
  422. } else {
  423. // 更多界面操作
  424. if (clickConfig.moreOperation) {
  425. // eslint-disable-next-line no-new-func
  426. const handlerFn = new Function('context', 'service', 'nodeId', 'event', clickConfig.moreOperation)
  427. try {
  428. handlerFn(lfInstance, service, data.id, e)
  429. }
  430. catch (err) {}
  431. }
  432. }
  433. }
  434. })
  435. // 节点进入
  436. lfInstance.on('myNode:mouseenter', ({ data, e }) => {
  437. const eventsData = data.properties.dynamic?.eventsData?.eventCombo || []
  438. const clickConfig = eventsData.find((ev) => ev.eventType === 'mouseEnter')
  439. if (!clickConfig)
  440. return
  441. if (clickConfig.enable && clickConfig.config)
  442. eventsHandlerDebounced(e, clickConfig, lfInstance, refreshFuncs)
  443. })
  444. // 节点离开
  445. lfInstance.on('myNode:mouseleave', ({ data, e }) => {
  446. const eventsData = data.properties.dynamic?.eventsData?.eventCombo || []
  447. const clickConfig = eventsData.find((ev) => ev.eventType === 'mouseLeave')
  448. if (!clickConfig)
  449. return
  450. if (clickConfig.enable && clickConfig.config)
  451. eventsHandlerDebounced(e, clickConfig, lfInstance, refreshFuncs)
  452. })
  453. }