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

465 lines
52 KiB

  1. const e="e46b9366-f350-4130-8b74-b718deccc636",a="custom-form-input",n="表单输入框",t='<?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="1700615525422" class="icon" viewBox="0 0 1170 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5042" xmlns:xlink="http://www.w3.org/1999/xlink" width="228.515625" height="200"><path d="M1024 128a39.862857 39.862857 0 0 1 36.571429 42.788571v682.422858a39.862857 39.862857 0 0 1-36.571429 42.788571H146.285714a39.862857 39.862857 0 0 1-36.571428-42.788571V170.788571A39.862857 39.862857 0 0 1 146.285714 128h877.714286M1024 0H146.285714C65.462857 0 0 76.434286 0 170.788571v682.422858C0 947.565714 65.462857 1024 146.285714 1024h877.714286c80.822857 0 146.285714-76.434286 146.285714-170.788571V170.788571C1170.285714 76.434286 1104.822857 0 1024 0z" fill="#4C4A58" p-id="5043"></path><path d="M310.857143 292.571429A54.857143 54.857143 0 0 0 256 347.428571v329.142858a54.857143 54.857143 0 0 0 109.714286 0v-329.142858A54.857143 54.857143 0 0 0 310.857143 292.571429z" fill="#51C75B" p-id="5044"></path><path d="M365.714286 292.571429H256a54.857143 54.857143 0 0 0 0 109.714285h109.714286a54.857143 54.857143 0 0 0 0-109.714285zM365.714286 621.714286H256a54.857143 54.857143 0 0 0 0 109.714285h109.714286a54.857143 54.857143 0 0 0 0-109.714285z" fill="#51C75B" p-id="5045"></path><path d="M556.251429 621.714286a54.857143 54.857143 0 1 0 54.857142 54.857143 54.857143 54.857143 0 0 0-54.857142-54.857143zM746.788571 621.714286a54.857143 54.857143 0 1 0 54.857143 54.857143 54.857143 54.857143 0 0 0-54.857143-54.857143z" fill="#4C4A58" p-id="5046"></path></svg>',l="svg",o="基础",i="常用",c=!1,u=!0,d="文字",s=`{"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",
  2. "nodes": [
  3. {
  4. "id": "62459966-2658-4f68-b00b-1cebd129d176",
  5. "type": "custom-form-input",
  6. "x": 200,
  7. "y": 200,
  8. "text": {
  9. "value": "",
  10. "x": 200,
  11. "y": 200
  12. },
  13. "properties": {
  14. "id": "62459966-2658-4f68-b00b-1cebd129d176",
  15. "width": 165,
  16. "height": 38,
  17. "x": 200,
  18. "y": 200,
  19. "rotation": 0,
  20. "opacity": 1,
  21. "showConfirmBtn": true,
  22. "showSearchIcon": false,
  23. "confirmText": "确认",
  24. "confirmBack": "#1984eb",
  25. "confirmTextColor": "rgba(255, 255, 255, 1)",
  26. "confirmTextSize": 14,
  27. "confirmWidth": 50,
  28. "placeholder": "请输入文本...",
  29. "placeholderColor": "",
  30. "inputBackground": "rgba(155, 155, 155, 0.5)",
  31. "borderWidth": 1,
  32. "borderRadius": 2,
  33. "fontSize": 14,
  34. "showChangeDialog": false,
  35. "radios": "yes",
  36. "nodeAlias": "表单输入框",
  37. "showDefaultValue": false,
  38. "showUnit": false,
  39. "valueColor": "rgba(245, 166, 35, 1)",
  40. "borderColor": "#1984eb",
  41. "borderStyle": "solid",
  42. "fontColor": "#1984eb",
  43. "fontFamily": "Microsoft Yahei",
  44. "inputTextAlign": "center",
  45. "fontStyle": "",
  46. "searchIconColor": "#1296db",
  47. "inputGradBack": "",
  48. "dynamic": {
  49. "normalData": {
  50. "dataPoint": "",
  51. "compareType": "",
  52. "conditionVariables": [],
  53. "defaultValue": "",
  54. "unit": ""
  55. },
  56. "eventsData": {
  57. "eventCombo": [
  58. {
  59. "eventType": "change",
  60. "enable": false,
  61. "config": "",
  62. "users": ""
  63. }
  64. ]
  65. }
  66. }
  67. }
  68. }
  69. ]
  70. }`,javascript:`const { createApp, createVNode, render } = Vue;
  71. const app = createApp({})
  72. const FormInput = {
  73. template: \`<div :style="getBorderStyle" @click="focus">
  74. <span v-if="showSearchIcon" :style="getSearchIconStyle(fontSize, iconColor, inputBackground)" >
  75. <svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="70%" height="70%">
  76. <path d="M966.4 924.8l-230.4-227.2c60.8-67.2 96-156.8 96-256 0-217.6-176-390.4-390.4-390.4-217.6 0-390.4 176-390.4 390.4 0 217.6 176 390.4 390.4 390.4 99.2 0 188.8-35.2 256-96l230.4 227.2c9.6 9.6 28.8 9.6 38.4 0C979.2 950.4 979.2 934.4 966.4 924.8zM102.4 441.6c0-185.6 150.4-339.2 339.2-339.2s339.2 150.4 339.2 339.2c0 89.6-35.2 172.8-92.8 233.6-3.2 0-3.2 3.2-6.4 3.2-3.2 3.2-3.2 3.2-3.2 6.4-60.8 57.6-144 92.8-233.6 92.8C256 780.8 102.4 627.2 102.4 441.6z" :fill="searchIconColor"></path>
  77. </svg>
  78. </span>
  79. <input ref="inputRef" v-model="inputValue" :style="getInputStyle" :placeholder="placeholder" class="scada-form-input" @change="changeDebounced" @input="inputHandler"/>
  80. <div v-if="showConfirmBtn" :style="getBtnStyle" @click="changeHandler">{{confirmText}}</div>
  81. </div>\`,
  82. props: {
  83. realValue: {
  84. type: String,
  85. default: ''
  86. },
  87. fontColor: {
  88. type: String,
  89. default: '#ffffff'
  90. },
  91. fontSize: {
  92. type: Number,
  93. default: 14
  94. },
  95. fontFamily: {
  96. type: String,
  97. default: '宋体'
  98. },
  99. fontStyle: {
  100. type: String,
  101. default: 'normal'
  102. },
  103. width: {
  104. type: Number,
  105. default: 80
  106. },
  107. height: {
  108. type: Number,
  109. default: 35
  110. },
  111. lineHeight: {
  112. type: Number,
  113. default: 35,
  114. },
  115. showConfirmBtn: {
  116. type: Boolean,
  117. default: true,
  118. },
  119. showChangeDialog: {
  120. type: Boolean,
  121. default: true,
  122. },
  123. confirmText: {
  124. type: String,
  125. default: '确认'
  126. },
  127. confirmBack: {
  128. type: String,
  129. default: '#1984eb'
  130. },
  131. confirmWidth: {
  132. type: Number,
  133. default: 70
  134. },
  135. placeholder: {
  136. type: String,
  137. default: '请输入文本'
  138. },
  139. placeholderColor: {
  140. type: String,
  141. default: ''
  142. },
  143. inputBackground: {
  144. type: String,
  145. default: 'rgba(155, 155, 155, 0.5)'
  146. },
  147. inputGradBack: {
  148. type: String,
  149. default: ''
  150. },
  151. borderWidth: {
  152. type: Number,
  153. default: 1
  154. },
  155. borderRadius: {
  156. type: Number,
  157. default: 2
  158. },
  159. borderColor: {
  160. type: String,
  161. default: '#1984eb'
  162. },
  163. borderStyle: {
  164. type: String,
  165. default: 'solid'
  166. },
  167. confirmTextColor: {
  168. type: String,
  169. default: '#ffffff'
  170. },
  171. inputTextAlign: {
  172. type: String,
  173. default: 'center'
  174. },
  175. confirmTextSize: {
  176. type: Number,
  177. default: 14
  178. },
  179. showSearchIcon: {
  180. type: Boolean,
  181. default: false
  182. },
  183. searchIconColor: {
  184. type: String,
  185. default: '#1296db'
  186. }
  187. },
  188. emits: ["change"],
  189. computed: {
  190. getBorderStyle() {
  191. const { width, height, borderWidth, borderRadius, borderColor, borderStyle } = this
  192. return {
  193. width: width + 'px',
  194. height: height + 'px',
  195. "border-radius": borderRadius + 'px',
  196. "border-color": borderColor,
  197. "border-style": borderStyle,
  198. "border-width": borderWidth + 'px',
  199. "box-sizing": "border-box",
  200. "display": "flex"
  201. }
  202. },
  203. getInputStyle() {
  204. const { width, confirmWidth, inputBackground, inputGradBack, placeholderColor, showConfirmBtn, fontColor, fontSize, fontFamily, fontStyle, inputTextAlign, showSearchIcon } = this;
  205. const style = {};
  206. if (fontStyle) {
  207. if (fontStyle.includes('bold')) {
  208. style["font-weight"] = 'bolder';
  209. }
  210. if (fontStyle.includes('italic')) {
  211. style["font-style"] = 'italic'
  212. }
  213. if (fontStyle.includes('underline,line-through')) {
  214. style["text-decoration"] = 'underline line-through'
  215. } else if (fontStyle.includes('line-through,underline')) {
  216. style["text-decoration"] = 'line-through underline'
  217. } else if (fontStyle.includes('underline')) {
  218. style["text-decoration"] = 'underline'
  219. } else if (fontStyle.includes('line-through')) {
  220. style["text-decoration"] = 'line-through'
  221. }
  222. }
  223. if (inputGradBack && !inputGradBack.includes('url')) {
  224. style.background = \`url(\${inputGradBack})\`;
  225. style.backgroundSize = '100% 100%';
  226. }
  227. let w = width + "px";
  228. if (showConfirmBtn && !showSearchIcon) {
  229. w = width - confirmWidth + "px";
  230. } else if (showSearchIcon && !showConfirmBtn) {
  231. w = width - 30 + "px"
  232. } else if (showSearchIcon && showConfirmBtn) {
  233. w = width - confirmWidth - 30 + "px";
  234. }
  235. return {
  236. "width": w,
  237. "background-color": inputBackground,
  238. "outline": "none",
  239. "border": "none",
  240. "font-size": fontSize + "px",
  241. "color": fontColor,
  242. "font-family": fontFamily,
  243. "text-align": inputTextAlign,
  244. "text-indent": inputTextAlign === "left" ? "5px" : "0px",
  245. ...style,
  246. }
  247. },
  248. getBtnStyle() {
  249. const { confirmWidth, height, confirmBack, confirmTextColor, fontSize, confirmTextSize } = this;
  250. return {
  251. "flex": "0 0 " + confirmWidth + "px",
  252. "color": confirmTextColor,
  253. "font-size": confirmTextSize + "px",
  254. "background-color": confirmBack,
  255. "text-align": "center",
  256. "line-height": height + "px",
  257. "cursor": "pointer",
  258. }
  259. },
  260. getSearchIconStyle: () => (fontSize, iconColor, inputBackground) => {
  261. return {
  262. flex: '0 0 30px',
  263. display: 'flex',
  264. 'justify-content': 'center',
  265. 'align-items': 'center',
  266. 'font-size': fontSize + 'px',
  267. color: iconColor,
  268. background: inputBackground
  269. }
  270. }
  271. },
  272. setup(props, { emit }) {
  273. const { ref, watch } = Vue;
  274. const inputValue = ref(null);
  275. const inputRef = ref(null);
  276. const isInputing = ref(false);
  277. const changeCallback = (e) => {
  278. if (!props.showConfirmBtn) {
  279. emit("change", e.target.value);
  280. isInputing.value = false;
  281. }
  282. }
  283. const changeDebounced = window._.debounce(changeCallback, 1000);
  284. const changeHandler = () => {
  285. emit("change", inputValue.value);
  286. isInputing.value = false;
  287. }
  288. watch(() => props.realValue, (val) => {
  289. if (isInputing.value) {
  290. return;
  291. }
  292. val && (inputValue.value = val);
  293. }, {
  294. immediate: true,
  295. })
  296. watch(() => props.placeholderColor, (val) => {
  297. if (val) {
  298. const root = document.querySelector(':root');
  299. root.style.setProperty('--scada-input-placeholder-color', val);
  300. }
  301. }, {
  302. immediate: true
  303. })
  304. const focus = () => {
  305. setTimeout(() => {
  306. inputRef.value.focus();
  307. }, 100)
  308. }
  309. let timeOut = null;
  310. const inputHandler = () => {
  311. isInputing.value = true;
  312. if (!props.showConfirmBtn) {
  313. if (timeOut) {
  314. clearTimeout(timeOut)
  315. }
  316. timeOut = setTimeout(() => {
  317. isInputing.value = false;
  318. }, 5000)
  319. }
  320. }
  321. return {
  322. changeDebounced,
  323. inputValue,
  324. changeHandler,
  325. inputRef,
  326. focus,
  327. inputHandler,
  328. }
  329. }
  330. }
  331. class CustomFormInputNode extends HtmlResize.view {
  332. oldProperties = {};
  333. instance = null;
  334. setHtml(rootEl) {
  335. const { properties, width, height, } = this.props.model;
  336. const {
  337. fontColor, fontSize, fontFamily, fontStyle, lineHeight,
  338. showConfirmBtn, showChangeDialog, confirmText, confirmBack, confirmWidth, placeholder, showSearchIcon, searchIconColor,
  339. inputBackground, inputGradBack, placeholderColor, borderWidth, borderRadius, borderColor, borderStyle, confirmTextColor, inputTextAlign, confirmTextSize
  340. } = properties;
  341. const { model, graphModel } = this.props;
  342. const { normalData, eventsData } = properties.dynamic || {};
  343. let realValue = "";
  344. if (normalData) {
  345. realValue = window.resolveScadaNewValue(normalData.defaultValue);
  346. }
  347. const changeHandler = (e) => {
  348. const findChange = eventsData?.eventCombo.find( i => i.eventType === 'change');
  349. const cacheToken = sessionStorage.getItem('v1@CacheToken');
  350. if(!cacheToken) {
  351. return window.createLoginDialog();
  352. }
  353. const tokenParsed = JSON.parse(cacheToken || '{}');
  354. if (findChange.users && !findChange.users.includes(tokenParsed.userid)) {
  355. return messageFn('无用户权限')
  356. }
  357. graphModel.eventCenter.emit("node:change", {
  358. data: this.props.model,
  359. e,
  360. });
  361. }
  362. if (this.instance) {
  363. Object.assign(this.instance.component.props, {
  364. realValue,
  365. fontColor,
  366. fontSize, fontFamily, fontStyle, width, height, lineHeight, showSearchIcon, searchIconColor,
  367. showConfirmBtn, showChangeDialog, confirmText, confirmBack, confirmWidth, placeholder, placeholderColor,
  368. inputBackground, inputGradBack, borderWidth, borderRadius, borderColor, borderStyle, confirmTextColor, inputTextAlign, confirmTextSize,
  369. onChange: changeHandler
  370. })
  371. return;
  372. }
  373. const el = document.createElement('div');
  374. rootEl.innerHTML = '';
  375. const instance = createVNode(FormInput, {
  376. realValue,
  377. fontColor,
  378. fontSize, fontFamily, fontStyle, width, height, lineHeight, showSearchIcon, searchIconColor,
  379. showConfirmBtn, showChangeDialog, confirmText, confirmBack, confirmWidth, placeholder, placeholderColor,
  380. inputBackground, inputGradBack, borderWidth, borderRadius, borderColor, borderStyle, confirmTextColor, inputTextAlign, confirmTextSize,
  381. onChange: changeHandler
  382. })
  383. instance.appContext = app._context
  384. render(instance, el)
  385. rootEl.appendChild(el);
  386. this.instance = instance;
  387. }
  388. sameProps(properties) {
  389. const isSame = window._.isEqual(this.oldProperties, properties);
  390. if (isSame) return true;
  391. this.oldProperties = properties;
  392. return false
  393. }
  394. // 生命周期 支持重写���容, 但格式需一致
  395. shouldUpdate() {
  396. const { properties } = this.props.model;
  397. const propertiesBack = window._.cloneDeep(properties);
  398. // 由于事件change 会给properties 增加一个 event 属性(见目录scadaDashboard/Diagram/useDynamicEventsHandler),会引发属性的改变,导致组件重渲染。
  399. delete propertiesBack.event;
  400. if (this.sameProps(propertiesBack)) {
  401. return false
  402. }
  403. return true;
  404. }
  405. }
  406. class CustomFormInputModel extends HtmlResize.model {
  407. initNodeData(data) {
  408. // 自定义组件,需最开始重置一下text 。
  409. data.text = {
  410. value: "",
  411. x: data.x,
  412. y: data.y,
  413. };
  414. super.initNodeData(data);
  415. const { properties } = this;
  416. this.width = properties.width || 80;
  417. this.height = properties.height || 35;
  418. }
  419. setAttributes() {
  420. // 自定义组件需重置 text
  421. const { x, y, properties } = this;
  422. const { textHorizontalMove = 0, textVerticalMove = 0 } = properties;
  423. this.text = {
  424. ...this.text,
  425. x: x + textHorizontalMove,
  426. y: y + textVerticalMove,
  427. value: "",
  428. }
  429. }
  430. }
  431. lf.register({
  432. type: 'custom-form-input',
  433. view: CustomFormInputNode,
  434. model: CustomFormInputModel,
  435. })
  436. `,css:`:root{\r
  437. --scada-input-placeholder-color: #999;\r
  438. }\r
  439. input.scada-form-input::-webkit-input-placeholder{\r
  440. color: var(--scada-input-placeholder-color);\r
  441. }`,fakeData:""},m={id:e,name:a,aliasName:n,image:t,imageType:l,groupName:o,groupType:i,isRemote:!1,isDefault:!0,sectionType:d,config:s,files:r};export{n as aliasName,s as config,m as default,r as files,o as groupName,i as groupType,e as id,t as image,l as imageType,u as isDefault,c as isRemote,a as name,d as sectionType};