|
|
const e="52d9f250-25be-450a-9aa4-809fefd989fa",n="custom-iframe-node",t="网页",a='<?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="1698398010161" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5163" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M64 904V120c0-30.93 25.07-56 56-56h784c30.93 0 56 25.07 56 56v784c0 30.93-25.07 56-56 56H120c-30.93 0-56-25.07-56-56z" fill="#E1F5FF" p-id="5164"></path><path d="M960 260H64V120c0-30.93 25.07-56 56-56h784c30.93 0 56 25.07 56 56v140z" fill="#8C9EFF" p-id="5165"></path><path d="M176 162m-28 0a28 28 0 1 0 56 0 28 28 0 1 0-56 0Z" fill="#FF4343" p-id="5166"></path><path d="M260 162m-28 0a28 28 0 1 0 56 0 28 28 0 1 0-56 0Z" fill="#FFD600" p-id="5167"></path><path d="M344 162m-28 0a28 28 0 1 0 56 0 28 28 0 1 0-56 0Z" fill="#65FF40" p-id="5168"></path><path d="M582 451.33H274c-23.2 0-42 18.8-42 42s18.8 42 42 42h308c23.2 0 42-18.8 42-42 0-23.19-18.8-42-42-42zM750 684.67H274c-23.2 0-42 18.8-42 42s18.8 42 42 42h476c23.2 0 42-18.8 42-42s-18.8-42-42-42z" fill="#313FA0" p-id="5169"></path></svg>',i="svg",l="动态",s="数据展示",p=!1,c=!0,o="时间",r=`{"id":"u:270584784ce1","type":"page","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 ","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":"input-text","label":"链�
"nodes": [ { "id": "28c1cc50-eecd-4534-afef-bd752f52aaa2", "type": "custom-iframe-node", "x": 200, "y": 200, "text": { "value": "", "x": 200, "y": 200 }, "properties": { "id": "28c1cc50-eecd-4534-afef-bd752f52aaa2", "width": 500, "height": 300, "x": 200, "y": 200, "rotation": 0, "opacity": 1, "disableClick": false, "nodeAlias": "外链", "showDefaultValue": false, "showUnit": false, "valueColor": "rgba(245, 166, 35, 1)", "fontSize": 12, "linkAddress": "", "dynamic": { "normalData": { "dataPoint": "", "compareType": "", "conditionVariables": [], "defaultValue": "", "unit": "", "iframeScript": "", "iframeOuterScript": "", "iframePlugins": [ { "input-text": "./plugins/vue.min.js" }, { "input-text": "./plugins/axios.min.js" }, { "input-text": "./plugins/lodash.js" }, { "input-text": "./plugins/dayjs.min.js" }, { "input-text": "./plugins/service.js" }, { "input-text": "./iconfonts/iconfont.css" }, { "input-text": "./plugins/layui/css/layui.css" }, { "input-text": "./plugins/layui/layui.js" } ] }, "eventsData": { "eventCombo": [ { "eventType": "change", "enable": false, "config": "" } ] } } } } ]}`,javascript:`const { createApp, createVNode, render } = Vue;const app = createApp({})
const timeArr = new Array(24).fill('');const totals = [];timeArr.forEach((i, index) => { const t = window.dayjs().hour(index).valueOf(); totals.push({ val: Math.random(1000) * 100, ts: t, attrKey: "A29" }) });const defaultSocketValue = []
const generateHTML = (innerPage, plugins, iframeScript) => { return \`<html>
<head> </head> <body> \${innerPage} <script type="module" id="_script"> window.addEventListener('message', function(event) { if (event.data.event === 'tokenSend') { window.iframeNodeToken = event.data.token; } });
const loadInnerScript = () => { if (\${JSON.stringify(iframeScript)}) { const innderScript = document.createElement('script'); innderScript.type = 'module'; innderScript.innerHTML = \${JSON.stringify(iframeScript)}; setTimeout(() => { document.body.append(innderScript); }, 200); }; };
let loadPlugin = function (url, index) { if (url.endsWith('.css')) { const linkDom = document.createElement('link'); linkDom.rel = "stylesheet"; linkDom.href = url; linkDom.onload = () => { if (index === \${JSON.stringify(plugins)}.length - 1) { loadInnerScript(); } else { loadPlugin(\${JSON.stringify(plugins)}[index + 1]['input-text'], index + 1); } }; document.body.append(linkDom); } else { const scriptDom = document.createElement('script'); scriptDom.src = url; scriptDom.onload = () => { if (index === \${JSON.stringify(plugins)}.length - 1) { loadInnerScript(); } else { loadPlugin(\${JSON.stringify(plugins)}[index + 1]['input-text'], index + 1); } }; document.body.append(scriptDom); } }; if (\${JSON.stringify(plugins)}.length > 0) { loadPlugin(\${JSON.stringify(plugins)}[0]['input-text'], 0); } window?.parent.postMessage('childFrameLoaded', '*'); </\\script> </body> </html\`}
const IframeNode = { template: \`<div :style="getIframeOuterStyle">
<iframe v-if="!linkAddress && iframeScript" :id="chartId" ref="iframeRef" width="100%" height="100%" sandbox="allow-scripts allow-modals allow-same-origin" frameborder="0" draggable="false"></iframe> <iframe v-if="linkAddress && !iframeScript" :src="linkAddress" :id="chartId" ref="iframeRef" width="100%" height="100%" sandbox="allow-scripts allow-modals allow-same-origin" frameborder="0" draggable="false"></iframe> <div v-if="!linkAddress && !iframeScript" style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; border: 1px solid #00ffff; box-sizing: border-box;color: #F5A623">暂无内容</div> </div> \`,
props: { chartId: { type: String, default: '' }, width: { type: Number, default: 350 }, height: { type: Number, default: 150 }, codeConfig: { type: String, default: '' }, linkAddress: { type: String, default: '' }, iframeScript: { type: String, default: '' }, iframePlugins: { type: Array, default: () => [] }, disableClick: { type: Boolean, default: false } }, computed: { getIframeOuterStyle() { return { width: '100%', height: '100%', cursor: 'default', 'pointer-events': this.disableClick ? 'none' : 'auto', } }, }, emits: ['iframeDataSend'], setup(props, { emit }) { const { nextTick, ref, onMounted } = Vue;
const iframeRef = ref(null);
onMounted(() => { nextTick(() => { if (iframeRef.value) { // 给iframe 注入token
const cacheToken = sessionStorage.getItem('v1@CacheToken'); const tokenParsed = JSON.parse(cacheToken || '{}'); const tokenArr = window.location.search.split('token='); const token = tokenParsed.token || sessionStorage.getItem('token') || window.developToken || tokenArr[1]; window.addEventListener('message', function (event) { emit('iframeDataSend', event.data); if (event.data === 'childFrameLoaded') { if (iframeRef.value.contentWindow) { iframeRef.value.contentWindow.postMessage({ event: 'tokenSend', token: token }); } } }) if (props.linkAddress && props.iframeScript) { const xhr = new XMLHttpRequest(); xhr.open("GET", props.linkAddress, true); xhr.send(); xhr.addEventListener("load", () => { const resText = xhr.responseText; iframeRef.value.srcdoc = generateHTML(resText, props.iframePlugins, props.iframeScript) }); } else if (!props.linkAddress && props.iframeScript) { iframeRef.value.srcdoc = generateHTML('', props.iframePlugins, props.iframeScript) } } }) })
return { iframeRef } }}
class CustomIframeNode extends HtmlResize.view { oldProperties = {}
setHtml(rootEl) { if (!rootEl) return; const { properties, width, height, } = this.props.model; const { nodeAlias, codeConfig, linkAddress, disableClick } = properties; const { iframeScript, iframeOuterScript, iframePlugins } = properties.dynamic.normalData || {}; const { model, graphModel } = this.props;
const fn = new Function('context', 'iframeData', iframeOuterScript); const handleIframeData = (iframeData) => { if (iframeOuterScript) { fn(window.lf || this, iframeData); } else { graphModel.eventCenter.emit("node:change", { data: model, e: iframeData, }); } }
const el = document.createElement('div'); el.style.width = "100%"; el.style.height = "100%"; rootEl.innerHTML = ''; const instance = createVNode(IframeNode, { name: nodeAlias, chartId: \`iframe-\${properties.id}\`,
width, height, codeConfig, linkAddress, iframeScript, iframePlugins, disableClick, onIframeDataSend: handleIframeData }) instance.appContext = app._context render(instance, el) rootEl.appendChild(el); }
sameProps(properties) { const isSame = window._.isEqual(this.oldProperties, properties); if (isSame) return true; this.oldProperties = properties; return false }
// 生命周期 支持重写内容, 但格式需一致
shouldUpdate() { const { properties } = this.props.model; const propertiesBack = window._.cloneDeep(properties); // 由于事件change 会给properties 增加一个 event 属性(见目录scadaDashboard/Diagram/useDynamicEventsHandler),会引发属性的改变,导致组件重渲染。
delete propertiesBack.event; if (this.sameProps(propertiesBack)) { return false } return true; }}
class CustomIframeModel extends HtmlResize.model { initNodeData(data) { // 自定义组件,需最开始重置一下text 。
data.text = { value: "", x: data.x, y: data.y, };
super.initNodeData(data); const { properties } = this; this.width = properties.width || 80; this.height = properties.height || 35; this.text.editable = false; // 不允许文本被编辑
}
setAttributes() { // 自定义组件需重置 text
const { x, y, properties } = this; const { textHorizontalMove = 0, textVerticalMove = 0 } = properties; this.text = { ...this.text, x: x + textHorizontalMove, y: y + textVerticalMove, value: "", } }
getResizeOutlineStyle() { return { stroke: "#00ffff", strokeWidth: 1, strokeDasharray: "none", }; }}
lf.register({ type: 'custom-iframe-node', view: CustomIframeNode, model: CustomIframeModel,})`,css:"",fakeData:""},u={id:e,name:n,aliasName:t,image:a,imageType:i,groupName:l,groupType:s,isRemote:!1,isDefault:!0,sectionType:o,config:r,files:d};export{t as aliasName,r as config,u as default,d as files,l as groupName,s as groupType,e as id,a as image,i as imageType,c as isDefault,p as isRemote,n as name,o as sectionType};
|