diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d5d024e --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 SNFocus + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 841c8ba..4695d02 100644 --- a/README.md +++ b/README.md @@ -56,3 +56,6 @@ ## 郑重感谢 非常感谢JakHuang的[form-generator](https://github.com/JakHuang/form-generator)为我解决了很多问题,也从中学习到了很多。再者就是我fork`form-generator`版本和JakHuang现在的版本也有很大的区别,感兴趣的童鞋可以去JakHuang那儿看看。 + + + diff --git a/lanch.bat b/lanch.bat deleted file mode 100644 index 543eafc..0000000 --- a/lanch.bat +++ /dev/null @@ -1 +0,0 @@ -npm run serve diff --git a/package-lock.json b/package-lock.json index b69c0ae..1afd5a6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2554,7 +2554,7 @@ "integrity": "sha1-d5+wAYYE+oVOrL9iUhgNg1Q+Pb4=", "dev": true, "requires": { - "minimist": "^1.2.3" + "minimist": "^1.2.0" } }, "loader-utils": { @@ -4624,9 +4624,9 @@ } }, "elliptic": { - "version": "6.5.2", - "resolved": "https://registry.npm.taobao.org/elliptic/download/elliptic-6.5.2.tgz?cache=0&sync_timestamp=1574449776597&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Felliptic%2Fdownload%2Felliptic-6.5.2.tgz", - "integrity": "sha1-BcVnjXFzwEnYykM1UiJKSV0ON2I=", + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", + "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", "dev": true, "requires": { "bn.js": "^4.4.0", @@ -5735,12 +5735,12 @@ "requires": { "deep-extend": "^0.6.0", "ini": "~1.3.0", - "minimist": "^1.2.3", + "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, "dependencies": { "minimist": { - "version": "1.2.3", + "version": "1.2.0", "bundled": true, "dev": true, "optional": true @@ -6363,9 +6363,9 @@ "dev": true }, "http-proxy": { - "version": "1.18.0", - "resolved": "https://registry.npm.taobao.org/http-proxy/download/http-proxy-1.18.0.tgz", - "integrity": "sha1-2+VfY+daNH2389mZdPJpKjFKajo=", + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", "dev": true, "requires": { "eventemitter3": "^4.0.0", @@ -7130,9 +7130,9 @@ } }, "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npm.taobao.org/lodash/download/lodash-4.17.15.tgz?cache=0&sync_timestamp=1577793955950&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flodash%2Fdownload%2Flodash-4.17.15.tgz", - "integrity": "sha1-tEf2ZwoEVbv+7dETku/zMOoJdUg=", + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", "dev": true }, "lodash.clonedeep": { diff --git a/src/views/admin/mockData.js b/public/mockConf.json similarity index 92% rename from src/views/admin/mockData.js rename to public/mockConf.json index 6aab544..ee3a2b8 100644 --- a/src/views/admin/mockData.js +++ b/public/mockConf.json @@ -1,4 +1,4 @@ -export default { +{ "basicSetting": { "flowName": "入职", "flowImg": 12, @@ -260,6 +260,51 @@ export default { }, "formData": { "fields": [ + { + "cmpType": "common", + "label": "组织机构", + "tag": "fc-org-select", + "tagIcon": "dept", + "defaultValue": { + "dep": [ + { + "nodeId": 1, + "deptId": 1, + "deptName": "xxxs公司" + } + ] + }, + "tabList": [ + "dep" + ], + "buttonType": "button", + "title": "组织机构", + "searchable": true, + "maxNum": 1, + "tagConfig": { + "type": "info", + "closable": true, + "disable-transitions": false, + "hit": false, + "size": "small", + "effect": "light" + }, + "style": { + "width": "100%" + }, + "span": 24, + "labelWidth": null, + "disabled": false, + "required": true, + "regList": [], + "changeTag": true, + "proCondition": true, + "asSummary": false, + "layout": "colFormItem", + "formId": 20, + "renderKey": 1590641662215, + "vModel": "field20" + }, { "cmpType": "common", "label": "姓名", @@ -427,7 +472,7 @@ export default { "show-word-limit": false, "readonly": false, "disabled": false, - "required": false, + "required": true, "regList": [], "changeTag": true, "proCondition": false, @@ -518,11 +563,9 @@ export default { } ], "formRef": "elForm", - "formModel": "formData", "size": "small", "labelPosition": "right", "labelWidth": 100, - "formRules": "rules", "gutter": 15, "disabled": false, "span": 12, diff --git a/public/pay.png b/public/pay.png new file mode 100644 index 0000000..3918a72 Binary files /dev/null and b/public/pay.png differ diff --git a/src/api/index.js b/src/api/index.js index 4d32700..a5a9f64 100644 --- a/src/api/index.js +++ b/src/api/index.js @@ -11,3 +11,6 @@ export const GET_DEPT_TREE = data => get( BASE_URL + 'depChild.json', data ) // 获取组织机构下人员信息 export const GET_USER_BY_DEPT = data => get( BASE_URL + 'userData.json', data ) + +// 获取Mock数据 +export const GET_MOCK_CONF = () => get(BASE_URL + 'mockConf.json') diff --git a/src/assets/logo.png b/src/assets/logo.png deleted file mode 100644 index f23b758..0000000 Binary files a/src/assets/logo.png and /dev/null differ diff --git a/src/components/DynamicForm/RightPanel.vue b/src/components/DynamicForm/RightPanel.vue index 85013d9..2037737 100644 --- a/src/components/DynamicForm/RightPanel.vue +++ b/src/components/DynamicForm/RightPanel.vue @@ -102,7 +102,7 @@ - + - 中等 @@ -746,7 +740,7 @@ import { } from "./components/generator/config"; import { saveFormConf } from "./utils/db"; import draggable from "vuedraggable"; -import {mergeNumberOfExps, validExp, toRPN, calcRPN} from '@/assets/utils/index.js' +import {mergeNumberOfExps, validExp, toRPN, calcRPN} from '@/utils/index.js' const dateTimeFormat = { date: "yyyy-MM-dd", week: "yyyy 第 WW 周", @@ -947,6 +941,9 @@ export default { } }, methods: { + notObject(val) { + return val === null || val === undefined || Object(val) !== val + }, reloadExpressionTemp(){ const isValid = d => { const target = this.calculateCmps.find(cmp => cmp.vModel === d.vModel && cmp.label === d.label) diff --git a/src/components/DynamicForm/components/generator/config.js b/src/components/DynamicForm/components/generator/config.js index 158e726..e4731c7 100644 --- a/src/components/DynamicForm/components/generator/config.js +++ b/src/components/DynamicForm/components/generator/config.js @@ -2,11 +2,9 @@ import PROVINCE from './province.js' export const formConf = { formRef: 'elForm', - formModel: 'formData', size: 'small', labelPosition: 'right', labelWidth: 100, - formRules: 'rules', gutter: 15, disabled: false, span: 24, @@ -92,6 +90,7 @@ export const inputComponents = [{ tagIcon: 'number', placeholder: '', defaultValue: undefined, + style: { width: null }, span: 24, labelWidth: null, min: undefined, @@ -112,6 +111,7 @@ export const inputComponents = [{ tagIcon: 'amount', placeholder: '请输入', defaultValue: undefined, + style: { width: null }, span: 24, labelWidth: null, min: undefined, @@ -134,10 +134,10 @@ export const selectComponents = [{ tag: 'el-select', tagIcon: 'select', placeholder: '请选择', + style: { width: '100%' }, defaultValue: undefined, span: 24, labelWidth: null, - style: { width: '100%' }, clearable: true, disabled: false, required: false, @@ -535,7 +535,8 @@ export const layoutComponents = [{ children: [], actionText: '添加', tableConf: {}, - 'show-summary': true + 'show-summary': true, + defaultValue: [] }] export const commonComponents = [...inputComponents, ...selectComponents, ...layoutComponents] @@ -700,5 +701,5 @@ export const trigger = { 'fc-amount': 'change', 'fc-time-duration': 'change', 'fc-date-duration': 'change', - 'fc-org-select': 'change' + 'fc-org-select': 'input' } \ No newline at end of file diff --git a/src/components/DynamicForm/components/generator/html.js b/src/components/DynamicForm/components/generator/html.js index ee7c601..7aabe8e 100644 --- a/src/components/DynamicForm/components/generator/html.js +++ b/src/components/DynamicForm/components/generator/html.js @@ -51,7 +51,7 @@ function buildFormTemplate ( conf, child, type ) { labelPosition = `label-position="${conf.labelPosition}"` } const disabled = conf.disabled ? `:disabled="${conf.disabled}"` : '' - let str = ` + let str = ` ${child} ${buildFromBtns( conf, type )} ` @@ -177,7 +177,7 @@ const tags = { return `<${el.tag} ${vModel} ${type} ${placeholder} ${maxlength} ${showWordLimit} ${readonly} ${disabled} ${clearable} ${prefixIcon} ${suffixIcon} ${showPassword} ${autosize} ${width}>${child}` }, 'el-input-number': el => { - const { disabled, vModel, placeholder } = attrBuilder( el ) + const { disabled, vModel, placeholder, width } = attrBuilder( el ) const controlsPosition = el['controls-position'] ? `controls-position=${el['controls-position']}` : '' const min = el.min ? `:min='${el.min}'` : '' const max = el.max ? `:max='${el.max}'` : '' @@ -185,7 +185,7 @@ const tags = { const stepStrictly = el['step-strictly'] ? 'step-strictly' : '' const precision = el.precision ? `:precision='${el.precision}'` : '' - return `<${el.tag} ${vModel} ${placeholder} ${step} ${stepStrictly} ${precision} ${controlsPosition} ${min} ${max} ${disabled}>` + return `<${el.tag} ${vModel} ${placeholder} ${step} ${stepStrictly} ${precision} ${controlsPosition} ${min} ${max} ${width} ${disabled}>` }, 'fc-org-select': function ( el ) { const { disabled, vModel, placeholder, width } = attrBuilder( el ) @@ -205,7 +205,7 @@ const tags = { 'fc-calculate': function ( el ) { const { vModel } = attrBuilder( el ) const showChinese = el.showChinese ? `:showChinese='${el.showChinese}'` : '' - const formData = `:formData="${confGlobal.formModel}"` + const formData = `:formData="formData"` const expression = `:expression="${el.vModel}Exps" ` return createTagHTML( el.tag, vModel, showChinese, formData, expression ) }, @@ -347,13 +347,14 @@ const tags = { labelWidth = `label-width="${el.labelWidth || confGlobal.labelWidth}px"` formSize = `form-size="${confGlobal.size}"` } - return `<${el.tag} ref="${el.vModel}" ${formSize} ${labelWidth} :config="tableRefs['${el.vModel}']" :value.sync="${confGlobal.formModel}.${el.vModel}">` + const formData = `:formData="formData"` + return `<${el.tag} ${formData} ref="${el.vModel}" ${formSize} ${labelWidth} :config="tableRefs['${el.vModel}']" v-model="formData.${el.vModel}">` } } function attrBuilder ( el ) { return { - vModel: `v-model="${confGlobal.formModel}.${el.vModel}"`, + vModel: `v-model="formData.${el.vModel}"`, clearable: el.clearable ? 'clearable' : '', placeholder: el.placeholder ? `placeholder="${el.placeholder}"` : '', width: el.style && el.style.width ? `:style="{width: '${el.style.width}'}"` : '', diff --git a/src/components/DynamicForm/components/generator/js.js b/src/components/DynamicForm/components/generator/js.js index c9b6389..9044c14 100644 --- a/src/components/DynamicForm/components/generator/js.js +++ b/src/components/DynamicForm/components/generator/js.js @@ -53,7 +53,7 @@ export function makeUpJs ( conf, type ) { function buildWatchInHook ( key, callbackStr, watchFuncList ) { watchFuncList.push( `this.$watch(function () { - return this.${confGlobal.formModel}.${key} + return this.formData.${key} }, ${callbackStr})` ) } /** @@ -137,7 +137,7 @@ function mixinMethod ( type ) { message: '请在控制台中查看数据输出', position: 'bottom-right' }); - console.log('表单数据', this.${confGlobal.formModel}) + console.log('表单数据', this.formData) // TODO 提交表单 }) },`, @@ -155,7 +155,7 @@ function mixinMethod ( type ) { let valid = true Object.keys(this.tableRefs).forEach(vModel => { const res = this.$refs[vModel].submit() // 返回false或表单数据 - res ? (this.${confGlobal.formModel}[vModel] = res) : (valid = false) + res ? (this.formData[vModel] = res) : (valid = false) }) return valid },`, @@ -305,10 +305,10 @@ function buildexport ( conf, type, data, rules, selectOptions, uploadVar, props, drawerVisible: false, drawerTitle: '', drawerText: '', - ${conf.formModel}: { + formData: { ${data} }, - ${conf.formRules}: { + ruleList: { ${rules} }, ${uploadVar} @@ -319,7 +319,7 @@ function buildexport ( conf, type, data, rules, selectOptions, uploadVar, props, computed: { // 为了验证时能获取到表单数据 vmFormData(){ - return this.${conf.formModel} + return this.formData } }, watch: {}, diff --git a/src/components/DynamicForm/index.vue b/src/components/DynamicForm/index.vue index be022db..a6976a0 100644 --- a/src/components/DynamicForm/index.vue +++ b/src/components/DynamicForm/index.vue @@ -141,7 +141,7 @@ >预览 清空 -
+
@@ -181,7 +181,8 @@
-
+
+
@@ -252,7 +253,7 @@ import { // saveIdGlobal, getFormConf } from "./utils/db"; -import { debounce } from '@/assets/utils' +import { debounce } from '@/utils' const emptyActiveData = { style: {}, autosize: {} }; let oldActiveId; @@ -296,17 +297,7 @@ export default { }, watch: { // eslint-disable-next-line func-names - "activeData.label": function(val, oldVal) { - if ( - this.activeData.placeholder === undefined || - !this.activeData.tag || - oldActiveId !== this.activeId - ) { - return; - } - this.activeData.placeholder = - this.activeData.placeholder.replace(oldVal, "") + val; - }, + activeId: { handler(val) { oldActiveId = val; @@ -342,6 +333,7 @@ export default { formConfInDB && (this.formConf = formConfInDB) } this.activeFormItem(this.drawingList[0]) + this.$nextTick(_ => this.getIpadMode()) // const clipboard = new ClipboardJS('#copyNode', { // text: trigger => { @@ -359,6 +351,10 @@ export default { // }) }, methods: { + getIpadMode () { + const {clientHeight, clientWidth} = this.$refs.ipad + this.ipadMode = clientWidth * 0.74> clientHeight ? 'landscape' : 'portrait' + }, handlerListChange(val){ const vm = this this.$store.commit('clearPCondition') // 清除所有条件 重新检测赋值 @@ -448,20 +444,26 @@ export default { this.drawingList.push(clone); this.activeFormItem(clone); }, - getMaxId(){ + getMaxId () { if(this.drawingList.length){ - return this.drawingList.reduce((maxId, cmp) => { - cmp.formId> maxId && (maxId = cmp.formId ) - if(Array.isArray(cmp.children)){ - maxId = cmp.children.reduce((max, child) => Math.max(max, child.formId), maxId) + let maxId = 0 + const loop = (data, parent) => { + if(!data) return + Array.isArray(data.children) && data.children.forEach(child => loop(child, data)) + if(Array.isArray(data)) { + data.forEach(loop) + }else{ + maxId = Math.max(data.formId, maxId) } - return maxId - }, 0) + } + loop(this.drawingList) + return maxId } return 0 }, getNextId(){ - return this.getMaxId() + 1 + let maxId = this.getMaxId() + 1 + return maxId }, cloneComponent(origin) { const clone = JSON.parse(JSON.stringify(origin)); @@ -538,20 +540,25 @@ export default { }) }, preview(){ - this.AssembleFormData(); - let htmlCode = makeUpHtml(this.formData, "file"); - let jsCode = makeUpJs(this.formData, "file"); - let cssCode = makeUpCss(this.formData); - this.$router.push({ - name: "preview", - params: { - formData: { - htmlCode, - jsCode, - cssCode - } - } - }); + this.AssembleFormData(); + // 这是沿用form-generator 创建文本模板的方法 + + // let htmlCode = makeUpHtml(this.formData, "file"); + // let jsCode = makeUpJs(this.formData, "file"); + // let cssCode = makeUpCss(this.formData); + // this.$router.push({ + // name: "preview", + // params: { + // formData: { + // htmlCode, + // jsCode, + // cssCode + // } + // } + // }); + + // 这是使用jsx渲染 + this.$router.push({ name: "jsxPreview", params: { formData: this.formData } }); }, generate(data) { const func = this[`exec${titleCase(this.operationType)}`]; @@ -732,7 +739,7 @@ export default { &.portrait{ padding: 45px 25px; height: 85% !important; - width: 68%; + width: 74%; min-height: 560px; } diff --git a/src/components/DynamicForm/styles/home.styl b/src/components/DynamicForm/styles/home.styl index b7a4959..85408ca 100644 --- a/src/components/DynamicForm/styles/home.styl +++ b/src/components/DynamicForm/styles/home.styl @@ -192,6 +192,7 @@ $lighterBlue = #409EFF; } .el-form-item{ margin-bottom: 12px !important; + overflow: hidden; } } .drawing-item{ diff --git a/src/components/FormControls/Amount/index.vue b/src/components/FormControls/Amount/index.vue index 7138c37..573e345 100644 --- a/src/components/FormControls/Amount/index.vue +++ b/src/components/FormControls/Amount/index.vue @@ -1,19 +1,19 @@ diff --git a/src/views/custom/preview.vue b/src/views/custom/preview.vue index 8b1d72c..983082a 100644 --- a/src/views/custom/preview.vue +++ b/src/views/custom/preview.vue @@ -23,6 +23,28 @@ const loadVueOption = (jsCode, htmlCode, defaultData) => { main.template = `
${htmlCode}
` return main } + +/** + * 默认数据 预览已经填写过的表单时 + * 将以下数据合并到Vue实例中即可 + */ +const defData = { + // "field2": "22", + // "field3": "本科", + // "field4": "男", + // "field5": [ + // { + // "field6": [ + // "2020-07-01", + // "2020-08-03" + // ], + // "field7": "212", + // "field8": "后端", + // "field9": [] + // } + // ], + // "field10": 21, +} export default { data(){ return{ @@ -33,7 +55,7 @@ export default { // defaultData 可以将默认formData覆盖到data中 const { jsCode, htmlCode, cssCode } = this.$route.params.formData loadStyle(cssCode) - const OPTION = loadVueOption(jsCode, htmlCode, {}) + const OPTION = loadVueOption(jsCode, htmlCode, defData) const Form = Vue.extend(OPTION) new Form().$mount("#customForm") }, diff --git a/src/views/custom/test.vue b/src/views/custom/test.vue index bcd2bc0..821fe7d 100644 --- a/src/views/custom/test.vue +++ b/src/views/custom/test.vue @@ -1,22 +1,366 @@ + submitForm() { + const isTableValid = this.checkTableData(); + this.$refs["elForm"].validate((valid) => { + if (!valid) return; + if (!isTableValid) return; + this.$notify({ + title: "表单数据", + message: "请在控制台中查看数据输出", + position: "bottom-right", + }); + console.log("表单数据", this.formData); + // TODO 提交表单 + }); + }, + resetForm() { + this.$refs["elForm"].resetFields(); + this.resetTableData(); + }, + resetTableData() { + Object.keys(this.tableRefs).forEach((vModel) => { + const res = this.$refs[vModel].reset(); + }); + }, + checkTableData() { + let valid = true; + Object.keys(this.tableRefs).forEach((vModel) => { + const res = this.$refs[vModel].submit(); // 返回false或表单数据 + res ? (this.formData[vModel] = res) : (valid = false); + }); + return valid; + }, + showExplain(explainText, title) { + if (!explainText) return; + this.drawerTitle = title; + this.drawerText = explainText; + this.drawerVisible = true; + }, + field9BeforeUpload(file) { + let isRightSize = file.size / 1024 / 1024 < 20; + if (!isRightSize) { + this.$message.error("文件大小超过 20MB"); + } + return isRightSize; + }, + }, +}; + \ No newline at end of file

AltStyle によって変換されたページ (->オリジナル) /