diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000000000000000000000000000000000000..009783b61fea20a777d828e8ffde460833d9bcf3 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,39 @@ +module.exports = { + 'env': { + 'browser': true, + 'es6': true + }, + 'extends': [ + 'eslint:recommended', + 'plugin:vue/essential' + ], + 'globals': { + 'Atomics': 'readonly', + 'SharedArrayBuffer': 'readonly' + }, + 'parserOptions': { + 'ecmaVersion': 2018, + 'sourceType': 'module' + }, + 'plugins': [ + 'vue' + ], + 'rules': { + 'indent': [ + 'error', + 'tab' + ], + 'linebreak-style': [ + 'error', + 'unix' + ], + 'quotes': [ + 'error', + 'single' + ], + 'semi': [ + 'error', + 'always' + ] + } +}; diff --git a/babel.config.js b/babel.config.js index e9558405fdcc02f12d757acb308e02937a7444f1..98b0a6cc5d4fed5ff7b56c4f93485a0813d10a4a 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,5 +1,5 @@ module.exports = { - presets: [ - '@vue/cli-plugin-babel/preset' - ] -} + presets: [ + '@vue/cli-plugin-babel/preset' + ] +}; diff --git a/install-render.js b/install-render.js index da60086cf16c5e04e44d90b3e31d1d9c7e836fdc..4e72d95e7780f8bff63b277b57f3d77e817d03ba 100644 --- a/install-render.js +++ b/install-render.js @@ -1,29 +1,29 @@ -import VFormRender from '@/components/form-render/index.vue' -import {loadExtension} from "@/extension/extension-loader" -import axios from "axios" +import VFormRender from '@/components/form-render/index.vue'; +import {loadExtension} from '@/extension/extension-loader'; +import axios from 'axios'; -loadExtension() +loadExtension(); VFormRender.install = function (Vue) { - Vue.component(VFormRender.name, VFormRender) -} + Vue.component(VFormRender.name, VFormRender); +}; const components = [ - VFormRender -] + VFormRender +]; const install = (Vue) => { - window.axios = axios - components.forEach(component => { - Vue.component(component.name, component) - }) -} + window.axios = axios; + components.forEach(component => { + Vue.component(component.name, component); + }); +}; if (typeof window !== 'undefined' && window.Vue) { /* script方式引入时主动调用install方法!! */ - install(window.Vue); + install(window.Vue); } export default { - install, - VFormRender -} + install, + VFormRender +}; diff --git a/install.js b/install.js index 71df8869ff856b84cc068957121cc2fcdae1823c..6ed9c31dbb3f7eb846ac06c1def70d6c84a91d5d 100644 --- a/install.js +++ b/install.js @@ -1,41 +1,41 @@ -import axios from 'axios' +import axios from 'axios'; -import VFormDesigner from '@/components/form-designer/index.vue' -import VFormRender from '@/components/form-render/index.vue' -import {loadExtension} from "@/extension/extension-loader" +import VFormDesigner from '@/components/form-designer/index.vue'; +import VFormRender from '@/components/form-render/index.vue'; +import {loadExtension} from '@/extension/extension-loader'; -import '@/utils/directive' -import '@/icons' -import '@/iconfont/iconfont.css' +import '@/utils/directive'; +import '@/icons'; +import '@/iconfont/iconfont.css'; -loadExtension() +loadExtension(); VFormDesigner.install = function (Vue) { - Vue.component(VFormDesigner.name, VFormDesigner) -} + Vue.component(VFormDesigner.name, VFormDesigner); +}; VFormRender.install = function (Vue) { - Vue.component(VFormRender.name, VFormRender) -} + Vue.component(VFormRender.name, VFormRender); +}; const components = [ - VFormDesigner, - VFormRender -] + VFormDesigner, + VFormRender +]; const install = (Vue) => { - window.axios = axios - components.forEach(component => { - Vue.component(component.name, component) - }) -} + window.axios = axios; + components.forEach(component => { + Vue.component(component.name, component); + }); +}; if (typeof window !== 'undefined' && window.Vue) { /* script方式引入时主动调用install方法!! */ - install(window.Vue); + install(window.Vue); } export default { - install, - VFormDesigner, - VFormRender -} + install, + VFormDesigner, + VFormRender +}; diff --git a/package.json b/package.json index ddbe10b60251cd8d8378918779c361fec21515a0..10bd2eb3533089e518cb281516f5a8cf01c0eb63 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "variant-form", - "version": "2.2.7", + "name": "xy-vform", + "version": "2.3.0", "private": false, "scripts": { "serve": "vue-cli-service serve --open src/main.js", @@ -10,6 +10,7 @@ "lint": "vue-cli-service lint" }, "dependencies": { + "@popperjs/core": "^2.11.6", "axios": "^0.21.1", "clipboard": "^2.0.8", "core-js": "^3.6.5", diff --git a/pro/3e94b4b3b6dcf0f77a164293733d20e.png b/pro/3e94b4b3b6dcf0f77a164293733d20e.png new file mode 100644 index 0000000000000000000000000000000000000000..6fee968661133ef0126acc2cd4991106b5beae52 Binary files /dev/null and b/pro/3e94b4b3b6dcf0f77a164293733d20e.png differ diff --git a/pro/95737186ebd7582b780b3c1ddd831bb.png b/pro/95737186ebd7582b780b3c1ddd831bb.png new file mode 100644 index 0000000000000000000000000000000000000000..56f580201a6fdac811e3e630c3eb23b6387dd306 Binary files /dev/null and b/pro/95737186ebd7582b780b3c1ddd831bb.png differ diff --git a/pro/dynamic-dialog.vue b/pro/dynamic-dialog.vue new file mode 100644 index 0000000000000000000000000000000000000000..c26beefb5ef526f6dca81c6732beb903f93c99c1 --- /dev/null +++ b/pro/dynamic-dialog.vue @@ -0,0 +1,177 @@ + + + + + diff --git a/pro/util.js b/pro/util.js new file mode 100644 index 0000000000000000000000000000000000000000..81ee34f9ab9c60681bda2db6a461202db58b57e6 --- /dev/null +++ b/pro/util.js @@ -0,0 +1,559 @@ +import Clipboard from 'clipboard'; +import axios from 'axios'; + +export function isNull(value) { + return (value === null) || (value === undefined); +} + +export function isNotNull(value) { + return (value !== null) && (value !== undefined); +} + +export function isEmptyStr(str) { + //return (str === undefined) || (!str) || (!/[^\s]/.test(str)); + return (str === undefined) || (!str && (str !== 0) && (str !== '0')) || (!/[^\s]/.test(str)); +} + +export const generateId = function() { + return Math.floor(Math.random() * 100000 + Math.random() * 20000 + Math.random() * 5000); +}; + +export const deepClone = function (origin) { + if (origin === undefined) { + return undefined; + } + + return JSON.parse(JSON.stringify(origin)); +}; + +export const overwriteObj = function(obj1, obj2) { /* 浅拷贝对象属性,obj2覆盖obj1 */ + // for (let prop in obj2) { + // if (obj2.hasOwnProperty(prop)) { + // obj1[prop] = obj2[prop] + // } + // } + + Object.keys(obj2).forEach(prop => { + obj1[prop] = obj2[prop]; + }); +}; + +export const addWindowResizeHandler = function (handler) { + let oldHandler = window.onresize; + if (typeof window.onresize != 'function') { + window.onresize = handler; + } else { + window.onresize = function () { + oldHandler(); + handler(); + }; + } +}; + +const createStyleSheet = function() { + let head = document.head || document.getElementsByTagName('head')[0]; + let style = document.createElement('style'); + style.type = 'text/css'; + head.appendChild(style); + return style.sheet; +}; + +export const insertCustomCssToHead = function (cssCode, formId = '') { + let head = document.getElementsByTagName('head')[0]; + let oldStyle = document.getElementById('vform-custom-css'); + if (oldStyle) { + head.removeChild(oldStyle); //先清除后插入!! + } + if (formId) { + oldStyle = document.getElementById('vform-custom-css' + '-' + formId); + !!oldStyle && head.removeChild(oldStyle); //先清除后插入!! + } + + let newStyle = document.createElement('style'); + newStyle.type = 'text/css'; + newStyle.rel = 'stylesheet'; + newStyle.id = formId ? 'vform-custom-css' + '-' + formId : 'vform-custom-css'; + try { + newStyle.appendChild(document.createTextNode(cssCode)); + } catch(ex) { + newStyle.styleSheet.cssText = cssCode; + } + + head.appendChild(newStyle); +}; + +export const insertGlobalFunctionsToHtml = function (functionsCode, formId = '') { + let bodyEle = document.getElementsByTagName('body')[0]; + let oldScriptEle = document.getElementById('v_form_global_functions'); + !!oldScriptEle && bodyEle.removeChild(oldScriptEle); //先清除后插入!! + if (formId) { + oldScriptEle = document.getElementById('v_form_global_functions' + '-' + formId); + !!oldScriptEle && bodyEle.removeChild(oldScriptEle); //先清除后插入!! + } + + let newScriptEle = document.createElement('script'); + newScriptEle.id = formId ? 'v_form_global_functions' + '-' + formId : 'v_form_global_functions'; + newScriptEle.type = 'text/javascript'; + newScriptEle.innerHTML = functionsCode; + bodyEle.appendChild(newScriptEle); +}; + +export const optionExists = function(optionsObj, optionName) { + if (!optionsObj) { + return false; + } + + return Object.keys(optionsObj).indexOf(optionName) > -1; +}; + +export const loadRemoteScript = function(srcPath, callback) { /*加载远程js,加载成功后执行回调函数*/ + let sid = encodeURIComponent(srcPath); + let oldScriptEle = document.getElementById(sid); + + if (!oldScriptEle) { + let s = document.createElement('script'); + s.src = srcPath; + s.id = sid; + document.body.appendChild(s); + + s.onload = s.onreadystatechange = function (_, isAbort) { /* 借鉴自ace.js */ + if (isAbort || !s.readyState || s.readyState === 'loaded' || s.readyState === 'complete') { + s = s.onload = s.onreadystatechange = null; + if (!isAbort) { + callback(); + } + } + }; + } +}; + +export function traverseFieldWidgets(widgetList, handler, parent = null, staticWidgetsIncluded) { + widgetList.forEach(w => { + if (w.formItemFlag || ((w.formItemFlag === false) && staticWidgetsIncluded)) { + handler(w, parent); + } else if (w.type === 'grid') { + w.cols.forEach(col => { + traverseFieldWidgets(col.widgetList, handler, w, staticWidgetsIncluded); + }); + } else if (w.type === 'table') { + w.rows.forEach(row => { + row.cols.forEach(cell => { + traverseFieldWidgets(cell.widgetList, handler, w, staticWidgetsIncluded); + }); + }); + } else if (w.type === 'tab') { + w.tabs.forEach(tab => { + traverseFieldWidgets(tab.widgetList, handler, w, staticWidgetsIncluded); + }); + } else if (w.type === 'sub-form' || w.type === 'grid-sub-form') { + traverseFieldWidgets(w.widgetList, handler, w, staticWidgetsIncluded); + } else if (w.category === 'container') { //自定义容器 + traverseFieldWidgets(w.widgetList, handler, w, staticWidgetsIncluded); + } + }); +} + +export function traverseContainerWidgets(widgetList, handler) { + widgetList.forEach(w => { + if (w.category === 'container') { + handler(w); + } + + if (w.type === 'grid') { + w.cols.forEach(col => { + traverseContainerWidgets(col.widgetList, handler); + }); + } else if (w.type === 'table') { + w.rows.forEach(row => { + row.cols.forEach(cell => { + traverseContainerWidgets(cell.widgetList, handler); + }); + }); + } else if (w.type === 'tab') { + w.tabs.forEach(tab => { + traverseContainerWidgets(tab.widgetList, handler); + }); + } else if (w.type === 'sub-form' || w.type === 'grid-sub-form') { + traverseContainerWidgets(w.widgetList, handler); + } else if (w.category === 'container') { //自定义容器 + traverseContainerWidgets(w.widgetList, handler); + } + }); +} + +export function traverseAllWidgets(widgetList, handler) { + widgetList.forEach(w => { + handler(w); + + if (w.type === 'grid') { + w.cols.forEach(col => { + handler(col); + traverseAllWidgets(col.widgetList, handler); + }); + } else if (w.type === 'table') { + w.rows.forEach(row => { + row.cols.forEach(cell => { + handler(cell); + traverseAllWidgets(cell.widgetList, handler); + }); + }); + } else if (w.type === 'tab') { + w.tabs.forEach(tab => { + traverseAllWidgets(tab.widgetList, handler); + }); + } else if (w.type === 'sub-form' || w.type === 'grid-sub-form') { + traverseAllWidgets(w.widgetList, handler); + } else if (w.category === 'container') { //自定义容器 + traverseAllWidgets(w.widgetList, handler); + } + }); +} + +function handleWidgetForTraverse(widget, handler) { + if (!!widget.category && (widget.category === 'container')) { + traverseFieldWidgetsOfContainer(widget, handler); + } else if (widget.formItemFlag) { + handler(widget); + } +} + +/** + * 遍历容器内的字段组件 + * @param con + * @param handler + */ +export function traverseFieldWidgetsOfContainer(con, handler) { + if (con.type === 'grid') { + con.cols.forEach(col => { + col.widgetList.forEach(cw => { + handleWidgetForTraverse(cw, handler); + }); + }); + } else if (con.type === 'table') { + con.rows.forEach(row => { + row.cols.forEach(cell => { + cell.widgetList.forEach(cw => { + handleWidgetForTraverse(cw, handler); + }); + }); + }); + } else if (con.type === 'tab') { + con.tabs.forEach(tab => { + tab.widgetList.forEach(cw => { + handleWidgetForTraverse(cw, handler); + }); + }); + } else if (con.type === 'sub-form' || con.type === 'grid-sub-form') { + con.widgetList.forEach(cw => { + handleWidgetForTraverse(cw, handler); + }); + } else if (con.category === 'container') { //自定义容器 + con.widgetList.forEach(cw => { + handleWidgetForTraverse(cw, handler); + }); + } +} + +function handleContainerTraverse(widget, fieldHandler, containerHandler) { + if (!!widget.category && (widget.category === 'container')) { + traverseWidgetsOfContainer(widget, fieldHandler, containerHandler); + } else if (widget.formItemFlag) { + fieldHandler(widget); + } +} + +/** + * 遍历容器内部的字段组件和容器组件 + * @param con + * @param fieldHandler + * @param containerHandler + */ +export function traverseWidgetsOfContainer(con, fieldHandler, containerHandler) { + if (con.type === 'grid') { + con.cols.forEach(col => { + col.widgetList.forEach(cw => { + handleContainerTraverse(cw, fieldHandler, containerHandler); + }); + }); + } else if (con.type === 'table') { + con.rows.forEach(row => { + row.cols.forEach(cell => { + cell.widgetList.forEach(cw => { + handleContainerTraverse(cw, fieldHandler, containerHandler); + }); + }); + }); + } else if (con.type === 'tab') { + con.tabs.forEach(tab => { + tab.widgetList.forEach(cw => { + handleContainerTraverse(cw, fieldHandler, containerHandler); + }); + }); + } else if (con.type === 'sub-form' || con.type === 'grid-sub-form') { + con.widgetList.forEach(cw => { + handleContainerTraverse(cw, fieldHandler, containerHandler); + }); + } else if (con.category === 'container') { //自定义容器 + con.widgetList.forEach(cw => { + handleContainerTraverse(cw, fieldHandler, containerHandler); + }); + } +} + +/** + * 获取所有字段组件 + * @param widgetList + * @param staticWidgetsIncluded 是否包含按钮等静态组件,默认不包含 + * @returns {[]} + */ +export function getAllFieldWidgets(widgetList, staticWidgetsIncluded) { + let result = []; + let handlerFn = (w) => { + result.push({ + type: w.type, + name: w.options.name, + field: w + }); + }; + traverseFieldWidgets(widgetList, handlerFn, null, staticWidgetsIncluded); + + return result; +} + +/** + * 获取所有容器组件 + * @param widgetList + * @returns {[]} + */ +export function getAllContainerWidgets(widgetList) { + let result = []; + let handlerFn = (w) => { + result.push({ + type: w.type, + name: w.options.name, + container: w + }); + }; + traverseContainerWidgets(widgetList, handlerFn); + + return result; +} + +export function getFieldWidgetByName(widgetList, fieldName, staticWidgetsIncluded) { + let foundWidget = null; + let handlerFn = (widget) => { + if (widget.options.name === fieldName) { + foundWidget = widget; + } + }; + + traverseFieldWidgets(widgetList, handlerFn, null, staticWidgetsIncluded); + return foundWidget; +} + +export function getContainerWidgetByName(widgetList, containerName) { + let foundContainer = null; + let handlerFn = (con) => { + if (con.options.name === containerName) { + foundContainer = con; + } + }; + + traverseContainerWidgets(widgetList, handlerFn); + return foundContainer; +} + +export function getContainerWidgetById(widgetList, containerId) { + let foundContainer = null; + let handlerFn = (con) => { + if (con.id === containerId) { + foundContainer = con; + } + }; + + traverseContainerWidgets(widgetList, handlerFn); + return foundContainer; +} + +export function copyToClipboard(content, clickEvent, $message, successMsg, errorMsg) { + const clipboard = new Clipboard(clickEvent.target, { + text: () => content + }); + + clipboard.on('success', () => { + $message.success(successMsg); + clipboard.destroy(); + }); + + clipboard.on('error', () => { + $message.error(errorMsg); + clipboard.destroy(); + }); + + clipboard.onClick(clickEvent); +} + +export function getQueryParam(variable) { + let query = window.location.search.substring(1); + let vars = query.split('&'); + for (let i=0; i 0)) { + rawData.forEach(ri => { + result.push({ + label: ri[labelKey], + value: ri[valueKey] + }); + }); + } + + return result; +} + +/** + * 组装axios请求配置参数 + * @param arrayObj + * @param DSV + * @param VFR + * @returns {{}} + */ +export function assembleAxiosConfig(arrayObj, DSV, VFR) { + let result = {}; + if (!arrayObj || (arrayObj.length <= 0)) { + return result; + } + + arrayObj.map(ai => { + if (ai.type === 'String') { + result[ai.name] = String(ai.value); + } else if (ai.type === 'Number') { + result[ai.name] = Number(ai.value); + } else if (ai.type === 'Boolean') { + if ((ai.value.toLowerCase() === 'false') || (ai.value === '0')) { + result[ai.name] = false; + } else if ((ai.value.toLowerCase() === 'true') || (ai.value === '1')) { + result[ai.name] = true; + } else { + result[ai.name] = null; + } + } else if (ai.type === 'Variable') { + result[ai.name] = eval(ai.value); + } + }); + + /* 需要注意:VFR.getWidgetRef()可能无法获取组件,因为组件尚未创建完成,跟数据源执行时机有关!! */ + + /* 加入如下两行日志打印代码,是为了防止编译打包时DSV、VFR参数被剔除!! begin */ + /* DSV、VFR入参没有在本函数中直接使用到,但在eval表达式中可能被使用到,故需确保DSV、VFR参数始终存在!! */ + console.log('test DSV: ', DSV); + console.log('test VFR: ', VFR); + /* 加入如下两行日志打印代码,是为了防止编译打包时DSV、VFR入参会被剔除!! end */ + + return result; +} + +function buildRequestConfig(dataSource, DSV, VFR, isSandbox) { + let config = {}; + if (dataSource.requestURLType === 'String') { + config.url = dataSource.requestURL; + } else { + config.url = eval(dataSource.requestURL); + } + config.method = dataSource.requestMethod; + + config.headers = assembleAxiosConfig(dataSource.headers, DSV, VFR); + config.params = assembleAxiosConfig(dataSource.params, DSV, VFR); + config.data = assembleAxiosConfig(dataSource.data, DSV, VFR); + + + let chFn = new Function('config', 'isSandbox', 'DSV', 'VFR', dataSource.configHandlerCode); + return chFn.call(null, config, isSandbox, DSV, VFR); +} + +export async function runDataSourceRequest(dataSource, DSV, VFR, isSandbox, $message) { + try { + let requestConfig = buildRequestConfig(dataSource, DSV, VFR, isSandbox); + let result = await axios.request(requestConfig); + //let result = await axios.create().request(requestConfig) + + let dhFn = new Function('result', 'isSandbox', 'DSV', 'VFR', dataSource.dataHandlerCode); + return dhFn.call(null, result, isSandbox, DSV, VFR); + } catch (err) { + let ehFn = new Function('error', 'isSandbox', 'DSV', '$message', 'VFR', dataSource.errorHandlerCode); + ehFn.call(null, err, isSandbox, DSV, $message, VFR); + console.error(err); + } +} + +export function getDSByName(formConfig, dsName) { + let resultDS = null; + if (!!dsName && !!formConfig.dataSources) { + formConfig.dataSources.forEach(ds => { + if (ds.uniqueName === dsName) { + resultDS = ds; + } + }); + } + + return resultDS; +} diff --git a/pro/vf-dialog-item.vue b/pro/vf-dialog-item.vue new file mode 100644 index 0000000000000000000000000000000000000000..09c207162051c0cac36edb351a3b75a021c7e700 --- /dev/null +++ b/pro/vf-dialog-item.vue @@ -0,0 +1,13 @@ + + + + + diff --git a/pro/vf-dialog-widget.vue b/pro/vf-dialog-widget.vue new file mode 100644 index 0000000000000000000000000000000000000000..b99d6f940707f8775c0f7e45e3e99f9785739907 --- /dev/null +++ b/pro/vf-dialog-widget.vue @@ -0,0 +1,160 @@ + + + + + diff --git "a/pro/\346\226\260\345\273\272\346\226\207\344\273\266\345\244\271.zip" "b/pro/\346\226\260\345\273\272\346\226\207\344\273\266\345\244\271.zip" new file mode 100644 index 0000000000000000000000000000000000000000..e941e9f6ed59305cef15b173bd14baf50b4dfeed Binary files /dev/null and "b/pro/\346\226\260\345\273\272\346\226\207\344\273\266\345\244\271.zip" differ diff --git a/src/App.vue b/src/App.vue index c0e75a7a19d4e9fb894da1dfd94bbf79111461e8..ec588c64723edc9831c882cadfb97ba6de8f016d 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,35 +1,34 @@ diff --git a/src/components/form-designer/form-widget/container-widget/containerMixin.js b/src/components/form-designer/form-widget/container-widget/containerMixin.js index fc0f2b11749bdcaee3040a933f974495b99a9f8a..45104890a1102e8f94b04e229c73dc4ecebc6d74 100644 --- a/src/components/form-designer/form-widget/container-widget/containerMixin.js +++ b/src/components/form-designer/form-widget/container-widget/containerMixin.js @@ -1,92 +1,125 @@ -export default { - methods: { - appendTableRow(widget) { - this.designer.appendTableRow(widget) - }, - - appendTableCol(widget) { - this.designer.appendTableCol(widget) - }, - - onContainerDragAdd(evt, subList) { - const newIndex = evt.newIndex - if (!!subList[newIndex]) { - this.designer.setSelected( subList[newIndex] ) - } - - this.designer.emitHistoryChange() - this.designer.emitEvent('field-selected', this.widget) - }, - - onContainerDragUpdate() { - this.designer.emitHistoryChange() - }, - - checkContainerMove(evt) { - return this.designer.checkWidgetMove(evt) - }, - - selectWidget(widget) { - this.designer.setSelected(widget) - }, - - selectParentWidget() { - if (this.parentWidget) { - this.designer.setSelected(this.parentWidget) - } else { - this.designer.clearSelected() - } - }, - - moveUpWidget() { - this.designer.moveUpWidget(this.parentList, this.indexOfParentList) - this.designer.emitHistoryChange() - }, +import {deepClone, generateId} from '@/utils/util'; - moveDownWidget() { - this.designer.moveDownWidget(this.parentList, this.indexOfParentList) - this.designer.emitHistoryChange() - }, - - cloneContainer(widget) { - if (!!this.parentList) { - let newCon = this.designer.cloneContainer(widget) - this.parentList.splice(this.indexOfParentList + 1, 0, newCon) - this.designer.setSelected(newCon) - - this.designer.emitHistoryChange() - } - }, - - removeWidget() { - if (!!this.parentList) { - let nextSelected = null - if (this.parentList.length === 1) { - if (!!this.parentWidget) { - nextSelected = this.parentWidget - } - } else if (this.parentList.length === (1 + this.indexOfParentList)) { - nextSelected = this.parentList[this.indexOfParentList - 1] - } else { - nextSelected = this.parentList[this.indexOfParentList + 1] - } - - this.$nextTick(() => { - this.parentList.splice(this.indexOfParentList, 1) - //if (!!nextSelected) { - this.designer.setSelected(nextSelected) - //} - - this.designer.emitHistoryChange() - }) - } - }, - - setWidgetOption(optionName, optionValue) { //通用组件选项修改API - if (this.widget.options.hasOwnProperty(optionName)) { - this.widget.options[optionName] = optionValue - } - }, - - } -} +export default { + methods: { + appendTableRow(widget) { + this.designer.appendTableRow(widget); + }, + setHidden(flag) { + console.log('>>>>>>2', flag); + }, + appendTableCol(widget) { + this.designer.appendTableCol(widget); + }, + + onContainerDragAdd(evt, subList) { + const newIndex = evt.newIndex; + if (subList[newIndex]) { + this.designer.setSelected(subList[newIndex]); + } + + this.designer.emitHistoryChange(); + this.designer.emitEvent('field-selected', this.widget); + }, + + onContainerDragUpdate() { + this.designer.emitHistoryChange(); + }, + + checkContainerMove(evt) { + return this.designer.checkWidgetMove(evt); + }, + + selectWidget(widget) { + this.designer.setSelected(widget); + }, + + selectParentWidget() { + if (this.parentWidget) { + this.designer.setSelected(this.parentWidget); + } else { + this.designer.clearSelected(); + } + }, + + moveUpWidget() { + this.designer.moveUpWidget(this.parentList, this.indexOfParentList); + this.designer.emitHistoryChange(); + }, + + moveDownWidget() { + this.designer.moveDownWidget(this.parentList, this.indexOfParentList); + this.designer.emitHistoryChange(); + }, + + cloneComponent(widget) { + console.log('cloneComponent:', widget); + let newFieldSchema = deepClone(widget); + newFieldSchema.id = widget.type.replace(/-/g, '') + generateId(); + newFieldSchema.options.name = newFieldSchema.id; + console.log(this,this.parentList); + if (this.parentList) { + this.parentList.splice(this.indexOfParentList + 1, 0, newFieldSchema); + }else if(this.designer.selectedParentList){ + this.designer.selectedParentList.splice(this.indexOfParentList + 1, 0, newFieldSchema); + } + }, + + cloneContainer(widget) { + console.log('containerMixin.js-cloneContainer:', widget, this.parentList); + let newCon = this.designer.cloneContainer(widget); + if (this.parentList) { + this.parentList.splice(this.indexOfParentList + 1, 0, newCon); + this.designer.setSelected(newCon); + this.designer.emitHistoryChange(); + } + }, + // 滑动至部件位置 + slideToSpecifyWidget(widgetId) { + let elementById = document.getElementById(`popover-designState-${widgetId}`); + if (elementById) { + elementById.scrollIntoView({ + //滚动到指定节点 + block: 'center', //值有start,center,end,nearest,当前显示在视图区域中间 + behavior: 'smooth', //值有auto、instant,smooth,缓动动画(当前是慢速的) + }); + elementById.classList.add('move-popover'); + setTimeout(() => { + elementById.classList.remove('move-popover'); + }, 4000); + }else{ + this.$message.warning(`未找到组件id:${widgetId}`); + } + }, + removeWidget() { + if (this.parentList) { + let nextSelected = null; + if (this.parentList.length === 1) { + if (this.parentWidget) { + nextSelected = this.parentWidget; + } + } else if (this.parentList.length === (1 + this.indexOfParentList)) { + nextSelected = this.parentList[this.indexOfParentList - 1]; + } else { + nextSelected = this.parentList[this.indexOfParentList + 1]; + } + + this.$nextTick(() => { + this.parentList.splice(this.indexOfParentList, 1); + //if (!!nextSelected) { + this.designer.setSelected(nextSelected); + //} + + this.designer.emitHistoryChange(); + }); + } + }, + + setWidgetOption(optionName, optionValue) { //通用组件选项修改API + if (this.widget.options.hasOwnProperty(optionName)) { + this.widget.options[optionName] = optionValue; + } + }, + + } +}; diff --git a/src/components/form-designer/form-widget/container-widget/grid-col-widget.vue b/src/components/form-designer/form-widget/container-widget/grid-col-widget.vue index 37d7fadd17563b16b5e3f9975c20269caab251ca..bf67426665fa051201c43c4a17c398616d48ac21 100644 --- a/src/components/form-designer/form-widget/container-widget/grid-col-widget.vue +++ b/src/components/form-designer/form-widget/container-widget/grid-col-widget.vue @@ -1,314 +1,324 @@ diff --git a/src/components/form-designer/form-widget/container-widget/grid-widget.vue b/src/components/form-designer/form-widget/container-widget/grid-widget.vue index f75f91e81067a631b5ff98c2b0813ff3f08b863f..d506d24495a4474adb1374878bc80b624b55792e 100644 --- a/src/components/form-designer/form-widget/container-widget/grid-widget.vue +++ b/src/components/form-designer/form-widget/container-widget/grid-widget.vue @@ -9,85 +9,105 @@ --> diff --git a/src/components/form-designer/form-widget/container-widget/index.js b/src/components/form-designer/form-widget/container-widget/index.js index 79f6d00ab310199448597b23c3c405df5ab5315e..0485dd0bcfa85a87609155cc5d8f07900716f8ec 100644 --- a/src/components/form-designer/form-widget/container-widget/index.js +++ b/src/components/form-designer/form-widget/container-widget/index.js @@ -1,6 +1,6 @@ -import Vue from 'vue' +import Vue from 'vue'; -const requireComponent = require.context('./', false, /\w+\.vue$/) +const requireComponent = require.context('./', false, /\w+\.vue$/); /** * 容器组件时递归组件,且内部可以嵌套其他容器,局部注册会找不到组件,必须注册为全局组件,原因不明?! @@ -19,6 +19,6 @@ end */ /* 全局注册!! */ requireComponent.keys().map(fileName => { - let comp = requireComponent(fileName).default; - Vue.component(comp.name, comp) -}) + let comp = requireComponent(fileName).default; + Vue.component(comp.name, comp); +}); diff --git a/src/components/form-designer/form-widget/container-widget/popover-widget.vue b/src/components/form-designer/form-widget/container-widget/popover-widget.vue new file mode 100644 index 0000000000000000000000000000000000000000..6d2c244a065ae668c74c41d0970c60736ee5abed --- /dev/null +++ b/src/components/form-designer/form-widget/container-widget/popover-widget.vue @@ -0,0 +1,83 @@ + + + + + diff --git a/src/components/form-designer/form-widget/container-widget/tab-widget.vue b/src/components/form-designer/form-widget/container-widget/tab-widget.vue index e966aff1e5e5d9176609e83fb67b177765990b3d..5992beb0dd9fa51d5c52caac7dac0f03652ddd78 100644 --- a/src/components/form-designer/form-widget/container-widget/tab-widget.vue +++ b/src/components/form-designer/form-widget/container-widget/tab-widget.vue @@ -44,67 +44,67 @@ diff --git a/src/components/form-designer/form-widget/field-widget/button-widget.vue b/src/components/form-designer/form-widget/field-widget/button-widget.vue index 758117f410595b3a9b55789edcebaf135b6289d3..5847caf03d6293c9ce4efd7c6cdda055b0c5c4a4 100644 --- a/src/components/form-designer/form-widget/field-widget/button-widget.vue +++ b/src/components/form-designer/form-widget/field-widget/button-widget.vue @@ -1,87 +1,98 @@ diff --git a/src/components/form-designer/form-widget/field-widget/cascader-widget.vue b/src/components/form-designer/form-widget/field-widget/cascader-widget.vue index 5fa2a0ba915de7abed92977702314b283fa2922d..b173960f302a98e6aae10ed21b5044ed263c9090 100644 --- a/src/components/form-designer/form-widget/field-widget/cascader-widget.vue +++ b/src/components/form-designer/form-widget/field-widget/cascader-widget.vue @@ -1,120 +1,128 @@ diff --git a/src/components/form-designer/form-widget/field-widget/checkbox-widget.vue b/src/components/form-designer/form-widget/field-widget/checkbox-widget.vue index b7e21b5b2f887e9ac390fb18cea4c86240d814ec..ef03efc4924868027022170f149a142be569f710 100644 --- a/src/components/form-designer/form-widget/field-widget/checkbox-widget.vue +++ b/src/components/form-designer/form-widget/field-widget/checkbox-widget.vue @@ -1,105 +1,129 @@ diff --git a/src/components/form-designer/form-widget/field-widget/color-widget.vue b/src/components/form-designer/form-widget/field-widget/color-widget.vue index b02789c8bf46645c45759aa2b12aa6e3e6f000e4..bb12266df130223aa188807be1489ca6a02887a1 100644 --- a/src/components/form-designer/form-widget/field-widget/color-widget.vue +++ b/src/components/form-designer/form-widget/field-widget/color-widget.vue @@ -11,82 +11,82 @@ diff --git a/src/components/form-designer/form-widget/field-widget/date-widget.vue b/src/components/form-designer/form-widget/field-widget/date-widget.vue index 5fd071b85d4c7b53e0170b646a62c3c979eb4dec..0e3b26b9e84e199af56dabae121c2b5cf102a9c6 100644 --- a/src/components/form-designer/form-widget/field-widget/date-widget.vue +++ b/src/components/form-designer/form-widget/field-widget/date-widget.vue @@ -1,103 +1,118 @@ diff --git a/src/components/form-designer/form-widget/field-widget/divider-widget.vue b/src/components/form-designer/form-widget/field-widget/divider-widget.vue index a09117a2c2e9a9a3b61b242fa2472d8d715a3d0e..be70c69548bd4961f2ae427e2ac86025a1577afb 100644 --- a/src/components/form-designer/form-widget/field-widget/divider-widget.vue +++ b/src/components/form-designer/form-widget/field-widget/divider-widget.vue @@ -8,73 +8,73 @@ diff --git a/src/components/form-designer/form-widget/field-widget/html-text-widget.vue b/src/components/form-designer/form-widget/field-widget/html-text-widget.vue index 6046b6546f0399be9688e991c4baab7c467226dc..d6fddd733e91fb881d43b7af4663bedcfaf993af 100644 --- a/src/components/form-designer/form-widget/field-widget/html-text-widget.vue +++ b/src/components/form-designer/form-widget/field-widget/html-text-widget.vue @@ -7,73 +7,73 @@ diff --git a/src/components/form-designer/form-widget/field-widget/number-widget.vue b/src/components/form-designer/form-widget/field-widget/number-widget.vue index a68519213b0f01c102b5a77b83dd1b921a6fb03d..baca41f58211bed623045aadc993948e67df0553 100644 --- a/src/components/form-designer/form-widget/field-widget/number-widget.vue +++ b/src/components/form-designer/form-widget/field-widget/number-widget.vue @@ -1,103 +1,112 @@ diff --git a/src/components/form-designer/form-widget/field-widget/picture-upload-widget.vue b/src/components/form-designer/form-widget/field-widget/picture-upload-widget.vue index 9705220f0455103cb08831969d5a4580d96a860e..a7d97b52024e9c19e30ad749fc01eeb85b55d56c 100644 --- a/src/components/form-designer/form-widget/field-widget/picture-upload-widget.vue +++ b/src/components/form-designer/form-widget/field-widget/picture-upload-widget.vue @@ -26,224 +26,224 @@ diff --git a/src/components/form-designer/form-widget/field-widget/slider-widget.vue b/src/components/form-designer/form-widget/field-widget/slider-widget.vue index ecbe13c36b3e86be3616f30ddc7df8133ad014be..673b02703a4acc4994ee429dc9c22bb548f20619 100644 --- a/src/components/form-designer/form-widget/field-widget/slider-widget.vue +++ b/src/components/form-designer/form-widget/field-widget/slider-widget.vue @@ -12,82 +12,82 @@ diff --git a/src/components/form-designer/form-widget/field-widget/static-text-widget.vue b/src/components/form-designer/form-widget/field-widget/static-text-widget.vue index 6962bb7d7537896ba5a934c1b56e3796a1791fbd..53f0ba5e7abb9fa712f39b8e0d5ab84ff315b274 100644 --- a/src/components/form-designer/form-widget/field-widget/static-text-widget.vue +++ b/src/components/form-designer/form-widget/field-widget/static-text-widget.vue @@ -1,83 +1,90 @@ diff --git a/src/components/form-designer/form-widget/field-widget/switch-widget.vue b/src/components/form-designer/form-widget/field-widget/switch-widget.vue index 5b433d54a748ad94140e877e128392d4fb2cf8f4..c7873177bec86cb6bb421cd1b4d277b4acf899cb 100644 --- a/src/components/form-designer/form-widget/field-widget/switch-widget.vue +++ b/src/components/form-designer/form-widget/field-widget/switch-widget.vue @@ -13,82 +13,82 @@ diff --git a/src/components/form-designer/form-widget/field-widget/time-range-widget.vue b/src/components/form-designer/form-widget/field-widget/time-range-widget.vue index 8a83704bb16ad40881046e2adc1a79bc2c0e4a5e..774143f553620c9679e3cc0df69926b056ee06ff 100644 --- a/src/components/form-designer/form-widget/field-widget/time-range-widget.vue +++ b/src/components/form-designer/form-widget/field-widget/time-range-widget.vue @@ -2,103 +2,105 @@ - diff --git a/src/components/form-designer/form-widget/field-widget/time-widget.vue b/src/components/form-designer/form-widget/field-widget/time-widget.vue index b4f15aad380c5f77dee8141ba7dcf2a3adba8ef6..889607a9be4f1086091891e69eb38639e0ebfc43 100644 --- a/src/components/form-designer/form-widget/field-widget/time-widget.vue +++ b/src/components/form-designer/form-widget/field-widget/time-widget.vue @@ -1,103 +1,109 @@ diff --git a/src/components/form-designer/form-widget/functionalUnit.vue b/src/components/form-designer/form-widget/functionalUnit.vue new file mode 100644 index 0000000000000000000000000000000000000000..f51f9bd595b2b79dd2a70b2f1355ea254263041f --- /dev/null +++ b/src/components/form-designer/form-widget/functionalUnit.vue @@ -0,0 +1,441 @@ + + + + + + + diff --git a/src/components/form-designer/form-widget/index.vue b/src/components/form-designer/form-widget/index.vue index 6358dcf31a9c3e9468d046b1f8abacd2d32b1471..d796d5c4d6a4507e96dea257a0dfc9e7ff94a2c2 100644 --- a/src/components/form-designer/form-widget/index.vue +++ b/src/components/form-designer/form-widget/index.vue @@ -6,174 +6,187 @@
{{i18nt('designer.noWidgetHint')}}
- + - - + diff --git a/src/components/form-designer/refMixinDesign.js b/src/components/form-designer/refMixinDesign.js index 0b027f112a237247842b87e8e6396e78cbf4d1fe..137996e879ef30e9317f8274653e1cc38534a020 100644 --- a/src/components/form-designer/refMixinDesign.js +++ b/src/components/form-designer/refMixinDesign.js @@ -1,28 +1,28 @@ export default { - methods: { - initRefList() { - if ((this.refList !== null) && !!this.widget.options.name) { - this.refList[this.widget.options.name] = this - } - }, + methods: { + initRefList() { + if ((this.refList !== null) && !!this.widget.options.name) { + this.refList[this.widget.options.name] = this; + } + }, - getWidgetRef(widgetName, showError = false) { - let foundRef = this.refList[widgetName] - if (!foundRef && !!showError) { - this.$message.error(this.i18nt('render.hint.refNotFound') + widgetName) - } - return foundRef - }, + getWidgetRef(widgetName, showError = false) { + let foundRef = this.refList[widgetName]; + if (!foundRef && !!showError) { + this.$message.error(this.i18nt('render.hint.refNotFound') + widgetName); + } + return foundRef; + }, - /* 该方法用于组件重名检查!! */ - registerToRefList(oldRefName) { - if ((this.refList !== null) && !!this.widget.options.name) { - if (!!oldRefName) { - delete this.refList[oldRefName] - } - this.refList[this.widget.options.name] = this - } - }, + /* 该方法用于组件重名检查!! */ + registerToRefList(oldRefName) { + if ((this.refList !== null) && !!this.widget.options.name) { + if (oldRefName) { + delete this.refList[oldRefName]; + } + this.refList[this.widget.options.name] = this; + } + }, - } -} + } +}; diff --git a/src/components/form-designer/setting-panel/form-setting.vue b/src/components/form-designer/setting-panel/form-setting.vue index 029964ee52c3aea5896d5f37b64dde1a55099520..791015a0ecc7077d626840de5f3eb69dc344acbf 100644 --- a/src/components/form-designer/setting-panel/form-setting.vue +++ b/src/components/form-designer/setting-panel/form-setting.vue @@ -24,9 +24,23 @@ {{i18nt('designer.setting.rightAlign')}} + + + + + + {{i18nt('designer.setting.labelOverflowNowrap')}} + + {{i18nt('designer.setting.labelOverflowHidden')}} + + {{i18nt('designer.setting.labelOverflowLineFeed')}} + + + + {{i18nt('designer.setting.addCss')}} @@ -69,20 +83,27 @@ {{i18nt('designer.setting.addEventHandler')}} - - + - + @@ -95,7 +116,7 @@