|
|
const e="fe873e35-7be4-4ac8-aec8-9f4afbd4e0fd",t="custom-radios-node",a="单选按钮",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="1700709948418" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4023" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M512 65.983389c-245.919634 0-446.016611 200.095256-446.016611 446.016611 0 245.952318 200.064292 446.016611 446.016611 446.016611S958.016611 757.952318 958.016611 512C958.016611 266.080366 757.952318 65.983389 512 65.983389zM512 894.016611c-210.655557 0-382.016611-171.392017-382.016611-382.016611 0-210.655557 171.359333-382.016611 382.016611-382.016611 210.624593 0 382.016611 171.359333 382.016611 382.016611C894.016611 722.624593 722.624593 894.016611 512 894.016611z" fill="#707070" p-id="4024"></path><path d="M512 352.00086c-88.223841 0-160.00086 71.775299-160.00086 159.99914s71.775299 160.00086 160.00086 160.00086 160.00086-71.775299 160.00086-160.00086S600.223841 352.00086 512 352.00086z" fill="#707070" p-id="4025"></path></svg>',l="svg",i="基础",o="常用",c=!1,u=!0,s="文字",d=`{"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 ","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":16,"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":16,"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":"fieldset","title":"未选中外框","collapsable":true,"body":[{"type":"input-
"nodes": [ { "id": "88cbfa0c-7a9e-4da3-b727-a11eda60a3f0", "type": "custom-radios-node", "x": 200, "y": 200, "text": { "value": "", "x": 200, "y": 200 }, "properties": { "id": "88cbfa0c-7a9e-4da3-b727-a11eda60a3f0", "width": 150, "height": 30, "x": 200, "y": 200, "rotation": 0, "opacity": 1, "unselectedBorderWidth": 1, "unselectedDiameter": 16, "selectedBorderWidth": 1, "selectedDiameter": 16, "selectedInnerBorderWidth": 0, "selectedInnerDiameter": 10, "fontSize": 12, "nodeAlias": "单选按钮", "showDefaultValue": false, "showUnit": false, "valueColor": "rgba(245, 166, 35, 1)", "unselectedBorderColor": "rgba(155, 155, 155, 1)", "unselectedBackColor": "rgba(255, 255, 255, 0)", "selectedBorderColor": "rgba(74, 144, 226, 1)", "selectedBackColor": "rgba(255, 255, 255, 0)", "selectedInnerBorderColor": "rgba(74, 144, 226, 1)", "selectedInnerBackColor": "rgba(74, 144, 226, 1)", "fontColor": "rgba(74, 74, 74, 1)", "fontFamily": "Microsoft Yahei", "dynamic": { "normalData": { "dataPoint": "", "compareType": "", "conditionVariables": [], "defaultValue": "", "unit": "", "dataFilterFn": "return datas", "defaultOptions": [ { "label": "电", "value": "A29" }, { "label": "水", "value": "B2" } ] }, "eventsData": { "eventCombo": [ { "eventType": "change", "enable": false, "config": "", "customEventHandler": false, "targetParamsType": "entitys", "targetParamsEntitys": "list" } ] } } } } ]}`,javascript:`
const { createApp, createVNode, render } = Vue;const app = createApp({})const Radios = { template: \`
<div :style="getStyle"> <div v-for="(item, index) in myRadioList" :key="item.value" :style="getRadioOuter" @click="clickHandler(item)"> <input type="radio" :id="'radio' + index" name="radio" :checked="item.checked" :style="getRadioInput"/> <label :for="'radio' + index" :style="getRadioLabel(item, myRadioList, unselectedBorderWidth, unselectedBorderColor, unselectedBackColor, selectedBorderWidth, selectedBorderColor, selectedBackColor, unselectedDiameter, selectedDiameter)"> <span v-if="item.checked === 'checked'" :style="getCheckedInner"></span> <span :style="labelStyle">{{item.label}}</span> </label> </div> </div> \`,
props: { fontColor: { type: String, default: '#ffffff' }, fontSize: { type: Number, default: 14 }, fontFamily: { type: String, default: '宋体' }, fontStyle: { type: String, default: 'normal' }, width: { type: Number, default: 80 }, height: { type: Number, default: 35 }, unselectedBorderWidth: { type: Number, default: 1, }, unselectedBorderColor: { type: String, default: 'rgba(155, 155, 155, 1)' }, unselectedBackColor: { type: String, default: 'rgba(255, 255, 255, 0)' }, selectedBorderWidth: { type: Number, default: 1 }, selectedBorderColor: { type: String, default: 'rgba(74, 144, 226, 1)' }, selectedBackColor: { type: String, default: 'rgba(255, 255, 255, 0)' }, selectedInnerBorderWidth: { type: Number, default: 0 }, selectedInnerBorderColor: { type: String, default: 'rgba(74, 144, 226, 1)' }, selectedInnerBackColor: { type: String, default: 'rgba(74, 144, 226, 1)' }, unselectedDiameter: { type: Number, default: 16 }, selectedDiameter: { type: Number, default: 16 }, selectedInnerDiameter: { type: Number, default: 10 }, radioList: { type: Array, default: () => [] }, realValue: { type: String, default: '' } }, emits: ["change"], computed: { getStyle() { // const { fontColor, fontSize, fontFamily, fontStyle, width, height, lineHeight, backgroundColor,strokeColor,strokeWidth } = this
const { width, height } = this; return { width: width + 'px', height: height + 'px', display: "flex", "flex-direction": width > height ? "row" : "column", "justify-content": "flex-start", "align-items": width > height ? 'center' : 'left' } }, getRadioOuter() { const { selectedDiameter } = this; return { position: "relative", width: selectedDiameter + 'px', height: selectedDiameter + 'px', flex: '1', } }, getRadioInput() { return { position: 'absolute', visibility: 'hidden' } }, labelStyle() { const { fontColor, fontSize, fontFamily, fontStyle, selectedDiameter, selectedInnerDiameter } = this; const pos = (selectedDiameter - selectedInnerDiameter) / 2;
const style = {}; if (fontStyle) { if (fontStyle.includes('bold')) { style["font-weight"] = 'bolder'; } if (fontStyle.includes('italic')) { style["font-style"] = 'italic' } if (fontStyle.includes('underline,line-through')) { style["text-decoration"] = 'underline line-through' } else if (fontStyle.includes('line-through,underline')) { style["text-decoration"] = 'line-through underline' } else if (fontStyle.includes('underline')) { style["text-decoration"] = 'underline' } else if (fontStyle.includes('line-through')) { style["text-decoration"] = 'line-through' } }
return { position: 'absolute', top: '0px', left: pos + selectedDiameter + 5 + 'px', 'color': fontColor, 'font-size': fontSize + 'px', 'font-family': fontFamily, height: '100%', display: 'flex', 'align-items': 'center', ...style, } }, getRadioLabel: () => (item, radioList, unselectedBorderWidth, unselectedBorderColor, unselectedBackColor, selectedBorderWidth, selectedBorderColor, selectedBackColor, unselectedDiameter, selectedDiameter) => {
if (radioList.length > 0) { return { position: 'absolute', left: '0px', display: 'inline-block', width: item.checked === 'checked' ? selectedDiameter + 'px' : unselectedDiameter + 'px', height: item.checked === 'checked' ? selectedDiameter + 'px' : unselectedDiameter + 'px', "border-width": item.checked === 'checked' ? selectedBorderWidth + 'px' : unselectedBorderWidth + 'px', "border-color": item.checked === 'checked' ? selectedBorderColor : unselectedBorderColor, "border-style": "solid", 'border-radius': item.checked === 'checked' ? (selectedDiameter + 2) / 2 + 'px' : (unselectedDiameter + 2) / 2 + 'px', 'background-color': item.checked === 'checked' ? selectedBackColor : unselectedBackColor, 'box-sizing': 'content-box', 'cursor': 'pointer' } } }, getCheckedInner() { const { selectedInnerBorderWidth, selectedInnerBorderColor, selectedInnerBackColor, selectedDiameter, selectedInnerDiameter } = this const pos = (selectedDiameter - selectedInnerDiameter) / 2 + 'px' return { position: 'absolute', top: pos, left: pos, width: selectedInnerDiameter + 'px', height: selectedInnerDiameter + 'px', 'border-radius': selectedInnerDiameter / 2 + 'px', 'background-color': selectedInnerBackColor, 'border-width': selectedInnerBorderWidth + 'px', 'border-color': selectedInnerBorderColor, 'border-style': 'solid', 'box-sizing': 'border-box' } } }, setup(props, { emit }) { const { ref, watch } = Vue const myRadioList = ref([]) const clickHandler = (item) => { myRadioList.value.forEach((el) => { if (el.value === item.value) { el.checked = 'checked'; } else { el.checked = false } }) emit("change", item.value); }
watch(() => props.radioList, (val) => { myRadioList.value = val }, { immediate: true, })
watch(() => props.realValue, (val) => { if (val) { myRadioList.value.forEach((el) => { if (el.value === String(val)) { el.checked = 'checked'; } else { el.checked = false } }) } }, { immediate: true, })
return { clickHandler, myRadioList } }}
class CustomRadiosNode extends HtmlResize.view { oldProperties = {}
setHtml(rootEl) { const { properties, width, height, } = this.props.model;
const { fontColor, fontSize, fontFamily, fontStyle, unselectedBorderWidth, unselectedBorderColor, unselectedBackColor, selectedBorderWidth, selectedBorderColor, selectedBackColor, selectedInnerBorderWidth, selectedInnerBorderColor, selectedInnerBackColor, unselectedDiameter, selectedDiameter, selectedInnerDiameter } = properties; const { model, graphModel } = this.props; const el = document.createElement('div'); rootEl.innerHTML = ''; const { normalData } = properties.dynamic || {}; const { defaultOptions } = normalData || {}; let list = []; if (defaultOptions) { let opts = [] if (typeof defaultOptions !== 'string') { opts = defaultOptions } else { opts = JSON.parse(defaultOptions); } list = window._.cloneDeep(opts).map((el, index) => { if (index === 0) { el.checked = 'checked' } else { el.checked = false } return el; }) }
let realValue = ""; if (normalData) { realValue = window.resolveScadaNewValue(normalData.defaultValue); }
const changeHandler = (e) => { graphModel.eventCenter.emit("node:change", { data: this.props.model, e, }); }
const instance = createVNode(Radios, { realValue, radioList: list, fontColor, fontSize, fontFamily, fontStyle, width, height, unselectedBorderWidth, unselectedBorderColor, unselectedBackColor, selectedBorderWidth, selectedBorderColor, selectedBackColor, selectedInnerBorderWidth, selectedInnerBorderColor, selectedInnerBackColor, unselectedDiameter, selectedDiameter, selectedInnerDiameter, onChange: changeHandler }) 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 CustomRadiosModel 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; }
setAttributes() { // 自定义组件需重置 text
const { x, y, properties } = this; const { textHorizontalMove = 0, textVerticalMove = 0 } = properties; this.text = { ...this.text, x: x + textHorizontalMove, y: y + textVerticalMove, value: "", } }}
lf.register({ type: 'custom-radios-node', view: CustomRadiosNode, model: CustomRadiosModel,})
`,css:`.scada-radio {\r position: relative;\r width: 16px;\r height: 16px;\r}\r.scada-radio input {\r position: absolute;\r visibility: hidden\r}\r.scada-radio label {\r position: absolute;\r display: inline-block;\r width: 16px;\r height: 16px;\r border: 1px solid #d7d7d7;\r border-radius: 9px;\r}\r/*选中状态*/\r.nm-radio input:checked + label {\r border: 1px solid #1baede;\r}\r.nm-radio input:checked + label:before {\r content: "";\r position: absolute;\r top: 3px; left: 3px;\r width: 10px;\r height: 10px;\r border-radius: 5px;\r background-color: #1baede;\r}`,fakeData:""},m={id:e,name:t,aliasName:a,image:n,imageType:l,groupName:i,groupType:o,isRemote:!1,isDefault:!0,sectionType:s,config:d,files:r};export{a as aliasName,d as config,m as default,r as files,i as groupName,o as groupType,e as id,n as image,l as imageType,u as isDefault,c as isRemote,t as name,s as sectionType};
|