├── .npmignore ├── .browserslistrc ├── demo.webp ├── public ├── favicon.ico └── index.html ├── babel.config.js ├── .prettierrc.json ├── .github ├── ISSUE_TEMPLATE │ ├── feature_request.md │ ├── bug_report.md │ └── question.md └── workflows │ └── main.yml ├── src ├── index.js ├── fixtures │ ├── extends │ │ ├── codemirror.js │ │ ├── json-editor.js │ │ ├── dynamic.js │ │ ├── bmap.js │ │ ├── gallery.js │ │ ├── video-uploader.js │ │ ├── quill-editor.js │ │ ├── upload-file.js │ │ ├── tree-select.js │ │ ├── image-uploader.js │ │ ├── data-editor.js │ │ ├── markdown-editor.js │ │ └── table-editor.js │ ├── form-item-common.js │ └── form-props.js ├── components │ ├── main │ │ ├── components │ │ │ ├── tpl │ │ │ │ ├── vue-ele-form.js │ │ │ │ └── f-render.js │ │ │ ├── preview-dialog.vue │ │ │ ├── code-dialog.vue │ │ │ ├── data-dialog.vue │ │ │ └── batch-dialog.vue │ │ ├── index.vue │ │ ├── main-header.vue │ │ └── main-content.vue │ ├── right │ │ ├── components │ │ │ ├── search-mixin.js │ │ │ ├── attrs-header.vue │ │ │ └── form-item-rules.vue │ │ ├── form-props.vue │ │ ├── form-item-attrs.vue │ │ ├── index.vue │ │ └── form-item-common.vue │ └── left │ │ └── index.vue ├── global-components.js ├── form-skeleton.vue ├── utils.js └── f-render.vue ├── .gitignore ├── .eslintrc.js ├── vue.config.js ├── example ├── App.vue ├── main.js └── AppHeader.vue ├── LICENSE ├── package.json ├── CHANGELOG.md └── README.md /.npmignore: -------------------------------------------------------------------------------- 1 | .github 2 | dist/demo.html 3 | -------------------------------------------------------------------------------- /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not ie <= 8 4 | not dead 5 | -------------------------------------------------------------------------------- /demo.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dream2023/f-render/HEAD/demo.webp -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dream2023/f-render/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ["@vue/cli-plugin-babel/preset"], 3 | plugins: ["lodash"] 4 | }; 5 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "none", 3 | "tabWidth": 2, 4 | "semi": true, 5 | "singleQuote": false 6 | } 7 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature Request(新功能建议) 3 | about: Suggest an idea for this project 4 | --- 5 | 6 | ## Feature request(新功能建议) 7 | 8 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import FRender from "./f-render"; 2 | 3 | if (window !== undefined && window.Vue) { 4 | window.Vue.component("f-render", FRender); 5 | } 6 | 7 | export default FRender; 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | const isProd = process.env.NODE_ENV === "production"; 2 | module.exports = { 3 | root: true, 4 | env: { 5 | node: true 6 | }, 7 | extends: ["plugin:vue/essential", "eslint:recommended", "@vue/prettier"], 8 | parserOptions: { 9 | parser: "babel-eslint" 10 | }, 11 | rules: { 12 | "no-unused-vars": isProd ? "error" : "warn", 13 | "vue/no-unused-components": isProd ? "error" : "warn", 14 | "no-console": isProd ? ["error", { allow: ["warn", "error"] }] : "off", 15 | "no-debugger": isProd ? "warn" : "off" 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /src/fixtures/extends/codemirror.js: -------------------------------------------------------------------------------- 1 | export default { 2 | type: "codemirror", 3 | label: "代码编辑器", 4 | config: { 5 | url: "https://github.com/dream2023/vue-ele-form-codemirror", 6 | attrs: { 7 | config: { 8 | options: { 9 | type: "data-editor", 10 | label: "配置", 11 | attrs: { 12 | types: ["object"], 13 | rows: 10 14 | } 15 | } 16 | } 17 | }, 18 | common: { 19 | config: { 20 | default: { 21 | type: "textarea", 22 | label: "默认值" 23 | } 24 | } 25 | } 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /src/components/main/components/tpl/vue-ele-form.js: -------------------------------------------------------------------------------- 1 | export default function(code) { 2 | return ` 10 | 11 | 30 | `; 31 | } 32 | -------------------------------------------------------------------------------- /src/components/main/components/tpl/f-render.js: -------------------------------------------------------------------------------- 1 | export default function(code) { 2 | return ` 11 | 12 | 31 | `; 32 | } 33 | -------------------------------------------------------------------------------- /src/components/right/components/search-mixin.js: -------------------------------------------------------------------------------- 1 | const fuzzy = require("fuzzy"); 2 | import { objectToArr, arrToObject } from "../../../utils"; 3 | 4 | export default { 5 | data() { 6 | return { 7 | keyword: "" 8 | }; 9 | }, 10 | computed: { 11 | filteredFormDesc() { 12 | if (this.keyword) { 13 | // 将 formDesc 转为数组 14 | const formDescArr = objectToArr(this.formDesc, "field"); 15 | const results = fuzzy 16 | .filter(this.keyword, formDescArr, { 17 | extract: item => item.label 18 | }) 19 | .map(el => el.original); 20 | return arrToObject(results, "field"); 21 | } else { 22 | return this.formDesc; 23 | } 24 | } 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | const LodashModuleReplacementPlugin = require("lodash-webpack-plugin"); 3 | const isProd = process.env.NODE_ENV === "production"; 4 | 5 | module.exports = { 6 | publicPath: isProd ? "./" : "/", 7 | transpileDependencies: [ 8 | "indent-string", 9 | "vue-ele-form-dynamic", 10 | "vue-ele-form/lib", 11 | "vuedraggable" 12 | ], 13 | configureWebpack: { 14 | devtool: "source-map", 15 | entry: path.resolve(__dirname, "./example/main.js"), 16 | resolve: { 17 | alias: { 18 | "f-render": path.resolve(__dirname, "./src/") 19 | } 20 | }, 21 | plugins: [new LodashModuleReplacementPlugin()] 22 | }, 23 | css: { 24 | extract: false 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> | 可视化表单设计器 9 | 10 | 11 | 18 |
19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/global-components.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 此文件用于注册全局组件 3 | */ 4 | 5 | import Vue from "vue"; 6 | 7 | // 滚动 8 | import PerfectScrollbar from "vue2-perfect-scrollbar"; 9 | import "vue2-perfect-scrollbar/dist/vue2-perfect-scrollbar.css"; 10 | 11 | // 扩展组件 12 | import EleFormDynamic from "vue-ele-form-dynamic"; 13 | import EleFormDataEditor from "vue-ele-form-data-editor"; 14 | 15 | // 拖拽 16 | import vueDraggable from "vuedraggable/src/vuedraggable"; 17 | 18 | // 代码编辑器 19 | import { PrismEditor } from "vue-prism-editor"; 20 | import "vue-prism-editor/dist/prismeditor.min.css"; 21 | import "prismjs/themes/prism-tomorrow.css"; 22 | 23 | Vue.use(PerfectScrollbar); 24 | Vue.component("dynamic", EleFormDynamic); 25 | Vue.component("PrismEditor", PrismEditor); 26 | Vue.component("vue-draggable", vueDraggable); 27 | Vue.component("data-editor", EleFormDataEditor); 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report(报告问题) 3 | about: Create a report to help us improve 4 | --- 5 | 6 | 11 | 12 | ## Bug report(问题描述) 13 | 14 | #### Steps to reproduce(问题复现步骤) 15 | 16 | 21 | 22 | #### Screenshot or Gif(截图或动态图) 23 | 24 | #### Link to minimal reproduction(最小可在线还原 demo) 25 | 26 | 29 | 30 | #### Other relevant information(格外信息) 31 | 32 | - Vue version: 33 | - f-render version: 34 | - ElementUI version: 35 | - vue-ele-form version: 36 | -------------------------------------------------------------------------------- /src/fixtures/extends/json-editor.js: -------------------------------------------------------------------------------- 1 | export default { 2 | type: "data-editor", 3 | label: "JSON编辑器", 4 | config: { 5 | url: "https://github.com/dream2023/vue-ele-form-upload-file", 6 | attrs: { 7 | config: { 8 | height: { 9 | type: "input", 10 | label: "高度" 11 | }, 12 | plus: { 13 | type: "switch", 14 | label: "是否显示全屏按钮" 15 | }, 16 | options: { 17 | type: "data-editor", 18 | label: "配置", 19 | attrs: { 20 | types: ["object"] 21 | } 22 | } 23 | }, 24 | data: {} 25 | }, 26 | common: { 27 | config: { 28 | default: { 29 | type: "data-editor", 30 | label: "默认值", 31 | attrs: { 32 | types: ["object", "array"] 33 | } 34 | } 35 | } 36 | } 37 | } 38 | }; 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question(提问) 3 | about: Asking questions about use 4 | --- 5 | 6 | ## Question(提问) 7 | 8 | 15 | 16 | #### Steps to reproduce(问题复现步骤) 17 | 18 | 23 | 24 | #### Screenshot or Gif(截图或动态图) 25 | 26 | #### Link to minimal reproduction(最小可在线还原 demo) 27 | 28 | 31 | 32 | #### Other relevant information(格外信息) 33 | 34 | - Vue version: 35 | - f-render version: 36 | - ElementUI version: 37 | - vue-ele-form version: 38 | -------------------------------------------------------------------------------- /src/components/right/form-props.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 35 | -------------------------------------------------------------------------------- /src/components/main/index.vue: -------------------------------------------------------------------------------- 1 | 40 | -------------------------------------------------------------------------------- /example/App.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 49 | -------------------------------------------------------------------------------- /src/components/right/components/attrs-header.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 34 | 35 | 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 二当家的 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE.m -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: gitub pages 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | build-deploy: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@master 14 | 15 | - name: install 16 | run: yarn 17 | 18 | - name: build 19 | run: yarn build 20 | 21 | - name: deploy 22 | uses: peaceiris/actions-gh-pages@v2.5.0 23 | env: 24 | ACTIONS_DEPLOY_KEY: ${{ secrets.ACTIONS_DEPLOY_KEY }} 25 | PUBLISH_BRANCH: gh-pages 26 | PUBLISH_DIR: ./dist 27 | 28 | - name: Sync to Gitee 29 | uses: wearerequired/git-mirror-action@master 30 | env: 31 | SSH_PRIVATE_KEY: ${{ secrets.GITEE_RSA_PRIVATE_KEY }} 32 | with: 33 | source-repo: "git@github.com:dream2023/f-render.git" 34 | destination-repo: "git@gitee.com:dream2023/f-render.git" 35 | 36 | - name: Build Gitee Pages 37 | uses: yanglbme/gitee-pages-action@master 38 | with: 39 | gitee-username: dream2023 40 | gitee-password: ${{ secrets.GITEE_PASSWORD }} 41 | gitee-repo: dream2023/f-render 42 | -------------------------------------------------------------------------------- /src/fixtures/extends/dynamic.js: -------------------------------------------------------------------------------- 1 | export default { 2 | type: "dynamic", 3 | label: "动态组件", 4 | config: { 5 | url: "https://github.com/dream2023/vue-ele-form-dynamic", 6 | attrs: { 7 | config: { 8 | columns: { 9 | type: "data-editor", 10 | label: "列", 11 | required: true, 12 | tip: "可以是数组或者对象", 13 | attrs: { 14 | types: ["array", "object"] 15 | } 16 | }, 17 | rules: { 18 | type: "data-editor", 19 | label: "校检规则", 20 | tip: 21 | "当columns为数组时, 则rules必须为对象类型, 指定校检字段, 当columns为对象时, 则rules为数组类型", 22 | attrs: { 23 | types: ["array", "object"], 24 | rows: 10 25 | } 26 | }, 27 | delimiter: { 28 | type: "input", 29 | label: "分割符" 30 | } 31 | }, 32 | data: {} 33 | }, 34 | common: { 35 | config: { 36 | default: { 37 | type: "data-editor", 38 | label: "默认值", 39 | attrs: { 40 | types: ["array", "object"] 41 | } 42 | } 43 | }, 44 | data: { 45 | default: [] 46 | } 47 | } 48 | } 49 | }; 50 | -------------------------------------------------------------------------------- /example/main.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import App from "./App.vue"; 3 | import FRender from "f-render"; 4 | import ElementUI from "element-ui"; 5 | import EleForm from "vue-ele-form"; 6 | import EleDynamic from "vue-ele-form-dynamic"; 7 | import "element-ui/lib/theme-chalk/index.css"; 8 | import "normalize.css"; 9 | import axios from "axios"; 10 | 11 | axios.interceptors.response.use(response => { 12 | // 将响应结果返回 13 | return response.data; 14 | }); 15 | Vue.prototype.$axios = axios; 16 | Vue.config.productionTip = false; 17 | Vue.use(ElementUI); 18 | Vue.use(EleForm, { 19 | upload: { 20 | action: "https://www.mocky.io/v2/5cc8019d300000980a055e76", 21 | responseFn(response) { 22 | // 因为是 mock 地址, 所以, 总是返回同一张图片的URL, 正常使用的时候不会 23 | return response.url; 24 | } 25 | }, 26 | "upload-file": { 27 | responseFn(response, file) { 28 | return { 29 | name: file.name, 30 | url: URL.createObjectURL(file.raw), 31 | size: file.size 32 | }; 33 | } 34 | }, 35 | bmap: { 36 | ak: "9YLHZRPvUNLhi34Oh2ojqeGSpzCf1rVG" 37 | } 38 | }); 39 | Vue.component("f-render", FRender); 40 | Vue.component("dynamic", EleDynamic); 41 | 42 | new Vue({ 43 | render: h => h(App) 44 | }).$mount("#app"); 45 | -------------------------------------------------------------------------------- /src/form-skeleton.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 20 | 21 | 59 | -------------------------------------------------------------------------------- /src/components/right/form-item-attrs.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 47 | -------------------------------------------------------------------------------- /src/components/main/components/preview-dialog.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 59 | -------------------------------------------------------------------------------- /src/fixtures/extends/bmap.js: -------------------------------------------------------------------------------- 1 | export default { 2 | type: "bmap", 3 | label: "地图", 4 | config: { 5 | url: "https://github.com/dream2023/vue-ele-form-bmap", 6 | attrs: { 7 | config: { 8 | ak: { 9 | type: "input", 10 | label: "密钥", 11 | required: true 12 | }, 13 | zoom: { 14 | type: "number", 15 | label: "缩放比", 16 | attrs: { 17 | min: 1 18 | } 19 | }, 20 | isScrollWheelZoom: { 21 | type: "switch", 22 | label: "滚轮缩放大小" 23 | }, 24 | mapHeight: { 25 | type: "number", 26 | label: "地图高度", 27 | attrs: { 28 | min: 0, 29 | step: 50 30 | } 31 | }, 32 | isShowNavigation: { 33 | type: "switch", 34 | label: "是否显示缩略控件" 35 | }, 36 | isShowGeolocation: { 37 | type: "switch", 38 | label: "是否显示自动定位控件" 39 | }, 40 | placeholder: { 41 | type: "input", 42 | label: "搜索占位符" 43 | } 44 | }, 45 | data: { 46 | ak: "9YLHZRPvUNLhi34Oh2ojqeGSpzCf1rVG" 47 | } 48 | }, 49 | common: { 50 | config: { 51 | default: { 52 | type: "data-editor", 53 | label: "默认值", 54 | attrs: { 55 | types: ["string", "object"], 56 | rows: 4 57 | } 58 | } 59 | } 60 | } 61 | } 62 | }; 63 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | import _ from "lodash"; 2 | const cloneDeep = require("clone"); 3 | /** 4 | * 对象转为数组 5 | * @param {object} obj 6 | * @example 7 | * objectToArr({a1: { name: "张", age: 10 }, a2: { name: "李", age: 20 }}, 'id') 8 | * // [{ name: "张", age: 10, id: 'a1' }, { name: "李", age: 20, id: 'a2' } ] 9 | */ 10 | export function objectToArr(obj, keyField) { 11 | return Object.keys(obj).reduce((acc, key) => { 12 | acc.push(Object.assign({}, { [keyField]: key }, obj[key])); 13 | return acc; 14 | }, []); 15 | } 16 | 17 | /** 18 | * 数组转为对象 19 | * @param {array} arr 20 | * @example 21 | * arrToObject([{ name: "张", age: 10, id: 'a1' }, { name: "李", age: 20, id: 'a2' } ], 'id') 22 | * // {a1: { name: "张", age: 10 }, a2: { name: "李", age: 20 }} 23 | */ 24 | export function arrToObject(arr, key) { 25 | return cloneDeep(arr).reduce((acc, cur) => { 26 | acc[cur[key]] = cur; 27 | delete cur[key]; 28 | 29 | return acc; 30 | }, {}); 31 | } 32 | 33 | // 改变 formDesc 的 Label 34 | export function changeFormDescLabel(formDesc = {}) { 35 | return _.mapValues(formDesc, (obj, key) => { 36 | // 将 label 改为 key:label, 37 | // 例如 max: { label: "最大值" } => max: { label: "max:最大值" } 38 | const label = `${key}: ${obj.label}`; 39 | 40 | // 因为 placeholder 会采用 label 做为默认值 41 | // 所以我们需要手动赋值保持 placeholder 不变 42 | if (!obj.attrs) { 43 | obj.attrs = {}; 44 | } 45 | obj.attrs.placeholder = obj.label; 46 | return { ...obj, label }; 47 | }); 48 | } 49 | 50 | /** 51 | * 移除双引号 52 | * @param {string} str 53 | * @example 54 | * reomveQuotes({"name": "zhang"}) => {name: "zhang"} 55 | */ 56 | export function reomveQuotes(str) { 57 | return str.replace(/"(\w+)":/g, "$1:"); 58 | } 59 | 60 | /** 61 | * 移除无用的属性 62 | */ 63 | export function removeEmptyProps(obj = {}) { 64 | return _.omitBy(obj, val => val === undefined || val === null || val === ""); 65 | } 66 | -------------------------------------------------------------------------------- /example/AppHeader.vue: -------------------------------------------------------------------------------- 1 | 30 | 31 | 54 | 55 | 77 | -------------------------------------------------------------------------------- /src/fixtures/extends/gallery.js: -------------------------------------------------------------------------------- 1 | export default { 2 | type: "gallery", 3 | label: "图片及视频展示", 4 | config: { 5 | url: "https://github.com/dream2023/vue-ele-form-gallery", 6 | attrs: { 7 | config: { 8 | type: { 9 | type: "select", 10 | label: "类型", 11 | options: ["image", "video", "iframe"] 12 | }, 13 | width: { 14 | type: "number", 15 | label: "缩略图宽度", 16 | attrs: { 17 | min: 0, 18 | step: 10 19 | } 20 | }, 21 | height: { 22 | type: "number", 23 | label: "缩略图高度", 24 | attrs: { 25 | min: 0, 26 | step: 10 27 | } 28 | }, 29 | lazy: { 30 | type: "switch", 31 | label: "缩略图是否懒加载" 32 | }, 33 | thumbSuffix: { 34 | type: "input", 35 | label: "缩略图后缀" 36 | }, 37 | thumbStyle: { 38 | type: "data-editor", 39 | label: "缩略图样式", 40 | attrs: { 41 | types: ["object"] 42 | } 43 | }, 44 | carouselAttrs: { 45 | type: "data-editor", 46 | label: "轮播图属性", 47 | attrs: { 48 | types: ["object"] 49 | } 50 | } 51 | }, 52 | data: {} 53 | }, 54 | common: { 55 | config: { 56 | default: { 57 | type: "dynamic", 58 | label: "默认值", 59 | attrs: { 60 | columns: { 61 | type: "el-input", 62 | attrs: { 63 | placeholder: "图片链接" 64 | } 65 | } 66 | } 67 | } 68 | }, 69 | data: { 70 | default: [ 71 | "https://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg", 72 | "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg" 73 | ] 74 | } 75 | } 76 | } 77 | }; 78 | -------------------------------------------------------------------------------- /src/fixtures/extends/video-uploader.js: -------------------------------------------------------------------------------- 1 | export default { 2 | type: "video-uploader", 3 | label: "上传视频", 4 | config: { 5 | url: "https://github.com/dream2023/vue-ele-form-video-uploader", 6 | attrs: { 7 | config: { 8 | action: { 9 | type: "input", 10 | label: "上传地址", 11 | required: true 12 | }, 13 | name: { 14 | type: "input", 15 | label: "上传的文件字段名", 16 | required: true 17 | }, 18 | fileSize: { 19 | type: "input", 20 | label: "文件大小限制(MB)", 21 | attrs: { 22 | type: "number", 23 | min: 0 24 | } 25 | }, 26 | width: { 27 | type: "number", 28 | label: "显示宽度", 29 | attrs: { 30 | step: 10, 31 | min: 0 32 | } 33 | }, 34 | height: { 35 | type: "number", 36 | label: "显示高度(默认auto)", 37 | attrs: { 38 | step: 10, 39 | min: 0 40 | } 41 | }, 42 | fileType: { 43 | type: "data-editor", 44 | label: "文件类型", 45 | attrs: { 46 | types: ["array"], 47 | rows: 4 48 | } 49 | }, 50 | isShowTip: { 51 | type: "switch", 52 | label: "是否显示提示" 53 | }, 54 | withCredentials: { 55 | type: "switch", 56 | label: "支持发送 cookie 凭证信息" 57 | }, 58 | data: { 59 | type: "data-editor", 60 | label: "上传时附带的额外参数", 61 | attrs: { 62 | types: ["object"] 63 | } 64 | }, 65 | headers: { 66 | type: "data-editor", 67 | label: "设置上传的请求头部", 68 | attrs: { 69 | types: ["object"] 70 | } 71 | } 72 | }, 73 | data: { 74 | action: "https://www.mocky.io/v2/5cc8019d300000980a055e76" 75 | } 76 | } 77 | } 78 | }; 79 | -------------------------------------------------------------------------------- /src/fixtures/extends/quill-editor.js: -------------------------------------------------------------------------------- 1 | export default { 2 | type: "quill-editor", 3 | label: "富文本编辑器", 4 | config: { 5 | url: "https://github.com/dream2023/vue-ele-form-quill-editor", 6 | attrs: { 7 | config: { 8 | action: { 9 | type: "input", 10 | label: "上传地址", 11 | required: true 12 | }, 13 | editorOptions: { 14 | type: "data-editor", 15 | label: "编辑器设置", 16 | tip: "请参考: https://github.com/davidroyer/vue2-editor", 17 | attrs: { 18 | types: ["object"] 19 | } 20 | }, 21 | placeholder: { 22 | type: "input", 23 | label: "占位符" 24 | }, 25 | fileSize: { 26 | type: "input", 27 | label: "文件大小限制(MB)", 28 | attrs: { 29 | type: "number", 30 | min: 0 31 | } 32 | }, 33 | name: { 34 | type: "input", 35 | label: "上传的文件字段名", 36 | required: true 37 | }, 38 | withCredentials: { 39 | type: "switch", 40 | label: "支持发送 cookie 凭证信息" 41 | }, 42 | data: { 43 | type: "data-editor", 44 | label: "上传时附带的额外参数", 45 | attrs: { 46 | types: ["object"] 47 | } 48 | }, 49 | headers: { 50 | type: "data-editor", 51 | label: "设置上传的请求头部", 52 | attrs: { 53 | types: ["object"] 54 | } 55 | }, 56 | editorToolbar: { 57 | type: "data-editor", 58 | label: "自定义toolbar", 59 | attrs: { 60 | types: ["array"] 61 | } 62 | } 63 | }, 64 | data: { 65 | action: "https://www.mocky.io/v2/5cc8019d300000980a055e76" 66 | } 67 | }, 68 | common: { 69 | config: { 70 | default: { 71 | type: "textarea", 72 | label: "默认值" 73 | } 74 | } 75 | } 76 | } 77 | }; 78 | -------------------------------------------------------------------------------- /src/components/right/index.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 51 | 52 | 82 | -------------------------------------------------------------------------------- /src/fixtures/extends/upload-file.js: -------------------------------------------------------------------------------- 1 | export default { 2 | type: "upload-file", 3 | label: "文件上传", 4 | config: { 5 | url: "https://github.com/dream2023/vue-ele-form-upload-file", 6 | attrs: { 7 | config: { 8 | action: { 9 | type: "input", 10 | label: "上传地址", 11 | required: true 12 | }, 13 | name: { 14 | type: "input", 15 | label: "上传的文件字段名", 16 | required: true 17 | }, 18 | placeholder: { 19 | type: "input", 20 | label: "上传按钮文本" 21 | }, 22 | fileSize: { 23 | type: "input", 24 | label: "文件大小限制(MB)", 25 | attrs: { 26 | type: "number", 27 | min: 0 28 | } 29 | }, 30 | fileType: { 31 | type: "data-editor", 32 | label: '文件类型, 例如["png", "jpg", "jpeg"]', 33 | attrs: { 34 | types: ["array"], 35 | rows: 4 36 | } 37 | }, 38 | multiple: { 39 | type: "switch", 40 | label: "是否支持多选文件" 41 | }, 42 | limit: { 43 | type: "input", 44 | label: "文件个数显示", 45 | vif: data => data.multiple, 46 | attrs: { 47 | type: "number", 48 | min: 0 49 | } 50 | }, 51 | isCanDownload: { 52 | type: "switch", 53 | label: "是否显示下载" 54 | }, 55 | isCanDelete: { 56 | type: "switch", 57 | label: "是否可删除" 58 | }, 59 | isCanUploadSame: { 60 | type: "switch", 61 | label: "是否可上传相同文件" 62 | }, 63 | isShowTip: { 64 | type: "switch", 65 | label: "是否显示提示" 66 | }, 67 | withCredentials: { 68 | type: "switch", 69 | label: "支持发送 cookie 凭证信息" 70 | }, 71 | data: { 72 | type: "data-editor", 73 | label: "上传时附带的额外参数", 74 | attrs: { 75 | types: ["object"] 76 | } 77 | }, 78 | headers: { 79 | type: "data-editor", 80 | label: "设置上传的请求头部", 81 | attrs: { 82 | types: ["object"] 83 | } 84 | } 85 | }, 86 | data: { 87 | action: "https://www.mocky.io/v2/5cc8019d300000980a055e76" 88 | } 89 | } 90 | } 91 | }; 92 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "f-render", 3 | "version": "4.12.3", 4 | "private": false, 5 | "license": "MIT", 6 | "description": "f-render | 基于 ElementUI 的表单设计器", 7 | "scripts": { 8 | "serve": "vue-cli-service serve", 9 | "build": "vue-cli-service build", 10 | "toc": "doctoc README.md", 11 | "build:lib": "vue-cli-service build --target lib --name f-render ./src/index.js", 12 | "lint": "vue-cli-service lint --mode=production", 13 | "release": "standard-version", 14 | "pub": " npm run release && npm publish && git push --follow-tags origin master" 15 | }, 16 | "main": "./dist/f-render.umd.min.js", 17 | "dependencies": { 18 | "clipboard-copy": "^3.1.0", 19 | "clone": "^2.1.2", 20 | "fuzzy": "^0.1.3", 21 | "indent-string": "^4.0.0", 22 | "lodash": "^4.17.20", 23 | "prismjs": "^1.21.0", 24 | "serialize-javascript": "^4.0.0", 25 | "vue-ele-form-data-editor": "^0.1.6", 26 | "vue-ele-form-dynamic": "^0.4.3", 27 | "vue-multipane": "^0.9.5", 28 | "vue-prism-editor": "^1.2.2", 29 | "vue2-perfect-scrollbar": "^1.5.0", 30 | "vuedraggable": "^2.24.0" 31 | }, 32 | "devDependencies": { 33 | "@vue/cli-plugin-babel": "~4.5.0", 34 | "@vue/cli-plugin-eslint": "~4.5.0", 35 | "@vue/cli-service": "~4.5.0", 36 | "@vue/eslint-config-prettier": "^6.0.0", 37 | "axios": "^0.20.0", 38 | "babel-eslint": "^10.1.0", 39 | "babel-plugin-lodash": "^3.3.4", 40 | "core-js": "^3.6.5", 41 | "doctoc": "^1.4.0", 42 | "element-ui": "^2.13.2", 43 | "eslint": "^6.7.2", 44 | "eslint-plugin-prettier": "^3.1.3", 45 | "eslint-plugin-vue": "^6.2.2", 46 | "lint-staged": "^9.5.0", 47 | "lodash-webpack-plugin": "^0.11.5", 48 | "normalize.css": "^8.0.1", 49 | "prettier": "^1.19.1", 50 | "standard-version": "^9.0.0", 51 | "vue": "^2.6.11", 52 | "vue-ele-form": "^0.8.56", 53 | "vue-template-compiler": "^2.6.11" 54 | }, 55 | "repository": { 56 | "type": "git", 57 | "url": "https://github.com/dream2023/f-render" 58 | }, 59 | "keywords": [ 60 | "vue-ele-form", 61 | "f-render", 62 | "form-schema", 63 | "vue-form", 64 | "form-designer", 65 | "form-design", 66 | "element-ui", 67 | "form-generator", 68 | "for-generate", 69 | "vue-form-generator", 70 | "form schema" 71 | ], 72 | "gitHooks": { 73 | "pre-commit": "lint-staged" 74 | }, 75 | "lint-staged": { 76 | "*.{js,jsx,vue}": [ 77 | "vue-cli-service lint --mode=production", 78 | "git add" 79 | ] 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/fixtures/extends/tree-select.js: -------------------------------------------------------------------------------- 1 | export default { 2 | type: "tree-select", 3 | label: "树形下拉选择器", 4 | config: { 5 | url: "https://github.com/dream2023/vue-ele-form-tree-select", 6 | attrs: { 7 | config: { 8 | placeholder: { 9 | type: "input", 10 | label: "占位符" 11 | }, 12 | appendToBody: { 13 | type: "switch", 14 | label: "弹窗插入body" 15 | }, 16 | multiple: { 17 | type: "switch", 18 | label: "是否开启多选模式" 19 | }, 20 | searchable: { 21 | type: "switch", 22 | label: "是否开启搜索功能" 23 | }, 24 | async: { 25 | type: "switch", 26 | label: "是否开启异步搜索" 27 | }, 28 | autoFocus: { 29 | type: "switch", 30 | label: "是否自动聚焦" 31 | }, 32 | clearable: { 33 | type: "switch", 34 | label: "是否显示清除图标" 35 | }, 36 | limit: { 37 | type: "number", 38 | label: "多选数量显示", 39 | vif: data => data.multiple, 40 | attrs: { 41 | min: 1 42 | } 43 | }, 44 | maxHeight: { 45 | type: "number", 46 | label: "弹出菜单高度", 47 | attrs: { 48 | min: 0, 49 | step: 10 50 | } 51 | }, 52 | alwaysOpen: { 53 | type: "switch", 54 | label: "一直打开选项菜单" 55 | }, 56 | flattenSearchResults: { 57 | type: "switch", 58 | label: "是否展平搜索结果", 59 | vif: data => data.async 60 | }, 61 | autoLoadRootOptions: { 62 | type: "switch", 63 | label: "是否自定加载根节点选项" 64 | } 65 | } 66 | }, 67 | common: { 68 | config: { 69 | default: { 70 | type: "tree-select", 71 | label: "默认值", 72 | prop: data => data.prop, 73 | optionsLinkageFields: data => data.optionsLinkageFields, 74 | options: data => data.options 75 | } 76 | }, 77 | data: { 78 | isOptions: true, 79 | options: [ 80 | { 81 | id: "a", 82 | label: "a", 83 | children: [ 84 | { 85 | id: "aa", 86 | label: "aa" 87 | }, 88 | { 89 | id: "ab", 90 | label: "ab" 91 | } 92 | ] 93 | }, 94 | { 95 | id: "b", 96 | label: "b" 97 | }, 98 | { 99 | id: "c", 100 | label: "c" 101 | } 102 | ] 103 | } 104 | } 105 | } 106 | }; 107 | -------------------------------------------------------------------------------- /src/components/left/index.vue: -------------------------------------------------------------------------------- 1 | 35 | 36 | 76 | 77 | 113 | -------------------------------------------------------------------------------- /src/components/main/components/code-dialog.vue: -------------------------------------------------------------------------------- 1 | 35 | 36 | 112 | -------------------------------------------------------------------------------- /src/fixtures/extends/image-uploader.js: -------------------------------------------------------------------------------- 1 | export default { 2 | type: "image-uploader", 3 | label: "上传图片", 4 | config: { 5 | url: "https://github.com/dream2023/vue-ele-form-image-uploader", 6 | attrs: { 7 | config: { 8 | action: { 9 | type: "input", 10 | label: "上传地址", 11 | required: true 12 | }, 13 | name: { 14 | type: "input", 15 | label: "上传的文件字段名", 16 | required: true 17 | }, 18 | corp: { 19 | type: "switch", 20 | label: "是否剪裁" 21 | }, 22 | cropHeight: { 23 | type: "number", 24 | label: "裁剪高度", 25 | vif: data => data.corp, 26 | attrs: { 27 | min: 0 28 | } 29 | }, 30 | cropWidth: { 31 | type: "number", 32 | label: "裁剪宽度", 33 | vif: data => data.corp, 34 | attrs: { 35 | min: 0 36 | } 37 | }, 38 | multiple: { 39 | type: "switch", 40 | label: "是否支持多选文件" 41 | }, 42 | limit: { 43 | type: "input", 44 | label: "文件个数显示", 45 | vif: data => data.multiple, 46 | attrs: { 47 | min: 0, 48 | type: "number" 49 | } 50 | }, 51 | size: { 52 | type: "number", 53 | label: "图片显示大小", 54 | attrs: { 55 | min: 0, 56 | step: 10 57 | } 58 | }, 59 | fileSize: { 60 | type: "number", 61 | label: "文件大小限制(MB)", 62 | attrs: { 63 | min: 0 64 | } 65 | }, 66 | lazy: { 67 | type: "switch", 68 | label: "图片懒加载" 69 | }, 70 | drag: { 71 | type: "switch", 72 | label: "是否启用拖拽上传" 73 | }, 74 | withCredentials: { 75 | type: "switch", 76 | label: "支持发送 cookie 凭证信息" 77 | }, 78 | isShowTip: { 79 | type: "switch", 80 | label: "是否显示提示" 81 | }, 82 | title: { 83 | type: "input", 84 | label: "弹窗标题" 85 | }, 86 | thumbSuffix: { 87 | type: "input", 88 | label: "略图后缀, 例如七牛云缩略图样式 (?imageView2/1/w/20/h/20)" 89 | }, 90 | fileType: { 91 | type: "data-editor", 92 | label: '文件类型, 例如["png", "jpg", "jpeg"]', 93 | attrs: { 94 | types: ["array"] 95 | } 96 | }, 97 | data: { 98 | type: "data-editor", 99 | label: "上传时附带的额外参数", 100 | attrs: { 101 | types: ["array", "object"] 102 | } 103 | }, 104 | headers: { 105 | type: "data-editor", 106 | label: "设置上传的请求头部", 107 | attrs: { 108 | types: ["object"] 109 | } 110 | } 111 | }, 112 | data: { 113 | action: "https://www.mocky.io/v2/5cc8019d300000980a055e76" 114 | } 115 | } 116 | } 117 | }; 118 | -------------------------------------------------------------------------------- /src/fixtures/extends/data-editor.js: -------------------------------------------------------------------------------- 1 | export default { 2 | type: "textarea", 3 | label: "多行输入框", 4 | sort: 2, 5 | config: { 6 | url: "https://element.eleme.cn/#/zh-CN/component/input#wen-ben-yu", 7 | attrs: { 8 | config: { 9 | autoSave: { 10 | type: "switch", 11 | label: "是否自动保存" 12 | }, 13 | types: { 14 | type: "dynamic", 15 | label: "数据类型" 16 | }, 17 | placeholder: { 18 | type: "input", 19 | label: "输入框占位文本", 20 | attrs: { 21 | clearable: true 22 | } 23 | }, 24 | rows: { 25 | type: "number", 26 | label: "输入框行", 27 | attrs: { 28 | min: 1 29 | } 30 | }, 31 | autosizeType: { 32 | type: "radio", 33 | label: "自适应内容高度值类型", 34 | default: "switch", 35 | options: [ 36 | { text: "自适应", value: "switch" }, 37 | { text: "最大最小值", value: "data-editor" } 38 | ] 39 | }, 40 | autosize: { 41 | type: data => data.autosizeType, 42 | default: data => { 43 | if (data.autosizeType === "switch") { 44 | return false; 45 | } else { 46 | return { minRows: 2, maxRows: 6 }; 47 | } 48 | }, 49 | label: "自适应内容高度配置", 50 | attrs(data) { 51 | if (data.autosizeType === "data-editor") { 52 | return { 53 | types: ["object"], 54 | rows: 4 55 | }; 56 | } 57 | }, 58 | rules: [ 59 | { 60 | trigger: "blur", 61 | validator: function(rule, value, callback) { 62 | if (typeof value === "object") { 63 | if (!value.minRows || !value.maxRows) { 64 | callback("对象必须包含 minRows 和 maxRows"); 65 | } 66 | } else if (typeof value !== "boolean") { 67 | callback("数据类型不正确"); 68 | } 69 | } 70 | } 71 | ] 72 | }, 73 | resize: { 74 | type: "select", 75 | label: "控制是否能被用户缩放", 76 | options: ["both", "horizontal", "vertical"], 77 | attrs: { 78 | clearable: true 79 | } 80 | }, 81 | showWordLimit: { 82 | type: "switch", 83 | label: "是否显示输入字数统计", 84 | vif: data => data.minlength || data.maxlength 85 | }, 86 | clearable: { 87 | type: "switch", 88 | label: "是否可清空" 89 | }, 90 | autofocus: { 91 | type: "switch", 92 | label: "原生属性,自动获取焦点" 93 | }, 94 | tabindex: { 95 | type: "input", 96 | label: "输入框的tabindex", 97 | attrs: { 98 | clearable: true 99 | } 100 | }, 101 | validateEvent: { 102 | type: "switch", 103 | label: "输入时是否触发表单的校验" 104 | } 105 | }, 106 | data: {} 107 | } 108 | } 109 | }; 110 | -------------------------------------------------------------------------------- /src/components/right/form-item-common.vue: -------------------------------------------------------------------------------- 1 | 44 | 45 | 116 | -------------------------------------------------------------------------------- /src/fixtures/extends/markdown-editor.js: -------------------------------------------------------------------------------- 1 | export default { 2 | type: "markdown-editor", 3 | label: "markdown编辑器", 4 | config: { 5 | url: "https://github.com/dream2023/vue-ele-form-markdown-editor", 6 | attrs: { 7 | config: { 8 | fontSize: { 9 | type: "input", 10 | label: "编辑区域文字大小" 11 | }, 12 | scrollStyle: { 13 | type: "switch", 14 | label: "开启滚动条样式(暂时仅支持chrome)" 15 | }, 16 | boxShadow: { 17 | type: "switch", 18 | label: "开启边框阴影" 19 | }, 20 | boxShadowStyle: { 21 | type: "input", 22 | label: "边框阴影样式" 23 | }, 24 | transition: { 25 | type: "switch", 26 | label: "是否开启过渡动画" 27 | }, 28 | toolbarsBackground: { 29 | type: "color", 30 | label: "工具栏背景颜色" 31 | }, 32 | previewBackground: { 33 | type: "color", 34 | label: "预览框背景颜色" 35 | }, 36 | subfield: { 37 | type: "switch", 38 | label: "true: 双栏(编辑预览同屏), false: 单栏(编辑预览分屏)" 39 | }, 40 | defaultOpen: { 41 | type: "radio", 42 | label: "默认展示区域", 43 | options: ["edit", "preview"] 44 | }, 45 | placeholder: { 46 | type: "input", 47 | label: "输入框为空时默认提示文本" 48 | }, 49 | editable: { 50 | type: "switch", 51 | label: "是否允许编辑" 52 | }, 53 | toolbarsFlag: { 54 | type: "switch", 55 | label: "工具栏是否显示" 56 | }, 57 | navigation: { 58 | type: "switch", 59 | label: "默认展示目录" 60 | }, 61 | shortCut: { 62 | type: "switch", 63 | label: "是否启用快捷键" 64 | }, 65 | autofocus: { 66 | type: "switch", 67 | label: "自动聚焦到文本框" 68 | }, 69 | ishljs: { 70 | type: "switch", 71 | label: "代码高亮" 72 | }, 73 | toolbars: { 74 | type: "data-editor", 75 | label: "工具栏", 76 | attrs: { 77 | types: ["object"], 78 | rows: 10 79 | } 80 | }, 81 | action: { 82 | type: "input", 83 | label: "上传地址", 84 | required: true 85 | }, 86 | fileSize: { 87 | type: "input", 88 | label: "文件大小限制(MB)", 89 | attrs: { 90 | type: "number", 91 | min: 0 92 | } 93 | }, 94 | name: { 95 | type: "input", 96 | label: "上传的文件字段名", 97 | required: true 98 | }, 99 | withCredentials: { 100 | type: "switch", 101 | label: "支持发送 cookie 凭证信息" 102 | }, 103 | data: { 104 | type: "data-editor", 105 | label: "上传时附带的额外参数", 106 | attrs: { 107 | types: ["object"] 108 | } 109 | }, 110 | headers: { 111 | type: "data-editor", 112 | label: "设置上传的请求头部", 113 | attrs: { 114 | types: ["object"] 115 | } 116 | } 117 | }, 118 | data: { 119 | action: "https://www.mocky.io/v2/5cc8019d300000980a055e76" 120 | } 121 | }, 122 | common: { 123 | config: { 124 | default: { 125 | type: "textarea", 126 | label: "默认值", 127 | default: "" 128 | } 129 | } 130 | } 131 | } 132 | }; 133 | -------------------------------------------------------------------------------- /src/fixtures/form-item-common.js: -------------------------------------------------------------------------------- 1 | export default { 2 | config: { 3 | field: { 4 | type: "input", 5 | label: "字段名", 6 | tip: "字段名不可重复", 7 | rules: { 8 | type: "string" 9 | } 10 | }, 11 | label: { 12 | type: "input", 13 | label: "标签" 14 | }, 15 | layout: { 16 | type: "slider", 17 | label: "宽度", 18 | attrs: { 19 | min: 1, 20 | max: 24, 21 | formatTooltip(val) { 22 | return `${val} / 24`; 23 | } 24 | } 25 | }, 26 | default: { 27 | type: "input", 28 | label: "默认值" 29 | }, 30 | required: { 31 | type: "yesno", 32 | label: "校检", 33 | title: "是否必填" 34 | }, 35 | rules: { 36 | type: "data-editor", 37 | label: "校检规则", 38 | title: "新增校检规则", 39 | default: [], 40 | attrs: { 41 | types: ["array", "object"], 42 | rows: 10 43 | }, 44 | tip: 45 | '校检规则文档, 请点击查看' 46 | }, 47 | options: { 48 | type: "data-editor", 49 | label: "选项", 50 | attrs: { 51 | types: ["string", "array", "function", "promise", "asyncfunction"], 52 | rows: 10 53 | }, 54 | vif: data => data.isOptions, 55 | tip: 56 | 'options支持`API接口`、`数组`、`函数`、`Promise`等, 具体看文档' 57 | }, 58 | prop: { 59 | type: "data-editor", 60 | label: "options 配置", 61 | vif: data => data.isOptions, 62 | attrs: { 63 | types: ["object"], 64 | rows: 4 65 | } 66 | }, 67 | optionsLinkageFields: { 68 | type: "dynamic", 69 | vif: data => data.isOptions, 70 | label: "options 关联属性" 71 | }, 72 | vif: { 73 | type: "data-editor", 74 | label: "联动显示/隐藏", 75 | attrs: { 76 | types: ["function", "boolean"] 77 | }, 78 | tip: 79 | '支持`布尔值`和`函数`,具体请查看:文档' 80 | }, 81 | disabled: { 82 | type: "data-editor", 83 | label: "联动启用/禁用", 84 | attrs: { 85 | types: ["function", "boolean", "string"] 86 | }, 87 | tip: 88 | '支持`布尔值`和`函数`,具体请查看:文档' 89 | }, 90 | tip: { 91 | type: "input", 92 | label: "表单项提示" 93 | }, 94 | isShowLabel: { 95 | label: "否显示标签", 96 | type: "radio-button", 97 | tip: "与全局isShowLabel作用相同", 98 | options: [ 99 | { text: "显示", value: undefined }, 100 | { text: "隐藏", value: false } 101 | ] 102 | }, 103 | labelWidth: { 104 | label: "标签宽度", 105 | type: "input", 106 | tip: "需要以`px`作为单位, 例如`100px`, 默认为全局设置的labelWidth值" 107 | }, 108 | break: { 109 | label: "强制折行", 110 | type: "radio-button", 111 | options: [ 112 | { text: "正常", value: undefined }, 113 | { text: "折行", value: true } 114 | ] 115 | }, 116 | displayFormatter: { 117 | label: "显示处理函数", 118 | type: "data-editor", 119 | attrs: { 120 | types: ["function"] 121 | } 122 | }, 123 | valueFormatter: { 124 | label: "最终值处理函数", 125 | type: "data-editor", 126 | attrs: { 127 | types: ["function"] 128 | } 129 | } 130 | }, 131 | // 覆盖值 132 | data: {} 133 | }; 134 | -------------------------------------------------------------------------------- /src/components/main/components/data-dialog.vue: -------------------------------------------------------------------------------- 1 | 37 | 38 | 125 | -------------------------------------------------------------------------------- /src/fixtures/extends/table-editor.js: -------------------------------------------------------------------------------- 1 | export default { 2 | type: "table-editor", 3 | label: "表格内容编辑组件", 4 | config: { 5 | url: "https://github.com/dream2023/vue-ele-form-table-editor", 6 | attrs: { 7 | config: { 8 | columns: { 9 | type: "data-editor", 10 | label: "table 列", 11 | required: true, 12 | attrs: { 13 | types: ["array", "object"] 14 | }, 15 | rows: 12 16 | }, 17 | isShowDelete: { 18 | type: "switch", 19 | label: "是否显示删除" 20 | }, 21 | isShowAdd: { 22 | type: "switch", 23 | label: "是否显示新增按钮" 24 | }, 25 | addBtnText: { 26 | type: "input", 27 | label: "新增按钮文本" 28 | }, 29 | newColumnValue: { 30 | type: "data-editor", 31 | label: "新增列的值", 32 | attrs: { 33 | types: ["object"] 34 | } 35 | }, 36 | rules: { 37 | type: "data-editor", 38 | label: "校检规则", 39 | attrs: { 40 | types: ["object", "array"], 41 | rows: 10 42 | } 43 | }, 44 | extraBtns: { 45 | type: "data-editor", 46 | label: "右侧其它按钮", 47 | attrs: { 48 | types: ["array"] 49 | } 50 | }, 51 | deleteBtnAttr: { 52 | type: "data-editor", 53 | label: "删除按钮属性", 54 | attrs: { 55 | types: ["object"] 56 | } 57 | }, 58 | tableAttrs: { 59 | type: "data-editor", 60 | label: "表格属性", 61 | attrs: { 62 | types: ["object"] 63 | } 64 | } 65 | }, 66 | data: { 67 | columns: [ 68 | { 69 | // el-table-column 的属性 70 | type: "index", 71 | width: 50 72 | }, 73 | { 74 | // el-table-column 的属性 75 | prop: "grade", 76 | label: "年级" 77 | }, 78 | { 79 | prop: "name", 80 | label: "姓名", 81 | content: { 82 | type: "el-input", 83 | attrs: { 84 | placeholder: "学员姓名" 85 | } 86 | } 87 | }, 88 | { 89 | label: "缴费", 90 | width: 200, 91 | content: [ 92 | "已缴纳: ", 93 | { 94 | type: "el-input", 95 | valueKey: "tuition", 96 | style: { 97 | width: "100px", 98 | marginRight: "10px" 99 | } 100 | } 101 | ] 102 | }, 103 | { 104 | prop: "dream", 105 | label: "梦想", 106 | content: { 107 | type: "el-select", 108 | options: [ 109 | { text: "科学家", value: "scientist" }, 110 | { text: "警察", value: "policeman" }, 111 | "程序员" 112 | ] 113 | } 114 | } 115 | ], 116 | newColumnValue: { 117 | grade: "三年级二班" 118 | } 119 | } 120 | }, 121 | common: { 122 | config: { 123 | default: { 124 | type: "data-editor", 125 | label: "默认值", 126 | attrs: { 127 | types: ["array"] 128 | } 129 | } 130 | }, 131 | data: { 132 | default: [ 133 | { 134 | grade: "三年级二班", 135 | name: "小张", 136 | sex: 1, 137 | tuition: 2000, 138 | unPay: 100, 139 | dream: "" 140 | } 141 | ] 142 | } 143 | } 144 | } 145 | }; 146 | -------------------------------------------------------------------------------- /src/components/main/main-header.vue: -------------------------------------------------------------------------------- 1 | 36 | 37 | 118 | 119 | 145 | -------------------------------------------------------------------------------- /src/fixtures/form-props.js: -------------------------------------------------------------------------------- 1 | export default { 2 | config: { 3 | inline: { 4 | type: "radio-button", 5 | label: "inline模式 / layout模式", 6 | options: [ 7 | { text: "layout模式", value: undefined }, 8 | { text: "inline模式", value: true } 9 | ] 10 | }, 11 | isResponsive: { 12 | type: "radio-button", 13 | label: "是否响应式", 14 | vif: data => !data.inline, 15 | options: [ 16 | { text: "是", value: undefined }, 17 | { text: "否", value: false } 18 | ] 19 | }, 20 | labelPosition: { 21 | type: "radio-button", 22 | label: "标签位置", 23 | options(data) { 24 | const options = ["left", "right", "top"]; 25 | if (data.isResponsive !== false && !data.inline) { 26 | options.unshift({ text: "响应式", value: undefined }); 27 | } 28 | return options; 29 | } 30 | }, 31 | span: { 32 | type: "select", 33 | label: "表单宽度", 34 | vif: data => !data.inline, 35 | options() { 36 | const options = Array.from({ length: 24 }, (v, i) => { 37 | return { text: `${24 - i} / 24`, value: 24 - i }; 38 | }); 39 | options.unshift({ text: "响应式", value: undefined }); 40 | return options; 41 | }, 42 | style: { 43 | width: "100%" 44 | } 45 | }, 46 | rules: { 47 | type: "data-editor", 48 | label: "校检规则", 49 | attrs: { 50 | types: ["object"] 51 | }, 52 | tip: 53 | '校检规则文档, 请点击查看' 54 | }, 55 | isDialog: { 56 | type: "radio-button", 57 | label: "是否为弹窗", 58 | options: [ 59 | { text: "非弹窗", value: undefined }, 60 | { text: "弹窗", value: true } 61 | ] 62 | }, 63 | isShowLabel: { 64 | type: "radio-button", 65 | label: "是否显示标签", 66 | options: [ 67 | { text: "显示", value: undefined }, 68 | { text: "不显示", value: false } 69 | ] 70 | }, 71 | labelWidth: { 72 | type: "input", 73 | label: "标签宽度", 74 | attrs: { 75 | type: "number", 76 | min: 0, 77 | step: 10 78 | }, 79 | tip: "默认值为 `auto`" 80 | }, 81 | disabled: { 82 | type: "radio-button", 83 | label: "全局禁用表单", 84 | options: [ 85 | { text: "正常", value: undefined }, 86 | { text: "禁用", value: true } 87 | ] 88 | }, 89 | readonly: { 90 | type: "radio-button", 91 | label: "全局只读表单", 92 | options: [ 93 | { text: "正常", value: undefined }, 94 | { text: "只读", value: true } 95 | ] 96 | }, 97 | isShowErrorNotify: { 98 | type: "radio-button", 99 | label: "是否在校检错误后显示右上角提示", 100 | options: [ 101 | { text: "显示", value: undefined }, 102 | { text: "不显示", value: false } 103 | ] 104 | }, 105 | isShowSubmitBtn: { 106 | type: "radio-button", 107 | label: "提交按钮", 108 | options: [ 109 | { text: "显示", value: undefined }, 110 | { text: "隐藏", value: false } 111 | ] 112 | }, 113 | isShowBackBtn: { 114 | type: "radio-button", 115 | label: "返回按钮", 116 | options: [ 117 | { text: "显示", value: undefined }, 118 | { text: "隐藏", value: false } 119 | ] 120 | }, 121 | formBtnSize: { 122 | type: "radio-button", 123 | label: "表单按钮大小", 124 | options: [{ text: "默认", value: undefined }, "medium", "small", "mini"] 125 | }, 126 | isShowResetBtn: { 127 | type: "radio-button", 128 | label: "重置按钮", 129 | options: [ 130 | { text: "显示", value: true }, 131 | { text: "隐藏", value: undefined } 132 | ] 133 | }, 134 | isShowCancelBtn: { 135 | type: "radio-button", 136 | label: "取消按钮", 137 | options: [ 138 | { text: "显示", value: true }, 139 | { text: "隐藏", value: undefined } 140 | ] 141 | }, 142 | submitBtnText: { 143 | type: "input", 144 | label: "提交按钮文字" 145 | }, 146 | backBtnText: { 147 | type: "input", 148 | label: "返回按钮文字" 149 | }, 150 | cancelBtnText: { 151 | type: "input", 152 | label: "取消按钮文字" 153 | }, 154 | resetBtnText: { 155 | type: "input", 156 | label: "返回按钮文字" 157 | }, 158 | formAttrs: { 159 | type: "data-editor", 160 | label: "el-form属性", 161 | attrs: { 162 | types: ["object"] 163 | } 164 | } 165 | }, 166 | data: {} 167 | }; 168 | -------------------------------------------------------------------------------- /src/components/main/main-content.vue: -------------------------------------------------------------------------------- 1 | 83 | 84 | 142 | 143 | 204 | -------------------------------------------------------------------------------- /src/components/main/components/batch-dialog.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 193 | -------------------------------------------------------------------------------- /src/components/right/components/form-item-rules.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 196 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | ### [4.12.2](https://github.com/dream2023/f-render/compare/v4.12.1...v4.12.2) (2020-12-22) 6 | 7 | 8 | ### Bug Fixes 9 | 10 | * **#66:** attrs 属性未隔离 & 火狐浏览器拖拽打开新页面 ([7d733e9](https://github.com/dream2023/f-render/commit/7d733e94131d8ae6a9384b6b25cf8a1c0009136f)), closes [#66](https://github.com/dream2023/f-render/issues/66) 11 | 12 | ### [4.12.1](https://github.com/dream2023/f-render/compare/v4.12.0...v4.12.1) (2020-11-17) 13 | 14 | ## [4.12.0](https://github.com/dream2023/f-render/compare/v4.10.2...v4.12.0) (2020-11-01) 15 | 16 | 17 | ### Features 18 | 19 | * 增加插槽 & 右侧属性面板配置 ([106fa49](https://github.com/dream2023/f-render/commit/106fa49f965366bd53dc90f3d8541ca0089c0b98)) 20 | 21 | ## [4.11.0](https://github.com/dream2023/f-render/compare/v4.10.2...v4.11.0) (2020-11-01) 22 | 23 | 24 | ### Features 25 | 26 | * 增加插槽 & 右侧属性面板配置 ([106fa49](https://github.com/dream2023/f-render/commit/106fa49f965366bd53dc90f3d8541ca0089c0b98)) 27 | 28 | ### [4.10.2](https://github.com/dream2023/f-render/compare/v4.10.1...v4.10.2) (2020-10-23) 29 | 30 | 31 | ### Bug Fixes 32 | 33 | * 修复 BUG ([fe50821](https://github.com/dream2023/f-render/commit/fe50821918dfd1106ee23feccae3f88a102d771b)) 34 | * 修复 switch 相关 BUG ([dfd0a7e](https://github.com/dream2023/f-render/commit/dfd0a7ecc349322983e8a5507641d547829d1618)) 35 | 36 | ### [4.10.1](https://github.com/dream2023/f-render/compare/v4.9.0...v4.10.1) (2020-10-16) 37 | 38 | ## [4.10.0](https://github.com/dream2023/f-render/compare/v4.8.0...v4.10.0) (2020-10-14) 39 | 40 | ### Features 41 | 42 | - 兼容 ie11 ([4a140df](https://github.com/dream2023/f-render/commit/4a140dfe7a9a6460170c8905b308b2a613b1ade6)) 43 | 44 | ## [4.8.0](https://github.com/dream2023/f-render/compare/v4.7.2...v4.8.0) (2020-09-14) 45 | 46 | ### Features 47 | 48 | - 修复级联组件默认值 BUG ([c950d55](https://github.com/dream2023/f-render/commit/c950d55cca9b6fb12e2568b71c1bcece51711652)) 49 | 50 | ### [4.7.2](https://github.com/dream2023/f-render/compare/v4.7.1...v4.7.2) (2020-09-10) 51 | 52 | ### Bug Fixes 53 | 54 | - **#49:** 增加强制换行属性 ([fbbb9a5](https://github.com/dream2023/f-render/commit/fbbb9a5423ebd6d067e42f4e4de66e949e468065)), closes [#49](https://github.com/dream2023/f-render/issues/49) 55 | - form-props 和 form-item-common 增加 default ([b16c006](https://github.com/dream2023/f-render/commit/b16c006b45c176cce4fbe060a1159d5968c40118)) 56 | - layout 会缩小 ([302bb06](https://github.com/dream2023/f-render/commit/302bb06549b8df2f2e12add2a45b43610e4fced3)) 57 | 58 | ### [4.7.1](https://github.com/dream2023/f-render/compare/v4.7.0...v4.7.1) (2020-09-05) 59 | 60 | ### Bug Fixes 61 | 62 | - **#62:** 校检更新问题 ([1e7a3cc](https://github.com/dream2023/f-render/commit/1e7a3cc474d288244935f2ab76bfdfbdff7b1a35)), closes [#62](https://github.com/dream2023/f-render/issues/62) 63 | 64 | ## [4.7.0](https://github.com/dream2023/f-render/compare/v4.6.1...v4.7.0) (2020-09-02) 65 | 66 | ### Features 67 | 68 | - 增加 remoteMethod ([f19e705](https://github.com/dream2023/f-render/commit/f19e70583badf51f98a0871063c8c785257069f2)) 69 | 70 | ### Bug Fixes 71 | 72 | - 修复 BUG & 升级依赖 ([3134a5c](https://github.com/dream2023/f-render/commit/3134a5cc0608abe4b838dc94067564b79701e872)) 73 | 74 | ### [4.6.2](https://github.com/dream2023/f-render/compare/v4.6.1...v4.6.2) (2020-09-01) 75 | 76 | ### Bug Fixes 77 | 78 | - 修复 BUG & 升级依赖 ([3134a5c](https://github.com/dream2023/f-render/commit/3134a5cc0608abe4b838dc94067564b79701e872)) 79 | 80 | ### [4.6.1](https://github.com/dream2023/f-render/compare/v4.6.0...v4.6.1) (2020-08-28) 81 | 82 | ### Bug Fixes 83 | 84 | - 修复 options BUG ([0079791](https://github.com/dream2023/f-render/commit/00797910c57c669d6e2163d7317894e01fb28850)) 85 | 86 | ## [4.6.0](https://github.com/dream2023/f-render/compare/v4.5.0...v4.6.0) (2020-08-28) 87 | 88 | ### Features 89 | 90 | - 增加点击添加功能 ([f8c53d9](https://github.com/dream2023/f-render/commit/f8c53d9396e22dea7611cf3d13398bcbc4fac897)) 91 | - 增加 order 属性, 避免回显时不一致 ([d81c4f4](https://github.com/dream2023/f-render/commit/d81c4f43050112bfd47f458b8fb160993a94b4b2)) 92 | 93 | ### Bug Fixes 94 | 95 | - 处理 options 相关问题 ([ffef651](https://github.com/dream2023/f-render/commit/ffef651e571037b501ce801be9c47598037e1801)) 96 | 97 | ## [4.5.0](https://github.com/dream2023/f-render/compare/v4.4.0...v4.5.0) (2020-08-26) 98 | 99 | ### Features 100 | 101 | - 优化体积 ([9618c00](https://github.com/dream2023/f-render/commit/9618c0017eb5bfe7a0526d07a0ae7b5c4660960e)) 102 | 103 | ### Bug Fixes 104 | 105 | - 修复 data-editor types 的拼写错误 ([743dc16](https://github.com/dream2023/f-render/commit/743dc16c45786104d7e5ac52c0771ae75e320bc3)) 106 | - 升级依赖 & 抽离全局组件 ([333e175](https://github.com/dream2023/f-render/commit/333e175908ddf1c5339aca15dabc615d224cf247)) 107 | - 增加配置 ([6d337f5](https://github.com/dream2023/f-render/commit/6d337f5494dc8281a59678aec01248e2785081e1)) 108 | 109 | ## [4.4.0](https://github.com/dream2023/f-render/compare/v4.3.2...v4.4.0) (2020-08-25) 110 | 111 | ### Features 112 | 113 | - 切换属性 Tab 时,滚动到顶部 ([00450a5](https://github.com/dream2023/f-render/commit/00450a59302134e0d3fa258434d501c1153ee8e3)) 114 | 115 | ### [4.3.2](https://github.com/dream2023/f-render/compare/v4.3.1...v4.3.2) (2020-08-24) 116 | 117 | ### [4.3.1](https://github.com/dream2023/f-render/compare/v4.3.0...v4.3.1) (2020-08-24) 118 | 119 | ## [4.3.0](https://github.com/dream2023/f-render/compare/v3.1.0...v4.3.0) (2020-08-24) 120 | 121 | ### Features 122 | 123 | - 增加 Dockerfile ([240c669](https://github.com/dream2023/f-render/commit/240c66998418bd0068e8c78e1b0b945245a4e37c)) 124 | - 增加 time-picker 配置 ([1f043ee](https://github.com/dream2023/f-render/commit/1f043eec6d86709cedcbed33132abd4e08239051)) 125 | - 正则表达式校检不正确 ([31ca5c2](https://github.com/dream2023/f-render/commit/31ca5c282d57692a5c89b90cef0a46d4666b9d2d)) 126 | 127 | ### Bug Fixes 128 | 129 | - 修复若干问题 ([#58](https://github.com/dream2023/f-render/issues/58)) ([60c6815](https://github.com/dream2023/f-render/commit/60c681569d842ff0027e0db75df9688441b2d7aa)), closes [#57](https://github.com/dream2023/f-render/issues/57) [#56](https://github.com/dream2023/f-render/issues/56) [#55](https://github.com/dream2023/f-render/issues/55) 130 | - 修复若干 BUG ([b8eea65](https://github.com/dream2023/f-render/commit/b8eea650a0f4b6a6335b392fe2d314d61f814e2b)) 131 | - 修复 BUG & 增加联动属性 ([27377b4](https://github.com/dream2023/f-render/commit/27377b47a483c4c4d83fe12ea15fcf153d09858e)) 132 | - 依赖报错 ([8eca6b5](https://github.com/dream2023/f-render/commit/8eca6b50fad64d99ed61e312ba72ce3268e9382d)) 133 | - 预览清空原数据 ([db60207](https://github.com/dream2023/f-render/commit/db602073f5fc93c67b6d31b13a39aa48888c76e9)) 134 | - labelWidth 计算不正确 ([7b35ce1](https://github.com/dream2023/f-render/commit/7b35ce1e67a2b908d2d3a4b4d3dc3a436e69a97e)) 135 | 136 | ## [4.2.0](https://github.com/dream2023/f-render/compare/v3.1.0...v4.2.0) (2020-08-24) 137 | 138 | ### Features 139 | 140 | - 增加 Dockerfile ([240c669](https://github.com/dream2023/f-render/commit/240c66998418bd0068e8c78e1b0b945245a4e37c)) 141 | - 增加 time-picker 配置 ([1f043ee](https://github.com/dream2023/f-render/commit/1f043eec6d86709cedcbed33132abd4e08239051)) 142 | - 正则表达式校检不正确 ([31ca5c2](https://github.com/dream2023/f-render/commit/31ca5c282d57692a5c89b90cef0a46d4666b9d2d)) 143 | 144 | ### Bug Fixes 145 | 146 | - 修复若干问题 ([#58](https://github.com/dream2023/f-render/issues/58)) ([60c6815](https://github.com/dream2023/f-render/commit/60c681569d842ff0027e0db75df9688441b2d7aa)), closes [#57](https://github.com/dream2023/f-render/issues/57) [#56](https://github.com/dream2023/f-render/issues/56) [#55](https://github.com/dream2023/f-render/issues/55) 147 | - 修复 BUG & 增加联动属性 ([27377b4](https://github.com/dream2023/f-render/commit/27377b47a483c4c4d83fe12ea15fcf153d09858e)) 148 | - 依赖报错 ([8eca6b5](https://github.com/dream2023/f-render/commit/8eca6b50fad64d99ed61e312ba72ce3268e9382d)) 149 | - 预览清空原数据 ([db60207](https://github.com/dream2023/f-render/commit/db602073f5fc93c67b6d31b13a39aa48888c76e9)) 150 | - labelWidth 计算不正确 ([7b35ce1](https://github.com/dream2023/f-render/commit/7b35ce1e67a2b908d2d3a4b4d3dc3a436e69a97e)) 151 | -------------------------------------------------------------------------------- /src/f-render.vue: -------------------------------------------------------------------------------- 1 | 40 | 41 | 319 | 320 | 389 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # f-render | 基于 ElementUI 的表单设计器 2 | 3 | [![MIT](https://img.shields.io/github/license/dream2023/f-render)](https://github.com/dream2023/f-render) 4 | ![npm bundle size](https://img.shields.io/bundlephobia/minzip/f-render) 5 | ![npm](https://img.shields.io/npm/dt/f-render) 6 | [![Netlify Status](https://api.netlify.com/api/v1/badges/4c2ddffb-26b2-4e64-8b22-25678db57483/deploy-status)](https://app.netlify.com/sites/f-render/deploys) 7 | ![gitub pages](https://github.com/dream2023/f-render/workflows/gitub%20pages/badge.svg) 8 | [![Star on GitHub](https://img.shields.io/github/stars/dream2023/f-render.svg?style=social)](https://github.com/dream2023/f-render/stargazers) 9 | 10 | 11 | 12 | 13 | 14 | - [交流群](#%E4%BA%A4%E6%B5%81%E7%BE%A4) 15 | - [介绍](#%E4%BB%8B%E7%BB%8D) 16 | - [注意](#%E6%B3%A8%E6%84%8F) 17 | - [特性](#%E7%89%B9%E6%80%A7) 18 | - [Demo](#demo) 19 | - [教程](#%E6%95%99%E7%A8%8B) 20 | - [1 分钟快速接入](#1-%E5%88%86%E9%92%9F%E5%BF%AB%E9%80%9F%E6%8E%A5%E5%85%A5) 21 | - [第 1 步:安装](#%E7%AC%AC-1-%E6%AD%A5%E5%AE%89%E8%A3%85) 22 | - [第 2 步:注册](#%E7%AC%AC-2-%E6%AD%A5%E6%B3%A8%E5%86%8C) 23 | - [第 3 步:使用](#%E7%AC%AC-3-%E6%AD%A5%E4%BD%BF%E7%94%A8) 24 | - [用户模式](#%E7%94%A8%E6%88%B7%E6%A8%A1%E5%BC%8F) 25 | - [基于 f-render 的配置](#%E5%9F%BA%E4%BA%8E-f-render-%E7%9A%84%E9%85%8D%E7%BD%AE) 26 | - [基于 vue-ele-form 的配置](#%E5%9F%BA%E4%BA%8E-vue-ele-form-%E7%9A%84%E9%85%8D%E7%BD%AE) 27 | - [定制化](#%E5%AE%9A%E5%88%B6%E5%8C%96) 28 | - [新增官方扩展组件(以富文本扩展为例)](#%E6%96%B0%E5%A2%9E%E5%AE%98%E6%96%B9%E6%89%A9%E5%B1%95%E7%BB%84%E4%BB%B6%E4%BB%A5%E5%AF%8C%E6%96%87%E6%9C%AC%E6%89%A9%E5%B1%95%E4%B8%BA%E4%BE%8B) 29 | - [安装组件](#%E5%AE%89%E8%A3%85%E7%BB%84%E4%BB%B6) 30 | - [注册组件](#%E6%B3%A8%E5%86%8C%E7%BB%84%E4%BB%B6) 31 | - [配置属性](#%E9%85%8D%E7%BD%AE%E5%B1%9E%E6%80%A7) 32 | - [新增自定义组件](#%E6%96%B0%E5%A2%9E%E8%87%AA%E5%AE%9A%E4%B9%89%E7%BB%84%E4%BB%B6) 33 | - [创建组件并全局注册](#%E5%88%9B%E5%BB%BA%E7%BB%84%E4%BB%B6%E5%B9%B6%E5%85%A8%E5%B1%80%E6%B3%A8%E5%86%8C) 34 | - [书写配置](#%E4%B9%A6%E5%86%99%E9%85%8D%E7%BD%AE) 35 | - [合并配置并传入](#%E5%90%88%E5%B9%B6%E9%85%8D%E7%BD%AE%E5%B9%B6%E4%BC%A0%E5%85%A5) 36 | - [定制化原组件配置 & 表单配置](#%E5%AE%9A%E5%88%B6%E5%8C%96%E5%8E%9F%E7%BB%84%E4%BB%B6%E9%85%8D%E7%BD%AE--%E8%A1%A8%E5%8D%95%E9%85%8D%E7%BD%AE) 37 | - [定制化右侧 Tabs](#%E5%AE%9A%E5%88%B6%E5%8C%96%E5%8F%B3%E4%BE%A7-tabs) 38 | - [样式定制化](#%E6%A0%B7%E5%BC%8F%E5%AE%9A%E5%88%B6%E5%8C%96) 39 | - [二次开发](#%E4%BA%8C%E6%AC%A1%E5%BC%80%E5%8F%91) 40 | - [f-render 问答集锦](#f-render-%E9%97%AE%E7%AD%94%E9%9B%86%E9%94%A6) 41 | - [Props 说明](#props-%E8%AF%B4%E6%98%8E) 42 | - [插槽](#%E6%8F%92%E6%A7%BD) 43 | - [生态](#%E7%94%9F%E6%80%81) 44 | - [特别感谢赞助者](#%E7%89%B9%E5%88%AB%E6%84%9F%E8%B0%A2%E8%B5%9E%E5%8A%A9%E8%80%85) 45 | - [Contributors ✨](#contributors-) 46 | 47 | 48 | 49 | ## 介绍 50 | 51 | f-render 是基于 [vue-ele-form](https://github.com/dream2023/vue-ele-form) 开发的可视化表单设计工具, 适用于 各种流程引擎和动态表单项目,大大节省你的开发时间; 52 | 53 | [![f-render 演示图](./demo.webp)](https://dream2023.gitee.io/f-render/) 54 | 55 | ## 注意 56 | 57 | 注意,此设计器不是独立存在的,是依托于 [vue-ele-form](https://github.com/dream2023/vue-ele-form),在使用前请务必阅读 [vue-ele-form 的文档](https://www.yuque.com/chaojie-vjiel/vbwzgu/xl46cd)。 58 | 59 | ## 特性 60 | 61 | - 组件方式:以组件方式接入,1 分钟轻松接入; 62 | - 体积小:Gzip 压缩后 `100k` 左右; 63 | - 易扩展:可以在`不更改源码`的情况下增删改属性、组件; 64 | 65 | ## Demo 66 | 67 | [https://dream2023.gitee.io/f-render/](https://dream2023.gitee.io/f-render/) 68 | 69 | ## 教程 70 | 71 | 虽然 f-render 可以做到在不更改源码的情况下实现大量的定制化,但是依然有不少人希望能够根据公司的需求进行二次开发。 72 | 73 | 所以我推出了一个从 0 实现整个项目的 [教程](https://www.lanqiao.cn/courses/2848),如果感兴趣 f-render 的实现过程和思考,可以点击 [从 0 实现可视化表单组件](https://www.lanqiao.cn/courses/2848) 进行学习。 74 | 75 | ## 1 分钟快速接入 76 | 77 | #### 第 1 步:安装 78 | 79 | ```bash 80 | yarn add element-ui # npm install element-ui -S 81 | yarn add vue-ele-form # npm install vue-ele-form -S 82 | yarn add f-render # npm install f-render -S 83 | ``` 84 | 85 | #### 第 2 步:注册 86 | 87 | ```js 88 | // vue-ele-form 的注册可参考:https://www.yuque.com/chaojie-vjiel/vbwzgu/xl46cd 89 | import EleForm from "vue-ele-form"; 90 | import FRender from "f-render"; 91 | import ElementUI from "element-ui"; 92 | import "element-ui/lib/theme-chalk/index.css"; 93 | 94 | Vue.use(ElementUI); 95 | Vue.use(EleForm); 96 | Vue.component("f-render", FRender); 97 | ``` 98 | 99 | #### 第 3 步:使用 100 | 101 | ```html 102 | 110 | 111 | 136 | ``` 137 | 138 | ## 用户模式 139 | 140 | 我们把动态表单分为两个阶段: 141 | 142 | - 首先是设计阶段:通过拖拽设计表单; 143 | - 然后是用户阶段:将设计好的表单以纯表单的形式让用户填写。 144 | 145 | 我们别分称这两个阶段的表单为设计模式和用户模式。设计模式的表单配置我们已经讲了,下面看用户模式下的表单配置: 146 | 147 | #### 基于 f-render 的配置 148 | 149 | 通过属性 `pure`, 可以直接做为表单使用,其数据提交方式同 `vue-ele-form` 一样,具体可查看[文档](https://www.yuque.com/chaojie-vjiel/vbwzgu/zbu9mn)。 150 | 151 | ```html 152 | 161 | 162 | 190 | ``` 191 | 192 | #### 基于 vue-ele-form 的配置 193 | 194 | 如果你的可视化设计和表单使用,不再一个系统,可以直接使用 `vue-ele-form`,不必安装 `f-render`,具体如下: 195 | 196 | ```html 197 | 206 | 207 | 238 | ``` 239 | 240 | ## 定制化 241 | 242 | ### 新增官方扩展组件(以富文本扩展为例) 243 | 244 | #### 安装组件 245 | 246 | ```bash 247 | yarn add vue-ele-form-quill-editor 248 | ``` 249 | 250 | #### 注册组件 251 | 252 | ```js 253 | Vue.component("quill-editor", EleFormQuillEditor); 254 | ``` 255 | 256 | #### 配置属性 257 | 258 | ```html 259 | 263 | 264 | 282 | ``` 283 | 284 | ### 新增自定义组件 285 | 286 | #### 创建组件并全局注册 287 | 288 | 需要根据 vue-ele-form 文档[创建自定义组件](https://www.yuque.com/chaojie-vjiel/vbwzgu/ugumna),并注册。 289 | 290 | #### 书写配置 291 | 292 | 你可以参考[源码中的配置]('./src/fixtures/comps.js'),一下是范例和属性说明: 293 | 294 | ```js 295 | // custom-url.js 296 | export default { 297 | // 假如这个组件叫 url(必填) 298 | type: "custom-url", 299 | // 默认标签名(必填) 300 | label: "URL", 301 | // 用于排序,值越小,越靠前 302 | sort: 1, 303 | // 属性配置 304 | config: { 305 | // 属性配置说明地址(可省略) 306 | url: "https://www.xxx.com", 307 | // 组件属性配置(不知道啥是组件属性,可以看一下界面右侧) 308 | attrs: { 309 | // config 配置 参考 FormDesc: 310 | // https://www.yuque.com/chaojie-vjiel/vbwzgu/iw5dzf#KOPkD 311 | config: { 312 | // max 为属性名 313 | max: { 314 | type: "number", 315 | label: "最大输入长度" 316 | }, 317 | name: { 318 | type: "input", 319 | label: "原生 name", 320 | // 必填 321 | required: true 322 | } 323 | // .... 324 | }, 325 | // 默认值,如果在配置文件里设置了,则每个组件都会携带 326 | data: { 327 | name: "url" 328 | } 329 | }, 330 | // 表单项配置,是 FormDesc 中非 attrs 的其它配置, 331 | // 具体可看:https://www.yuque.com/chaojie-vjiel/vbwzgu/iw5dzf#hl4pm 332 | common: { 333 | config: { 334 | // 默认值 335 | default: { 336 | type: "input", 337 | label: "默认值" 338 | } 339 | }, 340 | data: {} 341 | } 342 | } 343 | }; 344 | ``` 345 | 346 | #### 合并配置并传入 347 | 348 | ```html 349 | 353 | 354 | 365 | ``` 366 | 367 | ### 定制化原组件配置 & 表单配置 368 | 369 | - 组件配置目录:`f-render/src/fixtures/comps.js` 370 | - 表单配置目录:`f-render/src/fixtures/form-props.js` 371 | - 表单项通用属性配置:`f-render/src/fixtures/form-item-common.js` 372 | - 扩展组件目录:`f-render/src/fixtures/extends/[扩展组件名].js` 373 | 374 | 如果你想修改组件属性或者表单的属性,减少或者增加组件,可以将上述文件`拷贝到自己的项目`目录,参考上述配置说明,进行更改,并传入即可: 375 | 376 | ```html 377 | 378 | 379 | 380 | 385 | ``` 386 | 387 | 具体而言,如果想让每个 `input` 组件都携带 `clearable: true` 的属性,我们可以这样操作: 388 | 389 | ```html 390 | 395 | 396 | 411 | ``` 412 | 413 | ### 定制化右侧 Tabs 414 | 415 | 我们可以通过 `isShowRight` 属性来控制右侧面板是否显示,通过 `rightTabs` 来定制具体显示的面板名称,具体如下: 416 | 417 | ```html 418 | 422 | 423 | 437 | ``` 438 | 439 | ### 样式定制化 440 | 441 | 直接进行样式覆盖即可,注意不要加 `scoped`,否则覆盖不成功 442 | 443 | ## 二次开发 444 | 445 | 如果仅通过`属性`和`样式`定制化已无法满足的你和你产品经理的要求,那就需要进行定制化开发,我个人觉得代码整体还是非常简单的,你可以 `clone` 代码或者下载后(建议用[gitee](https://gitee.com/dream2023/f-render)),进行相应的更改,更改后有两种处理方式: 446 | 447 | - 直接放到项目目录里,并将安装 `dependencies` 的依赖复制到项目,进行开发即可; 448 | - 直接开发,然后发布到公司[私服](https://www.npmjs.com/package/verdaccio),如果是开源,则可以发到 GitHub 或者 gitee,然后安装自己的即可 449 | 450 | 具体的细节,开头提的[教程](https://www.lanqiao.cn/courses/2848)里会有详细的过程,希望大家可以支持一下。 451 | 452 | ## f-render 问答集锦 453 | 454 | - [1、f-render 不能做什么?](https://www.yuque.com/chaojie-vjiel/vbwzgu/adz8q8#0nlfc) 455 | - [2、怎么实现 options URL 配置?](https://www.yuque.com/chaojie-vjiel/vbwzgu/adz8q8#gvS8c) 456 | 457 | ## Props 说明 458 | 459 | ```js 460 | props: { 461 | // 表单内容 462 | config: { 463 | type: [Object, String], 464 | required: true 465 | }, 466 | // 设计器整体高度 467 | height: { 468 | type: [String, Number], 469 | default: "400px" 470 | }, 471 | // 保存格式 472 | saveFormat: { 473 | type: String, 474 | default: "string", 475 | validator(val) { 476 | return ["object", "string"].includes(val); 477 | } 478 | }, 479 | // 是否纯净(用于显示表单) 480 | pure: Boolean, 481 | // 表单配置 482 | formProps: { 483 | type: Object, 484 | default: () => formProps 485 | }, 486 | // 表单项配置 487 | formItemCommon: { 488 | type: Object, 489 | default: () => formItemCommonDefault 490 | }, 491 | // 组件列表 492 | comps: { 493 | type: Array, 494 | default: () => comps 495 | }, 496 | // 操作配置 497 | operations: { 498 | type: Array, 499 | default: () => ["preview", "data", "code", "batch", "clear", "save"] 500 | }, 501 | // 是否显示右侧 502 | isShowRight: { 503 | type: Boolean, 504 | default: true 505 | }, 506 | // 右侧属性面板 Tabs 507 | rightTabs: { 508 | type: Array, 509 | default: () => [ 510 | { label: "表单项属性配置", name: "form-item-common" }, 511 | { label: "组件属性配置", name: "form-item-attrs" }, 512 | { label: "表单配置", name: "form-props" } 513 | ] 514 | }, 515 | // 是否在加载 516 | loading: Boolean, 517 | 518 | // 表单相关(pure 为 true 时), 同 vue-ele-form 519 | // https://www.yuque.com/chaojie-vjiel/vbwzgu/dyw8a7 520 | requestFn: Function, 521 | isLoading: Boolean, 522 | formError: Object, 523 | // .... 524 | }, 525 | ``` 526 | 527 | ## 插槽 528 | 529 | - left:左侧组件列表 530 | - main: 中间区域 531 | - main-header: 头部操作区 532 | - main-content: 表单设计区 533 | - right: 右侧属性配置区 534 | 535 | 举例: 536 | 537 | ```html 538 | 550 | ``` 551 | 552 | 其中 `frender` 数据是 `f-render` 组件数据的集合,具体都有哪些数据,可以参考[源码](https://gitee.com/dream2023/f-render/blob/master/src/f-render.vue),其它插槽均有此参数。 553 | 554 | ## 生态 555 | 556 | | Project | Status | Description | 557 | | ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------ | 558 | | [vue-ele-form](https://github.com/dream2023/vue-ele-form) | [![npm](https://img.shields.io/npm/v/vue-ele-form)](https://github.com/dream2023/vue-ele-form) | 接基于 ElementUI 的数据驱动表单 | 559 | | [f-render](https://github.com/dream2023/f-render) | [![npm](https://img.shields.io/npm/v/f-render)](https://github.com/dream2023/f-render) | 专为 vue-ele-form 开发的可视化表单设计工具 | 560 | | [vue-ele-form-json-editor](https://github.com/dream2023/vue-ele-form-json-editor) | [![npm](https://img.shields.io/npm/v/vue-ele-form-json-editor)](https://github.com/dream2023/vue-ele-form-json-editor) | JSON 编辑器(vue-ele-form 扩展) | 561 | | [vue-ele-form-upload-file](https://github.com/dream2023/vue-ele-form-upload-file) | [![npm](https://img.shields.io/npm/v/vue-ele-form-upload-file)](https://github.com/dream2023/vue-ele-form-upload-file) | upload 文件上传组件(vue-ele-form 扩展) | 562 | | [vue-ele-form-image-uploader](https://github.com/dream2023/vue-ele-form-image-uploader) | [![npm](https://img.shields.io/npm/v/vue-ele-form-image-uploader)](https://github.com/dream2023/vue-ele-form-image-uploader) | 上传图片增强组件(vue-ele-form 扩展) | 563 | | [vue-ele-form-tree-select](https://github.com/dream2023/vue-ele-form-tree-select) | [![npm](https://img.shields.io/npm/v/vue-ele-form-tree-select)](https://github.com/dream2023/vue-ele-form-tree-select) | 树形选择框组件(vue-ele-form 扩展) | 564 | | [vue-ele-form-table-editor](https://github.com/dream2023/vue-ele-form-table-editor) | [![npm](https://img.shields.io/npm/v/vue-ele-form-table-editor)](https://github.com/dream2023/vue-ele-form-table-editor) | 表格编辑器(vue-ele-form 扩展) | 565 | | [vue-ele-form-dynamic](https://github.com/dream2023/vue-ele-form-dynamic) | [![npm](https://img.shields.io/npm/v/vue-ele-form-dynamic)](https://github.com/dream2023/vue-ele-form-dynamic) | 动态表单(vue-ele-form 扩展) | 566 | | [vue-ele-form-video-uploader](https://github.com/dream2023/vue-ele-form-video-uploader) | [![npm](https://img.shields.io/npm/v/vue-ele-form-video-uploader)](https://github.com/dream2023/vue-ele-form-video-uploader) | 上传视频增强组件(vue-ele-form 扩展) | 567 | | [vue-ele-form-quill-editor](https://github.com/dream2023/vue-ele-form-quill-editor) | [![npm](https://img.shields.io/npm/v/vue-ele-form-quill-editor)](https://github.com/dream2023/vue-ele-form-quill-editor) | 富文本编辑器(vue-ele-form 扩展) | 568 | | [vue-ele-form-markdown-editor](https://github.com/dream2023/vue-ele-form-markdown-editor) | [![npm](https://img.shields.io/npm/v/vue-ele-form-markdown-editor)](https://github.com/dream2023/vue-ele-form-markdown-editor) | markdown 编辑器(vue-ele-form 扩展) | 569 | | [vue-ele-form-bmap](https://github.com/dream2023/vue-ele-form-bmap) | [![npm](https://img.shields.io/npm/v/vue-ele-form-bmap)](https://github.com/dream2023/vue-ele-form-bmap) | 百度地图组件(vue-ele-form 扩展) | 570 | | [vue-ele-form-codemirror](https://github.com/dream2023/vue-ele-form-codemirror) | [![npm](https://img.shields.io/npm/v/vue-ele-form-codemirror)](https://github.com/dream2023/vue-ele-form-codemirror) | 代码编辑器(vue-ele-form-gallery 扩展) | 571 | | [vue-ele-form-gallery](https://github.com/dream2023/vue-ele-form-gallery) | [![npm](https://img.shields.io/npm/v/vue-ele-form-gallery)](https://github.com/dream2023/vue-ele-form-gallery) | 图片/视频展示组件(vue-ele-form 扩展) | 572 | | [vue-ele-form-data-editor](https://github.com/dream2023/vue-ele-form-data-editor) | [![npm](https://img.shields.io/npm/v/vue-ele-form-data-editor)](https://github.com/dream2023/vue-ele-form-data-editor) | 轻量级数据编辑器(vue-ele-form 扩展) | 573 | 574 |

特别感谢赞助者

575 | 576 | 577 | 578 | 579 | 585 | 591 | 597 | 603 | 609 | 615 | 616 | 617 |
580 | 581 | 582 |
优客服
583 |
584 |
586 | 587 | 588 |
圣捷远创
589 |
590 |
592 | 593 | 594 |
damonnie
595 |
596 |
598 | 599 | 600 |
xzusoft
601 |
602 |
604 | 605 | 606 |
seeenter
607 |
608 |
610 | 611 | 612 |
高亢
613 |
614 |
618 | 619 | 620 | > 如果您觉得对您有所帮助, 可以请作者喝一杯咖啡, 让开源走的更远, 点击进入[码云赞赏](https://gitee.com/dream2023/f-render)一下, 并加入下面交流群, 将链接发送给我 621 | 622 | ## Contributors ✨ 623 | 624 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 |

张超杰

📖 💻 🤔

Wisen

💻

IWANABETHATGUY

💻
636 | 637 | 638 | 639 | 640 | 641 | 642 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! 643 | --------------------------------------------------------------------------------