From 879cd36bafaf108225a79f0455cb54767d962fd8 Mon Sep 17 00:00:00 2001
From: robin <1032740078@qq.com>
Date: Thu, 1 Dec 2022 21:48:35 +0800
Subject: [PATCH] 1
---
.cz-config.js | 32 ++
.gitignore | 68 +++
LICENSE | 21 +
README.md | 141 ++++++
babel.config.js | 4 +
examples/App.vue | 303 +++++++++++
examples/index.html | 11 +
examples/main.js | 18 +
package.json | 135 +++++
src/components/DragBox.vue | 33 ++
src/components/DragTool.vue | 136 +++++
src/components/FcDesigner.vue | 861 ++++++++++++++++++++++++++++++++
src/components/Fetch.vue | 162 ++++++
src/components/IconRefresh.vue | 14 +
src/components/Required.vue | 64 +++
src/components/Struct.vue | 127 +++++
src/components/TableOptions.vue | 75 +++
src/components/Validate.vue | 229 +++++++++
src/config/base/field.js | 84 ++++
src/config/base/form.js | 55 ++
src/config/base/validate.js | 9 +
src/config/menu.js | 51 ++
src/config/rule/alert.js | 45 ++
src/config/rule/button.js | 54 ++
src/config/rule/cascader.js | 180 +++++++
src/config/rule/checkbox.js | 45 ++
src/config/rule/col.js | 23 +
src/config/rule/color.js | 36 ++
src/config/rule/date.js | 75 +++
src/config/rule/divider.js | 37 ++
src/config/rule/drawer.js | 27 +
src/config/rule/editor.js | 23 +
src/config/rule/image.ts | 57 +++
src/config/rule/index.js | 61 +++
src/config/rule/input.js | 65 +++
src/config/rule/number.js | 41 ++
src/config/rule/radio.js | 42 ++
src/config/rule/rate.js | 44 ++
src/config/rule/row.js | 41 ++
src/config/rule/select.js | 62 +++
src/config/rule/slider.js | 44 ++
src/config/rule/space.js | 41 ++
src/config/rule/span.js | 33 ++
src/config/rule/switch.js | 39 ++
src/config/rule/tab.js | 36 ++
src/config/rule/tabPane.js | 29 ++
src/config/rule/time.js | 57 +++
src/config/rule/transfer.js | 84 ++++
src/config/rule/tree.js | 100 ++++
src/config/rule/upload.js | 64 +++
src/index.js | 56 +++
src/style/fonts/fc-icons.woff | Bin 0 -> 5448 bytes
src/style/fonts/iconfont.css | 17 +
src/style/fonts/iconfont.ttf | Bin 0 -> 1772 bytes
src/style/index.css | 138 +++++
src/utils/form.js | 9 +
src/utils/index.js | 132 +++++
tools/cli/run.ts | 61 +++
tools/lib/build.ts | 163 ++++++
tools/lib/components.ts | 73 +++
tools/lib/packages.ts | 88 ++++
tools/lib/paths.ts | 14 +
tools/lib/utils.ts | 140 ++++++
tools/rollup/plugin/index.ts | 69 +++
tsconfig.json | 21 +
types/index.d.ts | 31 ++
vite.config.build.js | 85 ++++
vite.config.preview.js | 22 +
vue.config.js | 28 ++
69 files changed, 5265 insertions(+)
create mode 100644 .cz-config.js
create mode 100755 .gitignore
create mode 100644 LICENSE
create mode 100644 README.md
create mode 100644 babel.config.js
create mode 100644 examples/App.vue
create mode 100644 examples/index.html
create mode 100644 examples/main.js
create mode 100644 package.json
create mode 100644 src/components/DragBox.vue
create mode 100644 src/components/DragTool.vue
create mode 100644 src/components/FcDesigner.vue
create mode 100644 src/components/Fetch.vue
create mode 100644 src/components/IconRefresh.vue
create mode 100644 src/components/Required.vue
create mode 100644 src/components/Struct.vue
create mode 100644 src/components/TableOptions.vue
create mode 100644 src/components/Validate.vue
create mode 100644 src/config/base/field.js
create mode 100644 src/config/base/form.js
create mode 100644 src/config/base/validate.js
create mode 100644 src/config/menu.js
create mode 100644 src/config/rule/alert.js
create mode 100644 src/config/rule/button.js
create mode 100644 src/config/rule/cascader.js
create mode 100644 src/config/rule/checkbox.js
create mode 100644 src/config/rule/col.js
create mode 100644 src/config/rule/color.js
create mode 100644 src/config/rule/date.js
create mode 100644 src/config/rule/divider.js
create mode 100644 src/config/rule/drawer.js
create mode 100644 src/config/rule/editor.js
create mode 100644 src/config/rule/image.ts
create mode 100644 src/config/rule/index.js
create mode 100644 src/config/rule/input.js
create mode 100644 src/config/rule/number.js
create mode 100644 src/config/rule/radio.js
create mode 100644 src/config/rule/rate.js
create mode 100644 src/config/rule/row.js
create mode 100644 src/config/rule/select.js
create mode 100644 src/config/rule/slider.js
create mode 100644 src/config/rule/space.js
create mode 100644 src/config/rule/span.js
create mode 100644 src/config/rule/switch.js
create mode 100644 src/config/rule/tab.js
create mode 100644 src/config/rule/tabPane.js
create mode 100644 src/config/rule/time.js
create mode 100644 src/config/rule/transfer.js
create mode 100644 src/config/rule/tree.js
create mode 100644 src/config/rule/upload.js
create mode 100644 src/index.js
create mode 100644 src/style/fonts/fc-icons.woff
create mode 100644 src/style/fonts/iconfont.css
create mode 100644 src/style/fonts/iconfont.ttf
create mode 100644 src/style/index.css
create mode 100644 src/utils/form.js
create mode 100644 src/utils/index.js
create mode 100644 tools/cli/run.ts
create mode 100644 tools/lib/build.ts
create mode 100644 tools/lib/components.ts
create mode 100644 tools/lib/packages.ts
create mode 100644 tools/lib/paths.ts
create mode 100644 tools/lib/utils.ts
create mode 100644 tools/rollup/plugin/index.ts
create mode 100644 tsconfig.json
create mode 100644 types/index.d.ts
create mode 100644 vite.config.build.js
create mode 100644 vite.config.preview.js
create mode 100644 vue.config.js
diff --git a/.cz-config.js b/.cz-config.js
new file mode 100644
index 0000000..a8d7c28
--- /dev/null
+++ b/.cz-config.js
@@ -0,0 +1,32 @@
+module.exports = {
+ types: [
+ {value: 'feat', name: 'feat: 新功能'},
+ {value: 'fix', name: 'fix: 修复'},
+ {value: 'docs', name: 'docs: 文档变更'},
+ {value: 'style', name: 'style: 代码格式(不影响代码运行的变动)'},
+ {value: 'cli', name: 'cli: 脚手架优化(不影响代码运行的变动)'},
+ {value: 'refactor', name: 'refactor: 重构(既不是增加feature,也不是修复bug)'},
+ {value: 'perf', name: 'perf: 性能优化'},
+ {value: 'test', name: 'test: 增加测试'},
+ {value: 'chore', name: 'chore: 构建过程或辅助工具的变动'},
+ {value: 'revert', name: 'revert: 回退'},
+ {value: 'build', name: 'build: 打包'}
+ ],
+ // override the messages, defaults are as follows
+ messages: {
+ type: '请选择提交类型:',
+ scope: '请输入文件修改范围(可选):',
+ // used if allowCustomScopes is true
+ customScope: '请输入修改范围(可选):',
+ subject: '请简要描述提交(必填):',
+ body: '请输入详细描述(可选,待优化去除,跳过即可):',
+ // breaking: 'List any BREAKING CHANGES (optional):\n',
+ footer: '请输入要关闭的issue(待优化去除,跳过即可):',
+ confirmCommit: '确认使用以上信息提交?(y/n/e/h)'
+ },
+ allowCustomScopes: true,
+ // allowBreakingChanges: ['feat', 'fix'],
+ skipQuestions: ['body', 'footer'],
+ // limit subject length, commitlint默认是72
+ subjectLimit: 72
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100755
index 0000000..10e41f2
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,68 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+stats.html
+
+# Runtime data
+pids
+*.pid
+*.seed
+*.pid.lock
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+
+# nyc test coverage
+.nyc_output
+
+# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# Bower dependency directory (https://bower.io/)
+bower_components
+
+# node-waf configuration
+.lock-wscript
+
+# Compiled binary addons (https://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directories
+node_modules/
+jspm_packages/
+
+# TypeScript v1 declaration files
+typings/
+
+# Optional npm cache directory
+.npm
+
+# Optional eslint cache
+.eslintcache
+
+# Optional REPL history
+.node_repl_history
+
+# Output of 'npm pack'
+*.tgz
+
+# Yarn Integrity file
+.yarn-integrity
+
+# dotenv environment variables file
+.env
+
+# next.js build output
+.next
+.idea
+
+# custom
+yarn.lock
+/index.html
+dist
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..210009a
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2022 xaboy
+
+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
new file mode 100644
index 0000000..7c0a77f
--- /dev/null
+++ b/README.md
@@ -0,0 +1,141 @@
+
+
+
+
+
+
+# form-create-designer v3
+
+**这个是 Vue3 版本**
+
+[](https://github.com/xaboy/form-create-designer)
+[](https://github.com/xaboy)
+
+**form-create-designer 是基于 [@form-create/element-ui](https://github.com/xaboy/form-create) vue3版本实现的表单设计器组件。可以通过拖拽的方式快速创建表单,提高开发者对表单的开发效率,节省开发者的时间。**
+
+**[文档](http://designer.form-create.com/guide/) | [在线演示](http://form-create.com/v3/designer?fr=github) | [form-create 文档](http://form-create.com/v3/guide/)**
+
+> 如果对您有帮助,您可以点右上角 "Star" 支持一下 谢谢!本项目还在不断开发完善中,如有任何建议或问题[请在这里提出](https://github.com/xaboy/form-create-designer/issues/new)
+
+> 本项目QQ讨论群[629709230](https://jq.qq.com/?_wv=1027&k=F1FlEFIV)
+
+
+
+
+
+## 引入
+
+**CDN:**
+
+```html
+
+
+
+
+
+```
+
+**NodeJs:**
+
+```shell
+npm install @form-create/designer@next
+```
+
+请自行导入`ElementPlus`并挂载
+
+```js
+import formCreate from '@form-create/element-ui'
+import FcDesigner from '@form-create/designer'
+
+app.use(formCreate)
+app.use(FcDesigner)
+```
+
+## 使用
+
+```html
+
+```
+
+## 组件`props`
+
+- **menu**`MenuList` 重新配置拖拽的组件
+
+- **height**`int|string` 设计器组件高度, 默认`100%`
+
+## 组件方法
+
+- 获取当前生成表单的生成规则
+
+ ```ts
+ type getRule = () => Rule[]
+ ```
+ **示例: `this.$refs.designer.getRule()`**
+
+- 获取当前表单的全局配置
+
+ ```ts
+ type getOption = () => Object
+ ```
+
+- 设置当前生成表单的规则
+
+ ```ts
+ type setRule = (rules: Rule[]) => void;
+ ```
+
+- 设置当前表单的全局配置
+
+ ```ts
+ type setOption = (option: Object) => void;
+ ```
+
+- 增加一组拖拽组件
+
+ ```ts
+ type addMenu = (menu: Menu) => void;
+ ```
+- 删除一组拖拽组件
+
+ ```ts
+ type removeMenu = (name: string) => void;
+ ```
+
+- 批量覆盖插入拖拽组件
+
+ ```ts
+ type setMenuItem = (name: string, items: MenuItem[]) => void;
+ ```
+
+- 插入一个拖拽组件到分组
+
+ ```ts
+ type appendMenuItem = (name:string, item: MenuItem) => void;
+ ```
+
+- 删除一个拖拽组件
+
+ ```ts
+ type removeMenuItem = (item: string | MenuItem) => void;
+ ```
+
+- 新增一个拖拽组件的生成规则
+
+ ```ts
+ type addComponent = (item: DragRule) => void;
+ ```
+> **提示! 内置的三个组件分组`name`分别为: `main`,`aide`,`layout`**
+
+## 捐赠
+
+
+
+## 联系
+
+##### email : xaboy2005@qq.com
+
+## License
+
+[MIT](http://opensource.org/licenses/MIT)
+
+Copyright (c) 2021-present xaboy
diff --git a/babel.config.js b/babel.config.js
new file mode 100644
index 0000000..1a3e147
--- /dev/null
+++ b/babel.config.js
@@ -0,0 +1,4 @@
+module.exports = {
+ 'presets': [['@vue/cli-plugin-babel/preset', {'useBuiltIns': false}]],
+ 'plugins': ['@vue/babel-plugin-jsx']
+}
diff --git a/examples/App.vue b/examples/App.vue
new file mode 100644
index 0000000..f165a3c
--- /dev/null
+++ b/examples/App.vue
@@ -0,0 +1,303 @@
+
+
+
+
+
+
+
+
+
+
+ 赞助
+
+
+
+ |
+
+
+
+ |
+
+

+
+
+
+
+
+ 输入内容格式有误!
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/index.html b/examples/index.html
new file mode 100644
index 0000000..f145d99
--- /dev/null
+++ b/examples/index.html
@@ -0,0 +1,11 @@
+
+
+
+
+ form-create-designer 示例
+
+
+
+
+
+
diff --git a/examples/main.js b/examples/main.js
new file mode 100644
index 0000000..8cfd809
--- /dev/null
+++ b/examples/main.js
@@ -0,0 +1,18 @@
+import {createApp} from 'vue';
+import ELEMENT from 'element-plus';
+import 'element-plus/dist/index.css';
+import formCreate from '@form-create/element-ui';
+import Antd from 'ant-design-vue';
+import App from './App';
+import 'ant-design-vue/dist/antd.css';
+import FcDesigner from '../src/index';
+
+const app = createApp(App);
+
+app.use(Antd);
+app.use(ELEMENT);
+app.use(formCreate);
+app.use(FcDesigner);
+
+
+app.mount('#app')
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..8cbb1d0
--- /dev/null
+++ b/package.json
@@ -0,0 +1,135 @@
+{
+ "name": "@form-create/designer",
+ "version": "3.0.2",
+ "description": "好用的vue可视化表单设计器组件",
+ "unpkg": "./dist/index.umd.js",
+ "jsdelivr": "./dist/index.umd.js",
+ "typings": "./types/index.d.ts",
+ "main": "./dist/index.umd.js",
+ "module": "./dist/index.es.js",
+ "exports": {
+ ".": {
+ "import": "./dist/index.es.js",
+ "require": "./dist/index.umd.js"
+ }
+ },
+ "scripts": {
+ "clean": "rimraf dist/",
+ "dev": "vue-cli-service serve",
+ "rollup": "rollup -c ./rollup.config.ts",
+ "build": "vite build --config ./vite.config.build.js",
+ "build:preview": "vite build --config ./vite.config.preview.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/xaboy/form-create-designer.git"
+ },
+ "keywords": [
+ "表单设计器",
+ "@form-create",
+ "form-builder",
+ "form-designer",
+ "draggable",
+ "form",
+ "components",
+ "vue3",
+ "element-ui",
+ "json-form",
+ "dynamic-form"
+ ],
+ "files": [
+ "README.md",
+ "package.json",
+ "LICENSE",
+ "src",
+ "types",
+ "dist"
+ ],
+ "author": "xaboy",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/xaboy/form-create-designer/issues"
+ },
+ "homepage": "http://designer.form-create.com",
+ "publishConfig": {
+ "access": "public"
+ },
+ "devDependencies": {
+ "@element-plus/icons-vue": "^0.2.6",
+ "@sixian/css-url": "^1.0.3",
+ "@types/chalk": "^2.2.0",
+ "@types/shelljs": "^0.8.9",
+ "@vitejs/plugin-vue": "^3.1.2",
+ "@vitejs/plugin-vue-jsx": "^2.0.1",
+ "@vue/babel-plugin-jsx": "^1.0.7",
+ "@vue/cli-plugin-babel": "^4.5.13",
+ "@vue/cli-service": "^4.5.3",
+ "@vue/compiler-sfc": "^3.0.11",
+ "babel-eslint": "^10.1.0",
+ "chalk": "^4.1.2",
+ "codemirror": "^5.60.0",
+ "commander": "^6.0.0",
+ "commitizen": "^4.1.2",
+ "cross-env": "^7.0.2",
+ "css-loader": "^4.2.1",
+ "cssnano": "^5.1.13",
+ "cssnano-preset-advanced": "^5.3.8",
+ "cz-conventional-changelog": "^3.2.0",
+ "cz-customizable": "^6.3.0",
+ "dayjs": "^1.10.7",
+ "element-plus": "^2.0.1",
+ "eslint": "^7.7.0",
+ "eslint-plugin-vue": "^6.2.2",
+ "esno": "^0.9.1",
+ "execa": "^5.1.1",
+ "fast-glob": "^3.2.7",
+ "figlet": "^1.5.0",
+ "fs-extra": "^10.0.0",
+ "html-webpack-plugin": "^4.3.0",
+ "humps": "^2.0.1",
+ "husky": "^4.2.5",
+ "jsonlint-mod": "^1.7.6",
+ "lint-staged": "^10.2.11",
+ "npm-run-all": "^4.1.5",
+ "ora": "^5.0.0",
+ "postcss": "^8.4.17",
+ "rimraf": "^3.0.2",
+ "rollup-plugin-visualizer": "^5.8.2",
+ "shelljs": "^0.8.4",
+ "stringify-author": "^0.1.3",
+ "tslib": "^2.3.1",
+ "typescript": "^4.4.3",
+ "vite": "^3.1.4",
+ "vite-plugin-banner": "^0.5.0",
+ "vite-plugin-css-injected-by-js": "^2.1.0",
+ "vue": "^3.1.5",
+ "vue-loader": "^15.9.3",
+ "vue-style-loader": "^4.1.2",
+ "vue-template-compiler": "^2.6.11"
+ },
+ "config": {
+ "commitizen": {
+ "path": "./node_modules/cz-customizable"
+ }
+ },
+ "husky": {
+ "hooks": {
+ "pre-commit": "lint-staged"
+ }
+ },
+ "lint-staged": {
+ "*.{js,jsx,vue}": [
+ "eslint --fix",
+ "git add"
+ ]
+ },
+ "dependencies": {
+ "@form-create/ant-design-vue": "next",
+ "@form-create/component-wangeditor": "^3.1",
+ "@form-create/designer": "^1.0.8",
+ "@form-create/element-ui": "^3.1.16",
+ "@form-create/utils": "^3.1.15",
+ "ant-design-vue": "^3.2.15",
+ "vuedraggable": "4.1.0"
+ }
+}
diff --git a/src/components/DragBox.vue b/src/components/DragBox.vue
new file mode 100644
index 0000000..0733977
--- /dev/null
+++ b/src/components/DragBox.vue
@@ -0,0 +1,33 @@
+
diff --git a/src/components/DragTool.vue b/src/components/DragTool.vue
new file mode 100644
index 0000000..1a89124
--- /dev/null
+++ b/src/components/DragTool.vue
@@ -0,0 +1,136 @@
+
+
+
+
+
+
+
diff --git a/src/components/FcDesigner.vue b/src/components/FcDesigner.vue
new file mode 100644
index 0000000..9c44256
--- /dev/null
+++ b/src/components/FcDesigner.vue
@@ -0,0 +1,861 @@
+
+
+
+
+
+
+
+
+
+
{{ item.title }}
+
+
+
+
+
+
+
{{ element.label }}
+
+
+
+
+
+
+
+
+
+ 预 览
+
+
+
+ 清 空
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 组件配置
+
+ 表单配置
+
+
+
+
+
+
+
+ 基础配置
+
+ 属性配置
+
+ 验证规则
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/Fetch.vue b/src/components/Fetch.vue
new file mode 100644
index 0000000..96a69fe
--- /dev/null
+++ b/src/components/Fetch.vue
@@ -0,0 +1,162 @@
+
+
+
+
+
+
+
+
diff --git a/src/components/IconRefresh.vue b/src/components/IconRefresh.vue
new file mode 100644
index 0000000..2796dfe
--- /dev/null
+++ b/src/components/IconRefresh.vue
@@ -0,0 +1,14 @@
+
+
+
+
+
diff --git a/src/components/Required.vue b/src/components/Required.vue
new file mode 100644
index 0000000..7fcac58
--- /dev/null
+++ b/src/components/Required.vue
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/Struct.vue b/src/components/Struct.vue
new file mode 100644
index 0000000..59ecfac
--- /dev/null
+++ b/src/components/Struct.vue
@@ -0,0 +1,127 @@
+
+
+
{{ title }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/TableOptions.vue b/src/components/TableOptions.vue
new file mode 100644
index 0000000..15ba384
--- /dev/null
+++ b/src/components/TableOptions.vue
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+ (scope.row[col.key] = n, onInput(scope.row))">
+
+
+
+
+
+
+
+
+
+
+
+ 添加
+
+
+
+
+
+
+
diff --git a/src/components/Validate.vue b/src/components/Validate.vue
new file mode 100644
index 0000000..edfd987
--- /dev/null
+++ b/src/components/Validate.vue
@@ -0,0 +1,229 @@
+
+
+
+
+
+
+
diff --git a/src/config/base/field.js b/src/config/base/field.js
new file mode 100644
index 0000000..20485e2
--- /dev/null
+++ b/src/config/base/field.js
@@ -0,0 +1,84 @@
+import IconRefresh from '../../components/IconRefresh.vue';
+import {markRaw} from 'vue';
+
+export default function field() {
+ return [
+ {
+ type: 'input',
+ field: 'field',
+ value: '',
+ title: '字段 ID',
+ }, {
+ type: 'input',
+ field: 'title',
+ value: '',
+ title: '字段名称',
+ }, {
+ type: 'input',
+ field: 'info',
+ value: '',
+ title: '提示信息',
+ }, {
+ type: 'Struct',
+ field: '_control',
+ value: [],
+ title: '联动数据',
+ props: {
+ defaultValue: [],
+ validate(val) {
+ if (!Array.isArray(val)) return false;
+ if (!val.length) return true;
+ return !val.some(({rule}) => {
+ return !Array.isArray(rule);
+ });
+ }
+ }
+ }, {
+ type: 'col',
+ props: {
+ span: 24
+ },
+ children: [
+ {
+ type: 'el-button',
+ props: {
+ type: 'primary',
+ size: 'small',
+ },
+ inject: true,
+ on: {
+ click({$f}) {
+ const rule = $f.activeRule;
+ if (rule) {
+ rule.__fc__.updateKey();
+ rule.value = undefined;
+ rule.__fc__.$api.sync(rule);
+ }
+ },
+ },
+ native: true,
+ children: [{type: 'i', class: 'fc-icon icon-delete'}, '清空值']
+ }, {
+ type: 'el-button',
+ props: {
+ type: 'success',
+ size: 'small',
+ icon: markRaw(IconRefresh),
+ },
+ inject: true,
+ on: {
+ click({$f}) {
+ const rule = $f.activeRule;
+ if (rule) {
+ rule.__fc__.updateKey(true);
+ rule.__fc__.$api.sync(rule);
+ }
+ },
+ },
+ native: true,
+ children: ['刷新']
+ },
+ ]
+ }
+ ];
+}
diff --git a/src/config/base/form.js b/src/config/base/form.js
new file mode 100644
index 0000000..4cee918
--- /dev/null
+++ b/src/config/base/form.js
@@ -0,0 +1,55 @@
+export default function form() {
+ return [
+ {
+ type: 'radio',
+ field: 'labelPosition',
+ value: 'left',
+ title: '标签位置',
+ options: [
+ {value: 'right', label: 'right'},
+ {value: 'left', label: 'left'},
+ {value: 'top', label: 'top'},
+ ]
+ }, {
+ type: 'radio',
+ field: 'size',
+ value: 'small',
+ title: '表单尺寸',
+ options: [
+ {value: 'large', label: 'large'},
+ {value: 'default', label: 'default'},
+ {value: 'small', label: 'small'},
+ ]
+ }, {
+ type: 'input',
+ field: 'labelWidth',
+ value: '125px',
+ title: '标签宽度',
+ }, {
+ type: 'switch',
+ field: 'hideRequiredAsterisk',
+ value: false,
+ title: '隐藏必填字段的标签旁边的红色星号',
+ }, {
+ type: 'switch',
+ field: 'showMessage',
+ value: true,
+ title: '显示校验错误信息',
+ }, {
+ type: 'switch',
+ field: 'inlineMessage',
+ value: false,
+ title: '以行内形式展示校验信息',
+ }, {
+ type: 'switch',
+ field: 'formCreateSubmitBtn',
+ value: true,
+ title: '是否显示表单提交按钮',
+ }, {
+ type: 'switch',
+ field: 'formCreateResetBtn',
+ value: false,
+ title: '是否显示表单重置按钮',
+ },
+ ];
+}
diff --git a/src/config/base/validate.js b/src/config/base/validate.js
new file mode 100644
index 0000000..91b42ab
--- /dev/null
+++ b/src/config/base/validate.js
@@ -0,0 +1,9 @@
+export default function validate() {
+ return [
+ {
+ type: 'validate',
+ field: 'validate',
+ value: []
+ },
+ ];
+}
\ No newline at end of file
diff --git a/src/config/menu.js b/src/config/menu.js
new file mode 100644
index 0000000..e71a4bc
--- /dev/null
+++ b/src/config/menu.js
@@ -0,0 +1,51 @@
+import radio from './rule/radio';
+import checkbox from './rule/checkbox';
+import input from './rule/input';
+import number from './rule/number';
+import select from './rule/select';
+import _switch from './rule/switch';
+import slider from './rule/slider';
+import time from './rule/time';
+import date from './rule/date';
+import rate from './rule/rate';
+import color from './rule/color';
+import row from './rule/row';
+import divider from './rule/divider';
+import cascader from './rule/cascader';
+import upload from './rule/upload';
+import transfer from './rule/transfer';
+import tree from './rule/tree';
+import alert from './rule/alert';
+import span from './rule/span';
+import space from './rule/space';
+import button from './rule/button';
+import editor from './rule/editor';
+import tab from './rule/tab';
+import drawer from './rule/drawer';
+import image from './rule/image.ts';
+// 还需要在./rule/index.js文件里注册
+export default function createMenu() {
+ return [
+ {
+ name: 'main',
+ title: '表单组件',
+ list: [
+ input, number, radio, checkbox, select, _switch, time, date, slider, rate, color, cascader, upload, transfer, tree, editor
+ ]
+ },
+ {
+ name: 'aide',
+ title: '辅助组件',
+ list: [
+ alert, button, span, divider,image
+ ]
+ },
+ {
+ name: 'layout',
+ title: '布局组件',
+ list: [
+ row, tab, space,drawer
+ ]
+ },
+ ];
+}
diff --git a/src/config/rule/alert.js b/src/config/rule/alert.js
new file mode 100644
index 0000000..4e6f5d2
--- /dev/null
+++ b/src/config/rule/alert.js
@@ -0,0 +1,45 @@
+const label = '提示';
+const name = 'el-alert';
+
+export default {
+ icon: 'icon-alert',
+ label,
+ name,
+ rule() {
+ return {
+ type: name,
+ props: {
+ title: '提示',
+ description: 'form-create',
+ type: 'success',
+ effect: 'dark',
+ },
+ children: []
+ };
+ },
+ props() {
+ return [{type: 'input', field: 'title', title: '标题'}, {
+ type: 'select',
+ field: 'type',
+ title: '主题',
+ options: [{label: 'success', value: 'success'}, {label: 'warning', value: 'warning'}, {
+ label: 'info',
+ value: 'info'
+ }, {label: 'error', value: 'error'}]
+ }, {type: 'input', field: 'description', title: '辅助性文字'}, {
+ type: 'switch',
+ field: 'closable',
+ title: '是否可关闭',
+ value: true
+ }, {type: 'switch', field: 'center', title: '文字是否居中', value: true}, {
+ type: 'input',
+ field: 'closeText',
+ title: '关闭按钮自定义文本'
+ }, {type: 'switch', field: 'showIcon', title: '是否显示图标'}, {
+ type: 'select',
+ field: 'effect',
+ title: '选择提供的主题',
+ options: [{label: 'light', value: 'light'}, {label: 'dark', value: 'dark'}]
+ }];
+ }
+};
\ No newline at end of file
diff --git a/src/config/rule/button.js b/src/config/rule/button.js
new file mode 100644
index 0000000..06b2a0a
--- /dev/null
+++ b/src/config/rule/button.js
@@ -0,0 +1,54 @@
+const label = '按钮';
+const name = 'el-button';
+
+export default {
+ icon: 'icon-button',
+ label,
+ name,
+ mask: false,
+ rule() {
+ return {
+ type: name,
+ props: {},
+ children: ['按钮'],
+ };
+ },
+ props() {
+ return [{
+ type: 'input',
+ field: 'formCreateChild',
+ title: '内容',
+ }, {
+ type: 'select',
+ field: 'size',
+ title: '尺寸',
+ options: [{label: 'large', value: 'large'}, {label: 'default', value: 'default'}, {
+ label: 'small',
+ value: 'small'
+ }]
+ }, {
+ type: 'select',
+ field: 'type',
+ title: '类型',
+ options: [{label: 'primary', value: 'primary'}, {
+ label: 'success',
+ value: 'success'
+ }, {label: 'warning', value: 'warning'}, {label: 'danger', value: 'danger'}, {
+ label: 'info',
+ value: 'info'
+ }]
+ }, {type: 'switch', field: 'plain', title: '是否朴素按钮'}, {
+ type: 'switch',
+ field: 'round',
+ title: '是否圆角按钮'
+ }, {type: 'switch', field: 'circle', title: '是否圆形按钮'}, {
+ type: 'switch',
+ field: 'loading',
+ title: '是否加载中状态'
+ }, {type: 'switch', field: 'disabled', title: '是否禁用状态'}, {
+ type: 'input',
+ field: 'icon',
+ title: '图标类名'
+ }];
+ }
+};
diff --git a/src/config/rule/cascader.js b/src/config/rule/cascader.js
new file mode 100644
index 0000000..ce1fa21
--- /dev/null
+++ b/src/config/rule/cascader.js
@@ -0,0 +1,180 @@
+import uniqueId from '@form-create/utils/lib/unique';
+import {makeOptionsRule, makeRequiredRule} from '../../utils/index';
+
+const label = '级联选择器';
+const name = 'cascader';
+
+export default {
+ icon: 'icon-cascader',
+ label,
+ name,
+ rule() {
+ return {
+ type: name,
+ field: uniqueId(),
+ title: label,
+ info: '',
+ effect: {
+ fetch: ''
+ },
+ props: {
+ options: [{
+ value: 'zhinan',
+ label: '指南',
+ children: [{
+ value: 'shejiyuanze',
+ label: '设计原则',
+ children: [{
+ value: 'yizhi',
+ label: '一致'
+ }, {
+ value: 'fankui',
+ label: '反馈'
+ }, {
+ value: 'xiaolv',
+ label: '效率'
+ }, {
+ value: 'kekong',
+ label: '可控'
+ }]
+ }, {
+ value: 'daohang',
+ label: '导航',
+ children: [{
+ value: 'cexiangdaohang',
+ label: '侧向导航'
+ }, {
+ value: 'dingbudaohang',
+ label: '顶部导航'
+ }]
+ }]
+ }, {
+ value: 'zujian',
+ label: '组件',
+ children: [{
+ value: 'basic',
+ label: 'Basic',
+ children: [{
+ value: 'layout',
+ label: 'Layout 布局'
+ }, {
+ value: 'color',
+ label: 'Color 色彩'
+ }, {
+ value: 'typography',
+ label: 'Typography 字体'
+ }, {
+ value: 'icon',
+ label: 'Icon 图标'
+ }, {
+ value: 'button',
+ label: 'Button 按钮'
+ }]
+ }, {
+ value: 'form',
+ label: 'Form',
+ children: [{
+ value: 'radio',
+ label: 'Radio 单选框'
+ }, {
+ value: 'checkbox',
+ label: 'Checkbox 多选框'
+ }, {
+ value: 'input',
+ label: 'Input 输入框'
+ }, {
+ value: 'input-number',
+ label: 'InputNumber 计数器'
+ }, {
+ value: 'select',
+ label: 'Select 选择器'
+ }, {
+ value: 'cascader',
+ label: 'Cascader 级联选择器'
+ }, {
+ value: 'switch',
+ label: 'Switch 开关'
+ }, {
+ value: 'slider',
+ label: 'Slider 滑块'
+ }, {
+ value: 'time-picker',
+ label: 'TimePicker 时间选择器'
+ }, {
+ value: 'date-picker',
+ label: 'DatePicker 日期选择器'
+ }, {
+ value: 'datetime-picker',
+ label: 'DateTimePicker 日期时间选择器'
+ }, {
+ value: 'upload',
+ label: 'Upload 上传'
+ }, {
+ value: 'rate',
+ label: 'Rate 评分'
+ }, {
+ value: 'form',
+ label: 'Form 表单'
+ }]
+ }]
+ }]
+ }
+ };
+ },
+ props() {
+ return [
+ makeRequiredRule(),
+ makeOptionsRule('props.options', false),
+ {
+ type: 'Object',
+ field: 'props',
+ title: '配置选项',
+ props: {
+ rule: [{
+ type: 'select',
+ field: 'expandTrigger',
+ title: '次级菜单的展开方式',
+ options: [{label: 'click', value: 'click'}, {label: 'hover', value: 'hover'}]
+ }, {type: 'switch', field: 'multiple', title: '是否多选'}, {
+ type: 'switch',
+ field: 'checkStrictly',
+ title: '是否严格的遵守父子节点不互相关联'
+ }, {
+ type: 'switch',
+ field: 'emitPath',
+ title: '在选中节点改变时,是否返回由该节点所在的各级菜单的值所组成的数组,若设置 false,则只返回该节点的值',
+ value: true
+ }, {type: 'input', field: 'value', title: '指定选项的值为选项对象的某个属性值'}, {
+ type: 'input',
+ field: 'label',
+ title: '指定选项标签为选项对象的某个属性值'
+ }, {type: 'input', field: 'children', title: '指定选项的子选项为选项对象的某个属性值'}, {
+ type: 'input',
+ field: 'disabled',
+ title: '指定选项的禁用为选项对象的某个属性值'
+ }, {type: 'input', field: 'leaf', title: '指定选项的叶子节点的标志位为选项对象的某个属性值'}]
+ }
+ }, {
+ type: 'select',
+ field: 'size',
+ title: '尺寸',
+ options: [{label: 'large', value: 'large'}, {label: 'default', value: 'default'}, {
+ label: 'small',
+ value: 'small'
+ }]
+ }, {type: 'input', field: 'placeholder', title: '输入框占位文本'}, {
+ type: 'switch',
+ field: 'disabled',
+ title: '是否禁用'
+ }, {type: 'switch', field: 'clearable', title: '是否支持清空选项'}, {
+ type: 'switch',
+ field: 'showAllLevels',
+ title: '输入框中是否显示选中值的完整路径',
+ value: true
+ }, {type: 'switch', field: 'collapseTags', title: '多选模式下是否折叠Tag'}, {
+ type: 'input',
+ field: 'separator',
+ title: '选项分隔符'
+ }];
+ }
+};
diff --git a/src/config/rule/checkbox.js b/src/config/rule/checkbox.js
new file mode 100644
index 0000000..06a7691
--- /dev/null
+++ b/src/config/rule/checkbox.js
@@ -0,0 +1,45 @@
+import uniqueId from '@form-create/utils/lib/unique';
+import {makeOptionsRule, makeRequiredRule} from '../../utils/index';
+
+const label = '多选框';
+const name = 'checkbox';
+
+export default {
+ icon: 'icon-checkbox',
+ label,
+ name,
+ rule() {
+ return {
+ type: name,
+ field: uniqueId(),
+ title: label,
+ info: '',
+ effect: {
+ fetch: ''
+ },
+ props: {},
+ options: [
+ {value: '1', label: '选项1'},
+ {value: '2', label: '选项2'},
+ ]
+ };
+ },
+ props() {
+ return [
+ makeRequiredRule(), makeOptionsRule('options'),
+ {
+ type: 'switch',
+ field: 'type',
+ title: '按钮类型',
+ props: {activeValue: 'button', inactiveValue: 'default'}
+ }, {type: 'switch', field: 'disabled', title: '是否禁用'}, {
+ type: 'inputNumber',
+ field: 'min',
+ title: '可被勾选的 checkbox 的最小数量'
+ }, {type: 'inputNumber', field: 'max', title: '可被勾选的 checkbox 的最大数量'}, {
+ type: 'input',
+ field: 'textColor',
+ title: '按钮形式的 Checkbox 激活时的文本颜色'
+ }, {type: 'input', field: 'fill', title: '按钮形式的 Checkbox 激活时的填充色和边框色'}];
+ }
+};
diff --git a/src/config/rule/col.js b/src/config/rule/col.js
new file mode 100644
index 0000000..8a79fa5
--- /dev/null
+++ b/src/config/rule/col.js
@@ -0,0 +1,23 @@
+const name = 'col';
+
+export default {
+ name,
+ drag: true,
+ dragBtn: false,
+ inside: true,
+ mask: false,
+ rule() {
+ return {
+ type: name,
+ props: {span: 12},
+ children: []
+ };
+ },
+ props() {
+ return [
+ {type: 'slider', field: 'span', title: '栅格占据的列数', value: 12, props: {min: 0, max: 24}},
+ {type: 'slider', field: 'offset', title: '栅格左侧的间隔格数', props: {min: 0, max: 24}},
+ {type: 'slider', field: 'push', title: '栅格向右移动格数', props: {min: 0, max: 24}},
+ {type: 'slider', field: 'pull', title: '栅格向左移动格数', props: {min: 0, max: 24}}];
+ }
+};
diff --git a/src/config/rule/color.js b/src/config/rule/color.js
new file mode 100644
index 0000000..f3a8e4c
--- /dev/null
+++ b/src/config/rule/color.js
@@ -0,0 +1,36 @@
+import uniqueId from '@form-create/utils/lib/unique';
+import {makeRequiredRule} from '../../utils';
+
+const label = '颜色选择器';
+const name = 'colorPicker';
+
+export default {
+ icon: 'icon-color',
+ label,
+ name,
+ rule() {
+ return {
+ type: name,
+ field: uniqueId(),
+ title: label,
+ info: '',
+ props: {},
+ };
+ },
+ props() {
+ return [
+ makeRequiredRule(), {type: 'switch', field: 'disabled', title: '是否禁用'}, {
+ type: 'switch',
+ field: 'showAlpha',
+ title: '是否支持透明度选择'
+ }, {
+ type: 'select',
+ field: 'colorFormat',
+ title: '颜色的格式',
+ options: [{label: 'hsl', value: 'hsl'}, {label: 'hsv', value: 'hsv'}, {
+ label: 'hex',
+ value: 'hex'
+ }, {label: 'rgb', value: 'rgb'}]
+ }];
+ }
+};
diff --git a/src/config/rule/date.js b/src/config/rule/date.js
new file mode 100644
index 0000000..80a2104
--- /dev/null
+++ b/src/config/rule/date.js
@@ -0,0 +1,75 @@
+import uniqueId from '@form-create/utils/lib/unique';
+import {makeRequiredRule} from '../../utils';
+
+const label = '日期选择器';
+const name = 'datePicker';
+
+export default {
+ icon: 'icon-date',
+ label,
+ name,
+ rule() {
+ return {
+ type: name,
+ field: uniqueId(),
+ title: label,
+ info: '',
+ props: {},
+ };
+ },
+ props() {
+ return [makeRequiredRule(), {
+ type: 'Struct',
+ field: 'pickerOptions',
+ title: '当前时间日期选择器特有的选项',
+ props: {defaultValue: {}}
+ }, {type: 'switch', field: 'readonly', title: '完全只读'}, {
+ type: 'switch',
+ field: 'disabled',
+ title: '禁用'
+ }, {
+ type: 'select',
+ field: 'type',
+ title: '显示类型',
+ options: [{label: 'year', value: 'year'}, {label: 'month', value: 'month'}, {
+ label: 'date',
+ value: 'date'
+ }, {label: 'dates', value: 'dates'}, {label: 'week', value: 'week'}, {
+ label: 'datetime',
+ value: 'datetime'
+ }, {label: 'datetimerange', value: 'datetimerange'}, {
+ label: 'daterange',
+ value: 'daterange'
+ }, {label: 'monthrange', value: 'monthrange'}]
+ }, {type: 'switch', field: 'editable', title: '文本框可输入', value: true}, {
+ type: 'switch',
+ field: 'clearable',
+ title: '是否显示清除按钮',
+ value: true
+ }, {type: 'input', field: 'placeholder', title: '非范围选择时的占位内容'}, {
+ type: 'input',
+ field: 'startPlaceholder',
+ title: '范围选择时开始日期的占位内容'
+ }, {type: 'input', field: 'endPlaceholder', title: '范围选择时结束日期的占位内容'}, {
+ type: 'input',
+ field: 'format',
+ title: '显示在输入框中的格式'
+ }, {
+ type: 'select',
+ field: 'align',
+ title: '对齐方式',
+ options: [{label: 'left', value: 'left'}, {label: 'center', value: 'center'}, {
+ label: 'right',
+ value: 'right'
+ }, {label: 'left', value: 'left'}]
+ }, {type: 'input', field: 'rangeSeparator', title: '选择范围时的分隔符'}, {
+ type: 'switch',
+ field: 'unlinkPanels',
+ title: '在范围选择器里取消两个日期面板之间的联动'
+ }, {type: 'input', field: 'prefixIcon', title: '自定义头部图标的类名'}, {
+ type: 'input',
+ field: 'clearIcon',
+ title: '自定义清空图标的类名'
+ }];
+ }
+};
diff --git a/src/config/rule/divider.js b/src/config/rule/divider.js
new file mode 100644
index 0000000..6b39933
--- /dev/null
+++ b/src/config/rule/divider.js
@@ -0,0 +1,37 @@
+const label = '分割线';
+const name = 'el-divider';
+
+export default {
+ icon: 'icon-divider',
+ label,
+ name,
+ rule() {
+ return {
+ type: name,
+ props: {},
+ wrap: {show: false},
+ native: false,
+ children: [''],
+ };
+ },
+ props() {
+ return [{
+ type: 'select',
+ field: 'direction',
+ title: '设置分割线方向',
+ options: [{label: 'horizontal', value: 'horizontal'}, {label: 'vertical', value: 'vertical'}]
+ }, {
+ type: 'input',
+ field: 'formCreateChild',
+ title: '设置分割线文案',
+ }, {
+ type: 'select',
+ field: 'contentPosition',
+ title: '设置分割线文案的位置',
+ options: [{label: 'left', value: 'left'}, {label: 'right', value: 'right'}, {
+ label: 'center',
+ value: 'center'
+ }]
+ }];
+ }
+};
\ No newline at end of file
diff --git a/src/config/rule/drawer.js b/src/config/rule/drawer.js
new file mode 100644
index 0000000..fdcc967
--- /dev/null
+++ b/src/config/rule/drawer.js
@@ -0,0 +1,27 @@
+const label = "浮层面板";
+const name = "a-drawer";
+
+export default {
+ icon: "icon-row",
+ label,
+ name,
+ drag: true,
+ dragBtn: false,
+ mask: false,
+ rule() {
+ return {
+ type : name,
+ props : {
+ title:"Create a new account",
+ width:"720",
+ visible:false,
+ },
+ children: []
+ };
+ },
+ props() {
+ return [
+ { type: "input", field: "width", title: "宽度" },
+ ];
+ }
+};
diff --git a/src/config/rule/editor.js b/src/config/rule/editor.js
new file mode 100644
index 0000000..e41b676
--- /dev/null
+++ b/src/config/rule/editor.js
@@ -0,0 +1,23 @@
+import uniqueId from '@form-create/utils/lib/unique';
+import {makeRequiredRule} from '../../utils';
+
+const label = '富文本框';
+const name = 'fc-editor';
+
+export default {
+ icon: 'icon-editor',
+ label,
+ name,
+ rule() {
+ return {
+ type: name,
+ field: uniqueId(),
+ title: label,
+ info: '',
+ props: {},
+ };
+ },
+ props() {
+ return [makeRequiredRule(), {type: 'switch', field: 'disabled', title: '是否禁用'}];
+ }
+};
diff --git a/src/config/rule/image.ts b/src/config/rule/image.ts
new file mode 100644
index 0000000..e4a929a
--- /dev/null
+++ b/src/config/rule/image.ts
@@ -0,0 +1,57 @@
+// @ts-ignore
+// import FcDesigner from "@form-create/ant-design-vue";
+import {makeRequiredRule,makeOptionsRule} from '../../utils';
+const label = "图片";
+const name = "a-image";
+const icon = "icon-xingzhuang-tupian";
+let i = 1;
+const uniqueId = () => `uni${i++}`;
+
+export default {
+ //拖拽组件的图标
+ icon,
+ //拖拽组件的名称
+ label,
+ //拖拽组件的 key
+ name,
+ //拖拽组件的生成规则
+ rule() {
+ //如果在 props 方法中需要修改 rule 的属性,需要提前在 rule 上定义对应的属性
+ return {
+ //生成组件的名称
+ type: name,
+ //field 自定不能重复,所以这里每次都会生成一个新的
+ field: uniqueId(),
+ title: label,
+ info: "",
+ effect: {
+ fetch: ""
+ },
+ //这里设置组件的默认props配置项, 在下面的 props 方法里面设置无效
+ props: {
+ src: "https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png",
+ width: 200,
+ placeholder: true,
+ },
+ options: [
+
+ ],
+ };
+ },
+
+ //拖拽组件配置项(props)的生成规则
+ props() {
+ return [
+ //生成`checkbox`组件的`options`配置规则
+ // makeRequiredRule(),
+ // makeOptionsRule("props"),
+ { type: "input", field: "src", title: "图片地址(支持http/base64)" },
+ { type: "input", field: "fallback", title: "加载失败容错地址" },
+ { type: "input", field: "width", title: "图像宽度" },
+ { type: "input", field: "height", title: "图像高度" },
+ { type: "switch", field: "preview", title: "预览参数,为 false 时禁用" },
+ { type: "switch", field: "placeholder", title: "加载占位, 为 true 时使用默认占位"},
+ { type: "input", field: "alt", title: "图像描述"},
+ ];
+ }
+};
diff --git a/src/config/rule/index.js b/src/config/rule/index.js
new file mode 100644
index 0000000..aa9b56b
--- /dev/null
+++ b/src/config/rule/index.js
@@ -0,0 +1,61 @@
+import radio from './radio';
+import checkbox from './checkbox';
+import input from './input';
+import number from './number';
+import select from './select';
+import _switch from './switch';
+import slider from './slider';
+import time from './time';
+import date from './date';
+import rate from './rate';
+import color from './color';
+import row from './row';
+import col from './col';
+import tabPane from './tabPane';
+import divider from './divider';
+import cascader from './cascader';
+import upload from './upload';
+import transfer from './transfer';
+import tree from './tree';
+import alert from './alert';
+import span from './span';
+import space from './space';
+import tab from './tab';
+import button from './button';
+import editor from './editor';
+import drawer from './drawer';
+import image from './image.ts';
+
+// 还需要在../menu.js文件里注册
+
+const ruleList = {
+ [drawer.name]: drawer,
+ [radio.name]: radio,
+ [checkbox.name]: checkbox,
+ [input.name]: input,
+ [number.name]: number,
+ [select.name]: select,
+ [_switch.name]: _switch,
+ [slider.name]: slider,
+ [time.name]: time,
+ [date.name]: date,
+ [rate.name]: rate,
+ [color.name]: color,
+ [row.name]: row,
+ [col.name]: col,
+ [tab.name]: tab,
+ [tabPane.name]: tabPane,
+ [divider.name]: divider,
+ [cascader.name]: cascader,
+ [upload.name]: upload,
+ [transfer.name]: transfer,
+ [tree.name]: tree,
+ [alert.name]: alert,
+ [span.name]: span,
+ [space.name]: space,
+ [button.name]: button,
+ [editor.name]: editor,
+ [image.name]: image,
+};
+
+export default ruleList;
diff --git a/src/config/rule/input.js b/src/config/rule/input.js
new file mode 100644
index 0000000..6c935fd
--- /dev/null
+++ b/src/config/rule/input.js
@@ -0,0 +1,65 @@
+import uniqueId from '@form-create/utils/lib/unique';
+import {makeRequiredRule} from '../../utils';
+
+const label = '输入框';
+const name = 'input';
+
+export default {
+ icon: 'icon-input',
+ label,
+ name,
+ rule() {
+ return {
+ type: name,
+ field: uniqueId(),
+ title: label,
+ info: '',
+ props: {}
+ };
+ },
+ props() {
+ return [makeRequiredRule(), {
+ type: 'select',
+ field: 'type',
+ title: '类型',
+ options: [{label: 'text', value: 'text'}, {
+ label: 'textarea',
+ value: 'textarea'
+ }, {label: 'number', value: 'number'}, {label: 'password', value: 'password'}]
+ }, {type: 'inputNumber', field: 'maxlength', title: '最大输入长度'}, {
+ type: 'inputNumber',
+ field: 'minlength',
+ title: '最小输入长度'
+ }, {type: 'switch', field: 'showWordLimit', title: '是否显示输入字数统计'}, {
+ type: 'input',
+ field: 'placeholder',
+ title: '输入框占位文本'
+ }, {type: 'switch', field: 'clearable', title: '是否可清空'}, {
+ type: 'switch',
+ field: 'showPassword',
+ title: '是否显示切换密码图标'
+ }, {type: 'switch', field: 'disabled', title: '禁用'}, {
+ type: 'input',
+ field: 'prefixIcon',
+ title: '输入框头部图标'
+ }, {type: 'input', field: 'suffixIcon', title: '输入框尾部图标'}, {
+ type: 'inputNumber',
+ field: 'rows',
+ info: '只对 type="textarea" 有效',
+ title: '输入框行数'
+ }, {
+ type: 'select',
+ field: 'autocomplete',
+ title: '自动补全',
+ options: [{label: 'on', value: 'on'}, {label: 'off', value: 'off'}]
+ }, {type: 'switch', field: 'readonly', title: '是否只读'}, {
+ type: 'select',
+ field: 'resize',
+ title: '控制是否能被用户缩放',
+ options: [{label: 'none', value: 'none'}, {label: 'both', value: 'both'}, {
+ label: 'horizontal',
+ value: 'horizontal'
+ }, {label: 'vertical', value: 'vertical'}]
+ }, {type: 'switch', field: 'autofocus', title: '自动获取焦点'}];
+ }
+};
diff --git a/src/config/rule/number.js b/src/config/rule/number.js
new file mode 100644
index 0000000..55937bf
--- /dev/null
+++ b/src/config/rule/number.js
@@ -0,0 +1,41 @@
+import uniqueId from '@form-create/utils/lib/unique';
+import {makeRequiredRule} from '../../utils';
+
+const label = '计数器';
+const name = 'inputNumber';
+
+export default {
+ icon: 'icon-number',
+ label,
+ name,
+ rule() {
+ return {
+ type: name,
+ field: uniqueId(),
+ title: label,
+ info: '',
+ props: {}
+ };
+ },
+ props() {
+ return [makeRequiredRule(), {type: 'inputNumber', field: 'min', title: '设置计数器允许的最小值'}, {
+ type: 'inputNumber',
+ field: 'max',
+ title: '设置计数器允许的最大值'
+ }, {type: 'inputNumber', field: 'step', title: '计数器步长'}, {
+ type: 'switch',
+ field: 'stepStrictly',
+ title: '是否只能输入 step 的倍数'
+ }, {type: 'switch', field: 'disabled', title: '是否禁用计数器'}, {
+ type: 'switch',
+ field: 'controls',
+ title: '是否使用控制按钮',
+ value: true
+ }, {
+ type: 'select',
+ field: 'controlsPosition',
+ title: '控制按钮位置',
+ options: [{label: 'default', value: ''}, {label: 'right', value: 'right'}]
+ }, {type: 'input', field: 'placeholder', title: '输入框默认 placeholder'}];
+ }
+};
diff --git a/src/config/rule/radio.js b/src/config/rule/radio.js
new file mode 100644
index 0000000..85551f0
--- /dev/null
+++ b/src/config/rule/radio.js
@@ -0,0 +1,42 @@
+import uniqueId from '@form-create/utils/lib/unique';
+import {makeOptionsRule, makeRequiredRule} from '../../utils/index';
+
+const label = '单选框';
+const name = 'radio';
+
+export default {
+ icon: 'icon-radio',
+ label,
+ name,
+ rule() {
+ return {
+ type: name,
+ field: uniqueId(),
+ title: label,
+ info: '',
+ effect: {
+ fetch: ''
+ },
+ props: {},
+ options: [
+ {value: '1', label: '选项1'},
+ {value: '2', label: '选项2'},
+ ]
+ };
+ },
+ props() {
+ return [
+ makeRequiredRule(),
+ makeOptionsRule('options'),
+ {type: 'switch', field: 'disabled', title: '是否禁用'}, {
+ type: 'switch',
+ field: 'type',
+ title: '按钮形式',
+ props: {activeValue: 'button', inactiveValue: 'default'}
+ }, {type: 'input', field: 'textColor', title: '按钮形式的 Radio 激活时的文本颜色'}, {
+ type: 'input',
+ field: 'fill',
+ title: '按钮形式的 Radio 激活时的填充色和边框色'
+ }];
+ }
+};
diff --git a/src/config/rule/rate.js b/src/config/rule/rate.js
new file mode 100644
index 0000000..463fee8
--- /dev/null
+++ b/src/config/rule/rate.js
@@ -0,0 +1,44 @@
+import uniqueId from '@form-create/utils/lib/unique';
+import {makeRequiredRule} from '../../utils';
+
+const label = '评分';
+const name = 'rate';
+
+export default {
+ icon: 'icon-rate',
+ label,
+ name,
+ rule() {
+ return {
+ type: name,
+ field: uniqueId(),
+ title: label,
+ info: '',
+ props: {},
+ };
+ },
+ props() {
+ return [
+ makeRequiredRule(), {type: 'inputNumber', field: 'max', title: '最大分值'}, {
+ type: 'switch',
+ field: 'disabled',
+ title: '是否为只读'
+ }, {type: 'switch', field: 'allowHalf', title: '是否允许半选'}, {
+ type: 'input',
+ field: 'voidColor',
+ title: '未选中 icon 的颜色'
+ }, {type: 'input', field: 'disabledVoidColor', title: '只读时未选中 icon 的颜色'}, {
+ type: 'input',
+ field: 'voidIconClass',
+ title: '未选中 icon 的类名'
+ }, {type: 'input', field: 'disabledVoidIconClass', title: '只读时未选中 icon 的类名'}, {
+ type: 'switch',
+ field: 'showScore',
+ title: '是否显示当前分数,show-score 和 show-text 不能同时为真'
+ }, {type: 'input', field: 'textColor', title: '辅助文字的颜色'}, {
+ type: 'input',
+ field: 'scoreTemplate',
+ title: '分数显示模板'
+ }];
+ }
+};
diff --git a/src/config/rule/row.js b/src/config/rule/row.js
new file mode 100644
index 0000000..eca88d8
--- /dev/null
+++ b/src/config/rule/row.js
@@ -0,0 +1,41 @@
+const label = '栅格布局';
+const name = 'row';
+
+export default {
+ icon: 'icon-row',
+ label,
+ name,
+ mask: false,
+ rule() {
+ return {
+ type: 'FcRow',
+ props: {},
+ children: []
+ };
+ },
+ children: 'col',
+ props() {
+ return [{type: 'inputNumber', field: 'gutter', title: '栅格间隔'}, {
+ type: 'switch',
+ field: 'type',
+ title: 'flex布局模式',
+ props: {activeValue: 'flex', inactiveValue: 'default'}
+ }, {
+ type: 'select',
+ field: 'justify',
+ title: 'flex 布局下的水平排列方式',
+ options: [{label: 'start', value: 'start'}, {label: 'end', value: 'end'}, {
+ label: 'center',
+ value: 'center'
+ }, {label: 'space-around', value: 'space-around'}, {label: 'space-between', value: 'space-between'}]
+ }, {
+ type: 'select',
+ field: 'align',
+ title: 'flex 布局下的垂直排列方式',
+ options: [{label: 'top', value: 'top'}, {label: 'middle', value: 'middle'}, {
+ label: 'bottom',
+ value: 'bottom'
+ }]
+ }];
+ }
+};
diff --git a/src/config/rule/select.js b/src/config/rule/select.js
new file mode 100644
index 0000000..acfc1af
--- /dev/null
+++ b/src/config/rule/select.js
@@ -0,0 +1,62 @@
+import uniqueId from '@form-create/utils/lib/unique';
+import {makeOptionsRule, makeRequiredRule} from '../../utils/index';
+
+const label = '选择器';
+const name = 'select';
+
+export default {
+ icon: 'icon-select',
+ label,
+ name,
+ rule() {
+ return {
+ type: name,
+ field: uniqueId(),
+ title: label,
+ info: '',
+ effect: {
+ fetch: ''
+ },
+ props: {},
+ options: [
+ {value: '1', label: '选项1'},
+ {value: '2', label: '选项2'},
+ ]
+ };
+ },
+ props() {
+ return [
+ makeRequiredRule(),
+ makeOptionsRule('options'),
+ {type: 'switch', field: 'multiple', title: '是否多选'}, {
+ type: 'switch',
+ field: 'disabled',
+ title: '是否禁用'
+ }, {type: 'switch', field: 'clearable', title: '是否可以清空选项'}, {
+ type: 'switch',
+ field: 'collapseTags',
+ title: '多选时是否将选中值按文字的形式展示'
+ }, {type: 'inputNumber', field: 'multipleLimit', title: '多选时用户最多可以选择的项目数,为 0 则不限制'}, {
+ type: 'input',
+ field: 'autocomplete',
+ title: 'autocomplete 属性'
+ }, {type: 'input', field: 'placeholder', title: '占位符'}, {
+ type: 'switch',
+ field: 'filterable',
+ title: '是否可搜索'
+ }, {type: 'switch', field: 'allowCreate', title: '是否允许用户创建新条目'}, {
+ type: 'input',
+ field: 'noMatchText',
+ title: '搜索条件无匹配时显示的文字'
+ }, {type: 'input', field: 'noDataText', title: '选项为空时显示的文字'}, {
+ type: 'switch',
+ field: 'reserveKeyword',
+ title: '多选且可搜索时,是否在选中一个选项后保留当前的搜索关键词'
+ }, {type: 'switch', field: 'defaultFirstOption', title: '在输入框按下回车,选择第一个匹配项'}, {
+ type: 'switch',
+ field: 'popperAppendToBody',
+ title: '是否将弹出框插入至 body 元素',
+ value: true
+ }, {type: 'switch', field: 'automaticDropdown', title: '对于不可搜索的 Select,是否在输入框获得焦点后自动弹出选项菜单'}];
+ }
+};
diff --git a/src/config/rule/slider.js b/src/config/rule/slider.js
new file mode 100644
index 0000000..c3cf4ca
--- /dev/null
+++ b/src/config/rule/slider.js
@@ -0,0 +1,44 @@
+import uniqueId from '@form-create/utils/lib/unique';
+import {makeRequiredRule} from '../../utils';
+
+const label = '滑块';
+const name = 'slider';
+
+export default {
+ icon: 'icon-slider',
+ label,
+ name,
+ rule() {
+ return {
+ type: name,
+ field: uniqueId(),
+ title: label,
+ info: '',
+ props: {},
+ };
+ },
+ props() {
+ return [makeRequiredRule(), {type: 'inputNumber', field: 'min', title: '最小值'}, {
+ type: 'inputNumber',
+ field: 'max',
+ title: '最大值'
+ }, {type: 'switch', field: 'disabled', title: '是否禁用'}, {
+ type: 'inputNumber',
+ field: 'step',
+ title: '步长'
+ }, {type: 'switch', field: 'showInput', title: '是否显示输入框,仅在非范围选择时有效'}, {
+ type: 'switch',
+ field: 'showInputControls',
+ title: '在显示输入框的情况下,是否显示输入框的控制按钮',
+ value: true
+ }, {type: 'switch', field: 'showStops', title: '是否显示间断点'}, {
+ type: 'switch',
+ field: 'range',
+ title: '是否为范围选择'
+ }, {type: 'switch', field: 'vertical', title: '是否竖向模式'}, {
+ type: 'input',
+ field: 'height',
+ title: 'Slider 高度,竖向模式时必填'
+ }];
+ }
+};
diff --git a/src/config/rule/space.js b/src/config/rule/space.js
new file mode 100644
index 0000000..86c1f63
--- /dev/null
+++ b/src/config/rule/space.js
@@ -0,0 +1,41 @@
+const label = '间距';
+const name = 'div';
+
+export default {
+ icon: 'icon-space',
+ label,
+ name,
+ rule() {
+ return {
+ type: name,
+ wrap: {
+ show: false
+ },
+ native: false,
+ style: {
+ width: '100%',
+ height: '20px',
+ },
+ children: []
+ };
+ },
+ props() {
+ return [
+ {
+ type: 'object',
+ field: 'formCreateStyle',
+ native: true,
+ props: {
+ rule: [
+ {
+ type: 'input',
+ field: 'height',
+ title: 'height',
+ },
+ ]
+ }
+ }
+
+ ];
+ }
+};
\ No newline at end of file
diff --git a/src/config/rule/span.js b/src/config/rule/span.js
new file mode 100644
index 0000000..6d983e0
--- /dev/null
+++ b/src/config/rule/span.js
@@ -0,0 +1,33 @@
+const label = '文字';
+const name = 'span';
+
+export default {
+ icon: 'icon-span',
+ label,
+ name,
+ rule() {
+ return {
+ type: name,
+ title: '文字',
+ native: false,
+ children: ['这是一段文字'],
+ };
+ },
+ props() {
+ return [
+ {
+ type: 'input',
+ field: 'formCreateTitle',
+ title: 'title',
+ },
+ {
+ type: 'input',
+ field: 'formCreateChild',
+ title: '内容',
+ props: {
+ type: 'textarea'
+ }
+ }
+ ];
+ }
+};
\ No newline at end of file
diff --git a/src/config/rule/switch.js b/src/config/rule/switch.js
new file mode 100644
index 0000000..ca65ba3
--- /dev/null
+++ b/src/config/rule/switch.js
@@ -0,0 +1,39 @@
+import uniqueId from '@form-create/utils/lib/unique';
+import {makeRequiredRule} from '../../utils';
+
+const label = '开关';
+const name = 'switch';
+
+export default {
+ icon: 'icon-switch',
+ label,
+ name,
+ rule() {
+ return {
+ type: name,
+ field: uniqueId(),
+ title: label,
+ info: '',
+ props: {},
+ };
+ },
+ props() {
+ return [makeRequiredRule(), {type: 'switch', field: 'disabled', title: '是否禁用'}, {
+ type: 'inputNumber',
+ field: 'width',
+ title: '宽度(px)'
+ }, {type: 'input', field: 'activeText', title: 'switch 打开时的文字描述'}, {
+ type: 'input',
+ field: 'inactiveText',
+ title: 'switch 关闭时的文字描述'
+ }, {type: 'input', field: 'activeValue', title: 'switch 打开时的值'}, {
+ type: 'input',
+ field: 'inactiveValue',
+ title: 'switch 关闭时的值'
+ }, {type: 'input', field: 'activeColor', title: 'switch 打开时的背景色'}, {
+ type: 'input',
+ field: 'inactiveColor',
+ title: 'switch 关闭时的背景色'
+ }];
+ }
+};
diff --git a/src/config/rule/tab.js b/src/config/rule/tab.js
new file mode 100644
index 0000000..95a7b8a
--- /dev/null
+++ b/src/config/rule/tab.js
@@ -0,0 +1,36 @@
+const label = '标签页';
+const name = 'tab';
+
+export default {
+ icon: 'icon-tab',
+ label,
+ name,
+ children: 'tab-pane',
+ mask: false,
+ rule() {
+ return {
+ type: 'el-tabs',
+ style:'width:100%;',
+ children: []
+ };
+ },
+ props() {
+ return [{
+ type: 'select',
+ field: 'type',
+ title: '风格类型',
+ options: [{
+ label: 'card',
+ value: 'card'
+ }, {label: 'border-card', value: 'border-card'}]
+ }, {type: 'switch', field: 'closable', title: '标签是否可关闭'}, {
+ type: 'select',
+ field: 'tabPosition',
+ title: '选项卡所在位置',
+ options: [{label: 'top', value: 'top'}, {label: 'right', value: 'right'}, {
+ label: 'left',
+ value: 'left'
+ }]
+ }, {type: 'switch', field: 'stretch', title: '标签的宽度是否自撑开'}];
+ }
+};
diff --git a/src/config/rule/tabPane.js b/src/config/rule/tabPane.js
new file mode 100644
index 0000000..6656e58
--- /dev/null
+++ b/src/config/rule/tabPane.js
@@ -0,0 +1,29 @@
+const label = '标签页';
+const name = 'tab-pane';
+
+export default {
+ label,
+ name,
+ inside: true,
+ drag: true,
+ dragBtn: false,
+ mask: false,
+ rule() {
+ return {
+ type: 'el-tab-pane',
+ props: {label: '新标签页'},
+ children: []
+ };
+ },
+ props() {
+ return [{type: 'input', field: 'label', title: '选项卡标题'}, {
+ type: 'switch',
+ field: 'disabled',
+ title: '是否禁用'
+ }, {type: 'input', field: 'name', title: '与选项卡绑定值 value 对应的标识符,表示选项卡别名'}, {
+ type: 'switch',
+ field: 'lazy',
+ title: '标签是否延迟渲染'
+ }];
+ }
+};
diff --git a/src/config/rule/time.js b/src/config/rule/time.js
new file mode 100644
index 0000000..cda6b48
--- /dev/null
+++ b/src/config/rule/time.js
@@ -0,0 +1,57 @@
+import uniqueId from '@form-create/utils/lib/unique';
+import {makeRequiredRule} from '../../utils';
+
+const label = '时间选择器';
+const name = 'timePicker';
+
+export default {
+ icon: 'icon-time',
+ label,
+ name,
+ rule() {
+ return {
+ type: name,
+ field: uniqueId(),
+ title: label,
+ info: '',
+ props: {},
+ };
+ },
+ props() {
+ return [makeRequiredRule(), {
+ type: 'Struct',
+ field: 'pickerOptions',
+ title: '当前时间日期选择器特有的选项',
+ props: {defaultValue: {}}
+ }, {type: 'switch', field: 'readonly', title: '完全只读'}, {
+ type: 'switch',
+ field: 'disabled',
+ title: '禁用'
+ }, {type: 'switch', field: 'editable', title: '文本框可输入', value: true}, {
+ type: 'switch',
+ field: 'clearable',
+ title: '是否显示清除按钮',
+ value: true
+ }, {type: 'input', field: 'placeholder', title: '非范围选择时的占位内容'}, {
+ type: 'input',
+ field: 'startPlaceholder',
+ title: '范围选择时开始日期的占位内容'
+ }, {type: 'input', field: 'endPlaceholder', title: '范围选择时开始日期的占位内容'}, {
+ type: 'switch',
+ field: 'isRange',
+ title: '是否为时间范围选择'
+ }, {type: 'switch', field: 'arrowControl', title: '是否使用箭头进行时间选择'}, {
+ type: 'select',
+ field: 'align',
+ title: '对齐方式',
+ options: [{label: 'left', value: 'left'}, {label: 'center', value: 'center'}, {
+ label: 'right',
+ value: 'right'
+ }]
+ }, {type: 'input', field: 'prefixIcon', title: '自定义头部图标的类名'}, {
+ type: 'input',
+ field: 'clearIcon',
+ title: '自定义清空图标的类名'
+ }];
+ }
+};
diff --git a/src/config/rule/transfer.js b/src/config/rule/transfer.js
new file mode 100644
index 0000000..0a99bc8
--- /dev/null
+++ b/src/config/rule/transfer.js
@@ -0,0 +1,84 @@
+import uniqueId from '@form-create/utils/lib/unique';
+
+const label = '穿梭框';
+const name = 'el-transfer';
+
+const generateData = _ => {
+ const data = [];
+ for (let i = 1; i <= 15; i++) {
+ data.push({
+ key: i,
+ label: `备选项 ${i}`,
+ disabled: i % 4 === 0
+ });
+ }
+ return data;
+};
+
+export default {
+ icon: 'icon-transfer',
+ label,
+ name,
+ rule() {
+ return {
+ type: name,
+ field: uniqueId(),
+ title: label,
+ info: '',
+ props: {
+ data: generateData()
+ }
+ };
+ },
+ props() {
+ return [{
+ type: 'Struct',
+ field: 'data',
+ title: 'Transfer 的数据源',
+ props: {defaultValue: []}
+ }, {type: 'switch', field: 'filterable', title: '是否可搜索'}, {
+ type: 'input',
+ field: 'filterPlaceholder',
+ title: '搜索框占位符'
+ }, {
+ type: 'select',
+ field: 'targetOrder',
+ title: '右侧列表元素的排序策略',
+ info: '若为 original,则保持与数据源相同的顺序;若为 push,则新加入的元素排在最后;若为 unshift,则新加入的元素排在最前',
+ options: [{label: 'original', value: 'original'}, {
+ label: 'push',
+ value: 'push'
+ }, {label: 'unshift', value: 'unshift'}]
+ }, {
+ type: 'Struct',
+ field: 'titles',
+ title: '自定义列表标题',
+ props: {defaultValue: []}
+ }, {
+ type: 'Struct',
+ field: 'buttonTexts',
+ title: '自定义按钮文案',
+ props: {defaultValue: []}
+ }, {
+ type: 'Struct',
+ field: 'format',
+ title: '列表顶部勾选状态文案',
+ props: {defaultValue: {}}
+ }, {
+ type: 'Struct',
+ field: 'props',
+ title: '数据源的字段别名',
+ props: {defaultValue: {}}
+ }, {
+ type: 'Struct',
+ field: 'leftDefaultChecked',
+ title: '初始状态下左侧列表的已勾选项的 key 数组',
+ props: {defaultValue: []}
+ }, {
+ type: 'Struct',
+ field: 'rightDefaultChecked',
+ title: '初始状态下右侧列表的已勾选项的 key 数组',
+ props: {defaultValue: []}
+ }];
+ }
+};
\ No newline at end of file
diff --git a/src/config/rule/tree.js b/src/config/rule/tree.js
new file mode 100644
index 0000000..5184b7e
--- /dev/null
+++ b/src/config/rule/tree.js
@@ -0,0 +1,100 @@
+import uniqueId from '@form-create/utils/lib/unique';
+import {makeOptionsRule, makeRequiredRule} from '../../utils/index';
+
+const label = '树形控件';
+const name = 'tree';
+
+export default {
+ icon: 'icon-tree',
+ label,
+ name,
+ rule() {
+ return {
+ type: name,
+ field: uniqueId(),
+ title: label,
+ info: '',
+ effect: {
+ fetch: ''
+ },
+ props: {
+ props: {
+ label: 'label',
+ },
+ showCheckbox: true,
+ nodeKey: 'id',
+ data: [{
+ id: 1,
+ label: '一级 1',
+ children: [{
+ id: 4,
+ label: '二级 1-1',
+ children: [{
+ id: 9,
+ label: '三级 1-1-1'
+ }, {
+ id: 10,
+ label: '三级 1-1-2'
+ }]
+ }]
+ }, {
+ id: 2,
+ label: '一级 2',
+ children: [{
+ id: 5,
+ label: '二级 2-1'
+ }, {
+ id: 6,
+ label: '二级 2-2'
+ }]
+ }, {
+ id: 3,
+ label: '一级 3',
+ children: [{
+ id: 7,
+ label: '二级 3-1'
+ }, {
+ id: 8,
+ label: '二级 3-2'
+ }]
+ }]
+ },
+ };
+ },
+ props() {
+ return [
+ makeRequiredRule(),
+ makeOptionsRule('props.data', false),
+ {type: 'input', field: 'emptyText', title: '内容为空的时候展示的文本'}, {
+ type: 'Struct',
+ field: 'props',
+ title: '配置选项,具体看下表',
+ props: {defaultValue: {}}
+ }, {type: 'switch', field: 'renderAfterExpand', title: '是否在第一次展开某个树节点后才渲染其子节点', value: true}, {
+ type: 'switch',
+ field: 'defaultExpandAll',
+ title: '是否默认展开所有节点',
+ }, {
+ type: 'switch',
+ field: 'expandOnClickNode',
+ title: '是否在点击节点的时候展开或者收缩节点, 默认值为 true,如果为 false,则只有点箭头图标的时候才会展开或者收缩节点。',
+ value: true
+ }, {
+ type: 'switch',
+ field: 'checkOnClickNode',
+ title: '是否在点击节点的时候选中节点,默认值为 false,即只有在点击复选框时才会选中节点。'
+ }, {type: 'switch', field: 'autoExpandParent', title: '展开子节点的时候是否自动展开父节点', value: true}, {
+ type: 'switch',
+ field: 'checkStrictly',
+ title: '在显示复选框的情况下,是否严格的遵循父子不互相关联的做法,默认为 false'
+ }, {type: 'switch', field: 'accordion', title: '是否每次只打开一个同级树节点展开'}, {
+ type: 'inputNumber',
+ field: 'indent',
+ title: '相邻级节点间的水平缩进,单位为像素'
+ }, {type: 'input', field: 'iconClass', title: '自定义树节点的图标'}, {
+ type: 'input',
+ field: 'nodeKey',
+ title: '每个树节点用来作为唯一标识的属性,整棵树应该是唯一的'
+ }];
+ }
+};
diff --git a/src/config/rule/upload.js b/src/config/rule/upload.js
new file mode 100644
index 0000000..cb49be4
--- /dev/null
+++ b/src/config/rule/upload.js
@@ -0,0 +1,64 @@
+import uniqueId from '@form-create/utils/lib/unique';
+import {makeRequiredRule} from '../../utils';
+
+const label = '上传';
+const name = 'upload';
+
+export default {
+ icon: 'icon-upload',
+ label,
+ name,
+ rule() {
+ return {
+ type: name,
+ field: uniqueId(),
+ title: label,
+ info: '',
+ props: {
+ action: '',
+ onSuccess(res, file) {
+ file.url = res.data.url;
+ }
+ }
+ };
+ },
+ props() {
+ return [makeRequiredRule(), {
+ type: 'select',
+ field: 'uploadType',
+ title: '上传类型',
+ value: 'image',
+ options: [{label: '图片', value: 'image'}, {
+ label: '文件',
+ value: 'file'
+ }]
+ }, {type: 'input', field: 'action', title: '上传的地址(必填)'}, {
+ type: 'Struct',
+ field: 'headers',
+ title: '设置上传的请求头部',
+ props: {defaultValue: {}}
+ }, {type: 'switch', field: 'multiple', title: '是否支持多选文件'}, {
+ type: 'Struct',
+ field: 'data',
+ title: '上传时附带的额外参数',
+ props: {defaultValue: {}}
+ }, {type: 'input', field: 'name', title: '上传的文件字段名'}, {
+ type: 'switch',
+ field: 'withCredentials',
+ title: '支持发送 cookie 凭证信息'
+ }, {type: 'input', field: 'accept', title: '接受上传的文件类型(thumbnail-mode 模式下此参数无效)'}, {
+ type: 'switch',
+ field: 'autoUpload',
+ title: '是否在选取文件后立即进行上传',
+ value: true
+ }, {
+ type: 'switch',
+ field: 'disabled',
+ title: '是否禁用'
+ }, {
+ type: 'inputNumber',
+ field: 'limit',
+ title: '最大允许上传个数'
+ }];
+ }
+};
diff --git a/src/index.js b/src/index.js
new file mode 100644
index 0000000..823bc7a
--- /dev/null
+++ b/src/index.js
@@ -0,0 +1,56 @@
+import FcDesigner from './components/FcDesigner.vue';
+import DragTool from './components/DragTool.vue';
+import Struct from './components/Struct.vue';
+import Fetch from './components/Fetch.vue';
+import Validate from './components/Validate.vue';
+import DragBox from './components/DragBox.vue';
+import Required from './components/Required.vue';
+import TableOptions from './components/TableOptions.vue';
+import {designerForm} from './utils/form';
+import FcEditor from '@form-create/component-wangeditor';
+import './style/index.css';
+import draggable from 'vuedraggable/src/vuedraggable';
+import unique from '@form-create/utils/lib/unique';
+import {makeOptionsRule} from './utils/index';
+import formCreate from './utils/form';
+
+designerForm.component('draggable', draggable);
+designerForm.component('DragTool', DragTool);
+designerForm.component('DragBox', DragBox);
+designerForm.component('Validate', Validate);
+designerForm.component('Struct', Struct);
+designerForm.component('Fetch', Fetch);
+designerForm.component('Required', Required);
+designerForm.component('TableOptions', TableOptions);
+designerForm.component('FcEditor', FcEditor);
+formCreate.component('FcEditor', FcEditor);
+
+designerForm.register('_fc', {
+ init(fc, rule) {
+ rule._id = unique();
+ if (fc.repeat)
+ rule.field = unique();
+ if (fc.value) {
+ rule.effect._fc = false;
+ }
+ }
+});
+
+designerForm.register('_fc_tool', {
+ init(_, rule) {
+ rule.props.unique = unique();
+ }
+});
+
+const install = function (Vue) {
+ Vue.component('FcDesigner', FcDesigner);
+};
+
+FcDesigner.install = install;
+FcDesigner.makeOptionsRule = makeOptionsRule;
+FcDesigner.formCreate = formCreate;
+FcDesigner.designerForm = designerForm;
+
+export default FcDesigner;
+
+export {formCreate, designerForm, install};
diff --git a/src/style/fonts/fc-icons.woff b/src/style/fonts/fc-icons.woff
new file mode 100644
index 0000000000000000000000000000000000000000..830e21fff4163e32f4287fcb15246389fc6937b2
GIT binary patch
literal 5448
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
literal 0
HcmV?d00001
diff --git a/src/style/index.css b/src/style/index.css
new file mode 100644
index 0000000..270412e
--- /dev/null
+++ b/src/style/index.css
@@ -0,0 +1,138 @@
+@font-face {
+ font-family: "fc-icon";
+ src: url(fonts/fc-icons.woff) format('woff');
+}
+@font-face {
+ font-family: "fc-icon"; /* Project id */
+ src: url('fonts/iconfont.ttf') format('truetype');
+}
+.fc-icon {
+ font-family: "fc-icon" !important;
+ font-size: 16px;
+ font-style: normal;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+.icon-xingzhuang-tupian:before {
+ content: "\eb98";
+}
+.icon-add-child:before {
+ content: "\e789";
+}
+
+.icon-switch:before {
+ content: "\e77c";
+}
+
+.icon-tab:before {
+ content: "\e77b";
+}
+
+.icon-button:before {
+ content: "\e77e";
+}
+
+.icon-input:before {
+ content: "\e77f";
+}
+
+.icon-checkbox:before {
+ content: "\e780";
+}
+
+.icon-radio:before {
+ content: "\e781";
+}
+
+.icon-rate:before {
+ content: "\e782";
+}
+
+.icon-number:before {
+ content: "\e783";
+}
+
+.icon-upload:before {
+ content: "\e784";
+}
+
+.icon-cascader:before {
+ content: "\e785";
+}
+
+.icon-space:before {
+ content: "\e786";
+}
+
+.icon-color:before {
+ content: "\e787";
+}
+
+.icon-span:before {
+ content: "\e788";
+}
+
+.icon-alert:before {
+ content: "\e78a";
+}
+
+.icon-row:before {
+ content: "\e78b";
+}
+
+.icon-divider:before {
+ content: "\e78d";
+}
+
+.icon-select:before {
+ content: "\e78e";
+}
+
+.icon-transfer:before {
+ content: "\e78f";
+}
+
+.icon-editor:before {
+ content: "\e790";
+}
+
+.icon-slider:before {
+ content: "\e791";
+}
+
+.icon-tree:before {
+ content: "\e792";
+}
+
+.icon-date:before {
+ content: "\e793";
+}
+
+.icon-time:before {
+ content: "\e794";
+}
+
+.icon-delete:before {
+ content: "\e770";
+}
+
+.icon-copy:before {
+ content: "\e771";
+}
+
+.icon-import:before {
+ content: "\e773";
+}
+
+.icon-add:before {
+ content: "\e774";
+}
+
+.icon-preview:before {
+ content: "\e776";
+}
+
+.icon-move:before {
+ content: "\e777";
+}
+
diff --git a/src/utils/form.js b/src/utils/form.js
new file mode 100644
index 0000000..8a181c1
--- /dev/null
+++ b/src/utils/form.js
@@ -0,0 +1,9 @@
+import formCreate from '@form-create/element-ui';
+
+const viewForm = formCreate;
+
+const designerForm = formCreate.factory();
+
+export default viewForm;
+
+export {designerForm};
diff --git a/src/utils/index.js b/src/utils/index.js
new file mode 100644
index 0000000..c6bfea2
--- /dev/null
+++ b/src/utils/index.js
@@ -0,0 +1,132 @@
+import is, {hasProperty} from '@form-create/utils/lib/type';
+import {parseFn} from '@form-create/utils/lib/json';
+
+export function makeRequiredRule() {
+ return {
+ type: 'Required', field: 'formCreate$required', title: '是否必填'
+ };
+}
+
+export function makeOptionsRule(to, flag) {
+ const options = [
+ {'label': 'JSON数据', 'value': 0},
+ {'label': '接口数据', 'value': 1},
+ ];
+
+ const control = [
+ {
+ value: 0,
+ rule: [
+ {
+ type: 'Struct',
+ field: 'formCreate' + upper(to).replace('.', '>'),
+ props: {defaultValue: []}
+ },
+ ],
+ },
+ {
+ value: 1,
+ rule: [
+ {
+ type: 'Fetch',
+ field: 'formCreateEffect>fetch',
+ props: {
+ to
+ }
+ }
+ ]
+ }
+ ];
+
+ if (flag !== false) {
+ options.splice(0, 0, {'label': '静态数据', 'value': 2});
+ control.push({
+ value: 2,
+ rule: [
+ {
+ type: 'TableOptions',
+ field: 'formCreate' + upper(to).replace('.', '>'),
+ props: {defaultValue: []}
+ },
+ ],
+ });
+ }
+
+ return {
+ type: 'radio',
+ title: '选项数据',
+ field: '_optionType',
+ value: flag !== false ? 2 : 0,
+ options,
+ props: {
+ type: 'button'
+ },
+ control
+ };
+}
+
+export function upper(str) {
+ return str.replace(str[0], str[0].toLocaleUpperCase());
+}
+
+
+export const toJSON = function (val) {
+ const type = /object ([a-zA-Z]*)/.exec(Object.prototype.toString.call(val));
+ if (type && _toJSON[type[1].toLowerCase()]) {
+ return _toJSON[type[1].toLowerCase()](val);
+ } else {
+ return val;
+ }
+};
+
+const _toJSON = {
+ object: function (val) {
+ var json = [];
+ for (var i in val) {
+ if (!hasProperty(val, i)) continue;
+ json.push(
+ toJSON(i) + ': ' +
+ ((val[i] != null) ? toJSON(val[i]) : 'null')
+ );
+ }
+ return '{\n ' + json.join(',\n ') + '\n}';
+ },
+ array: function (val) {
+ for (var i = 0, json = []; i < val.length; i++)
+ json[i] = (val[i] != null) ? toJSON(val[i]) : 'null';
+ return '[' + json.join(', ') + ']';
+ },
+ string: function (val) {
+ var tmp = val.split('');
+ for (var i = 0; i < tmp.length; i++) {
+ var c = tmp[i];
+ (c >= ' ') ?
+ (c === '\\') ? (tmp[i] = '\\\\') :
+ (c === '"') ? (tmp[i] = '\\"') : 0 :
+ (tmp[i] =
+ (c === '\n') ? '\\n' :
+ (c === '\r') ? '\\r' :
+ (c === '\t') ? '\\t' :
+ (c === '\b') ? '\\b' :
+ (c === '\f') ? '\\f' :
+ (c = c.charCodeAt(), ('\\u00' + ((c > 15) ? 1 : 0) + (c % 16)))
+ );
+ }
+ return '"' + tmp.join('') + '"';
+ }
+};
+
+export const deepParseFn = function (target) {
+ for (let key in target) {
+ if (Object.prototype.hasOwnProperty.call(target, key)) {
+ let data = target[key];
+ if (Array.isArray(data) || is.Object(data)) {
+ deepParseFn(data);
+ }
+ if (is.String(data)) {
+ target[key] = parseFn(data);
+ }
+ }
+ }
+ return target;
+};
diff --git a/tools/cli/run.ts b/tools/cli/run.ts
new file mode 100644
index 0000000..89122da
--- /dev/null
+++ b/tools/cli/run.ts
@@ -0,0 +1,61 @@
+/*
+ * @Author : djkloop
+ * @Date : 2021-09-15 15:13:17
+ * @LastEditors : djkloop
+ * @LastEditTime : 2021-09-19 16:10:22
+ * @Description : 头部注释
+ * @FilePath : /form-create2/tools/cli/run.ts
+ */
+import {program} from 'commander';
+import path from 'path';
+import chalk from 'chalk';
+import build from '../lib/build';
+// pkgUrl
+const log = console.log
+const commandExecUrl = process.cwd()
+log()
+log(' ' + chalk.green('command run path with: ', commandExecUrl))
+log()
+const pkgUrl = path.join(commandExecUrl, '/lerna.json');
+
+program.on('--help', () => {
+ log();
+ log(chalk.blue.bold(' Usage:'), chalk.cyan.bold('tools build tools with Node 👍 ~'));
+ log();
+})
+
+/// tools 版本
+program
+ .version(`@form-create/tools v${require(pkgUrl).version}`, '-v, --version', 'tools versions')
+
+program
+ .command('build [flag]')
+ .description('build components && packages || build components || build packages')
+ .option('-a,--all', 'Build @form-create/[all]packages') /// 默认打包components和packages
+ .option('-c, --components ', 'Build @form-create/component- package or packages array') // 打单独的组件
+ .option('-p, --packages ', 'Build @form-create/ package or packages array') // 打单独的包
+ .action((_: any, cmd: any) => build(_, cleanArgs(cmd)));
+
+program.parse(process.argv);
+
+
+
+// code with vue-cli: https://github.com/vuejs/vue-cli/blob/dev/packages/%40vue/cli/bin/vue.js#L275
+function camelize(str: string) {
+ return str.replace(/-(\w)/g, (_, c) => c ? c.toUpperCase() : '')
+}
+
+// commander passes the Command object itself as options,
+// extract only actual options into a fresh object.
+function cleanArgs(cmd: any) {
+ const args: any = {}
+ cmd.options.forEach((o: any) => {
+ const key = camelize(o.long.replace(/^--/, ''))
+ // if an option is not present and Command has a method with the same name
+ // it should not be copied
+ if (typeof cmd[key] !== 'function' && typeof cmd[key] !== 'undefined') {
+ args[key] = cmd[key]
+ }
+ })
+ return args
+}
\ No newline at end of file
diff --git a/tools/lib/build.ts b/tools/lib/build.ts
new file mode 100644
index 0000000..450cbad
--- /dev/null
+++ b/tools/lib/build.ts
@@ -0,0 +1,163 @@
+/*
+ * @Author : djkloop
+ * @Date : 2020-08-15 17:21:22
+ * @LastEditors : djkloop
+ * @LastEditTime : 2021-10-04 19:33:38
+ * @Description : 头部注释
+ * @FilePath : /form-create2/tools/lib/build.ts
+ */
+import chalk from 'chalk';
+import ora from 'ora';
+import dayjs from 'dayjs';
+import fs from 'fs';
+import { exit } from 'process';
+import shell from 'shelljs';
+import createBuildComponents from './components';
+import createBuildPackages from './packages';
+import { blue, getFolderNames, getSingleComponentPaths, getSinglePackagePaths, red, targets as getAllTargetsPath, yellow } from './utils'
+
+
+let spinner
+const log = console.log
+const context = process.cwd()
+
+
+async function buildAllComponents(paths: string[] = []) {
+ let componentsPathsObject = Object.create(null)
+ paths.forEach((comPath: string) => {
+ const [name, cname] = comPath.split('/')
+ const componentsPaths = getSingleComponentPaths('components', name, cname)
+
+ if (!componentsPathsObject[name]) {
+ componentsPathsObject[name] = componentsPaths[name]
+ } else {
+ componentsPathsObject[name] = [...componentsPathsObject[name], ...componentsPaths[name]]
+ }
+ });
+ await createBuildComponents(componentsPathsObject)
+ await exit();
+}
+
+
+async function createBuildTask(args: any) {
+ const isAll = args.all || Object.keys(args).length === 0
+ const isComponentsAll = args?.components?.includes('all')
+ const isPackagesAll = args?.packages?.includes('all')
+ let tips = '';
+ if (isAll) {
+ tips = 'build all components and all packages'
+ } else if (isComponentsAll) {
+ tips = 'build all components'
+ } else if (isPackagesAll) {
+ tips = 'build all packages'
+ } else {
+ tips = ' build task time' + ' ' + dayjs().format('YYYY-MM-DD HH:mm:ss') + '\n'
+ }
+ yellow(tips, true)
+ blue(' ---------------------- start ----------------------\n', true)
+ /// not all components
+ if (!isComponentsAll && args?.components?.length) {
+ const libs = args?.components
+ if (libs.length === 1) {
+ /// 先切包名
+ const lib = libs[0];
+ /// 单包下存在多个包
+ if (lib.includes('*') || !lib.includes('/')) {
+ /// xxx/*
+ const [name] = !lib.includes('/') ? [lib] : lib.split('/')
+ const _p = getFolderNames('components', name)
+ buildAllComponents(_p)
+ } else {
+ const [name, cname] = lib.split('/')
+ const componentsPaths = getSingleComponentPaths('components', name, cname)
+ await createBuildComponents(componentsPaths)
+ await exit();
+ }
+ } else {
+ const compsPaths = args?.components;
+ const allPaths = compsPaths.filter(cp => cp.includes('*') || !cp.includes('/'));
+ const fixPaths = compsPaths.filter(cp => !cp.includes('*') && cp.includes('/'));
+ let _all_ = [...fixPaths]
+ if (allPaths.length) {
+ allPaths.forEach(allp => {
+ const [name] = !allp.includes('/') ? [allp] : allp.split('/')
+ const _p = getFolderNames('components', name)
+ _all_ = [..._all_, ..._p]
+ });
+ }
+ buildAllComponents(_all_)
+ }
+ }
+
+ if (!isPackagesAll && args?.packages?.length) {
+ const libs = args?.packages
+ if (libs.length === 1) {
+ /// 先切包名
+ const lib = libs[0];
+ const [name] = lib.split('/')
+ const packagesAllPaths = getSinglePackagePaths('packages', name)
+ await createBuildPackages(packagesAllPaths)
+ await exit();
+ } else {
+ let componentsPathsObject = Object.create(null)
+ libs.forEach(async lib => {
+ const componentsPaths = getSinglePackagePaths('packages', lib)
+ componentsPathsObject[lib] = componentsPaths[lib]
+ });
+ await createBuildPackages(componentsPathsObject)
+ await exit();
+ }
+ }
+
+ /// 如果是打包全部
+ if (isAll) {
+ /// 先打对应的依赖components
+ const componentsAllPaths = getAllTargetsPath('components')
+ const packagesAllPaths = getAllTargetsPath('packages')
+ if (!Object.keys(componentsAllPaths).length && !Object.keys(packagesAllPaths).length) {
+ yellow('\n no build components and packages task! please check buildFormCreateOptions or private with components/*/*/package.json \n')
+ exit(1);
+ }
+ if (!Object.keys(componentsAllPaths).length) {
+ yellow('\n no build components task! please check buildFormCreateOptions or private with components/*/*/package.json \n')
+ }
+ if (!Object.keys(packagesAllPaths).length) {
+ yellow('\n no build packages task! please check buildFormCreateOptions or private with packages/*/package.json \n')
+ }
+ /// 打印对应的组件
+ await createBuildComponents(componentsAllPaths)
+ /// 再打对应的包
+ await createBuildPackages(packagesAllPaths)
+ /// 退出
+ await exit();
+ } else {
+
+ /// 单独打所有的component组件
+ if(isComponentsAll) {
+ const componentsAllPaths = getAllTargetsPath('components')
+ if (!Object.keys(componentsAllPaths).length) {
+ yellow('\n no build components task! please check buildFormCreateOptions or private with components/*/*/package.json \n')
+ await exit(1)
+ }
+
+ await createBuildComponents(componentsAllPaths)
+ await exit();
+ }
+
+ /// 单独打所有的package包
+ if (isPackagesAll) {
+ const packagesAllPaths = getAllTargetsPath('packages')
+ if (!Object.keys(packagesAllPaths).length) {
+ yellow('\n no build packages task! please check buildFormCreateOptions or private with packages/*/package.json \n')
+ await exit(1)
+ }
+
+ await createBuildPackages(packagesAllPaths)
+ await exit();
+ }
+ }
+}
+
+export default (_: any, args: any) => {
+ return createBuildTask(args)
+}
\ No newline at end of file
diff --git a/tools/lib/components.ts b/tools/lib/components.ts
new file mode 100644
index 0000000..5b1a884
--- /dev/null
+++ b/tools/lib/components.ts
@@ -0,0 +1,73 @@
+/**
+ * 打包components文件
+ */
+import type { Ora } from 'ora';
+import chalk from 'chalk';
+import ora from 'ora';
+import os from 'os';
+import execa from 'execa';
+import dayjs from 'dayjs';
+
+function sleep(ms) {
+ return new Promise((resolve) => {
+ setTimeout(resolve, ms);
+ });
+}
+
+
+let spinner: Ora;
+const build = async (target: string, comp: string, targetName: string) => {
+ dayjs().startOf('millisecond');
+ /// env 先写死
+ const env = 'production'
+ await execa(
+ 'rollup',
+ [
+ `-c`,
+ '--environment',
+ [
+ `NODE_ENV:${env}`,
+ `BUILD_TARGET:${targetName}`,
+ `BUILD_TARGET_COMP:${comp}`,
+ `BUILD_TYPE:component`,
+ `BUILD_TARGET_PATH:${target}`
+ ].filter(Boolean).join(',')
+ ],
+ { stdio: 'inherit' }
+ );
+ console.log('build task time' + ' ' + dayjs().format('YYYY-MM-DD HH:mm:ss'))
+}
+
+
+const runParallel = async (maxConcurrency: number, source: string[], buildName: string, iteratorFn: Function) => {
+ const ret = []
+ const executing = []
+ for (const item of source) {
+ const comp = item.split('/').pop()
+ const p = Promise.resolve().then(() => iteratorFn(item, comp, buildName))
+ ret.push(p)
+
+ if (maxConcurrency <= source.length) {
+ const e = p.then(() => executing.splice(executing.indexOf(e), 1))
+ executing.push(e)
+ if (executing.length >= maxConcurrency) {
+ await Promise.race(executing)
+ }
+ }
+ }
+ return Promise.all(ret)
+}
+
+const buildAll = async (comAllTargets) => {
+ await runParallel(os.cpus().length, comAllTargets[1], comAllTargets[0], build)
+}
+
+const createBuildComponents = async (cpaths: { [k: string]: any }) => {
+ /// 根据每个不同的ui库去生成每个ui库下面的不同的组件打包
+ const cps = Object.entries(cpaths)
+ for (const cpath of cps) {
+ await buildAll(cpath)
+ }
+}
+
+export default createBuildComponents
\ No newline at end of file
diff --git a/tools/lib/packages.ts b/tools/lib/packages.ts
new file mode 100644
index 0000000..08f35f1
--- /dev/null
+++ b/tools/lib/packages.ts
@@ -0,0 +1,88 @@
+/**
+ * 打包packages文件
+ */
+import type {Ora} from 'ora';
+import chalk from 'chalk';
+import ora from 'ora';
+import os from 'os';
+import execa from 'execa';
+import dayjs from 'dayjs';
+
+let spinner: Ora;
+const build = async (target: string, comp: string, targetName: string) => {
+ dayjs().startOf('millisecond');
+ spinner.text = chalk.bold.yellow(`start build ${targetName} ui \n`);
+ /// env 先写死
+ const env = 'production'
+ await execa(
+ 'rollup',
+ [
+ '-c',
+ '--environment',
+ [
+ `NODE_ENV:${env}`,
+ `BUILD_TARGET:${targetName}`,
+ `BUILD_TARGET_COMP:${comp}`,
+ 'BUILD_TYPE:packages',
+ `BUILD_TARGET_PATH:${target}`
+ ].filter(Boolean).join(',')
+ ],
+ {stdio: 'inherit'}
+ );
+ spinner.text = chalk.bold.green(`finished build ${targetName} ui time: ${dayjs().startOf('millisecond').format('SSS')}ms. \n `);
+}
+
+
+const runParallel = async (maxConcurrency: number, source: string[], buildName: string, iteratorFn: Function) => {
+ const ret = []
+ const executing = []
+ for (const item of source) {
+ const comp = item.split('/').pop()
+ const p = Promise.resolve().then(() => iteratorFn(item, comp, buildName))
+ ret.push(p)
+
+ if (maxConcurrency <= source.length) {
+ const e = p.then(() => executing.splice(executing.indexOf(e), 1))
+ executing.push(e)
+ if (executing.length >= maxConcurrency) {
+ await Promise.race(executing)
+ }
+ }
+ }
+ return Promise.all(ret)
+}
+
+const buildAll = async (comAllTargets) => {
+ await runParallel(os.cpus().length, comAllTargets[1], comAllTargets[0], build)
+}
+
+const _filter_current_url_ = (urls: Array) => {
+ const arr = []
+ urls.map((url) => {
+ const itemUrlLibName = url[0];
+ let itemUrlLibsUrl = '';
+ url[1].forEach((item, idx) => {
+ const suffix = item.split('/').pop()
+ if (suffix === itemUrlLibName) {
+ itemUrlLibsUrl = item
+ }
+ })
+ const item = [itemUrlLibName, [itemUrlLibsUrl]]
+ arr.push(item)
+ })
+ return arr
+}
+
+const createBuildPackages = async (cpaths: { [k: string]: any }) => {
+ const tips = chalk.redBright.bold('\n start build all packages \n')
+ spinner = ora(tips).start()
+ /// 根据每个不同的ui库去生成每个ui库下面的不同的组件打包
+ const cps = Object.entries(cpaths)
+ /// 处理下当前的url
+ const fCps = _filter_current_url_(cps)
+ for (const cpath of fCps) {
+ await buildAll(cpath)
+ }
+}
+
+export default createBuildPackages
diff --git a/tools/lib/paths.ts b/tools/lib/paths.ts
new file mode 100644
index 0000000..9fb7daa
--- /dev/null
+++ b/tools/lib/paths.ts
@@ -0,0 +1,14 @@
+import path from 'path';
+
+/// 项目目录
+export const projRoot = path.resolve(__dirname, '../../');
+/// 单独component目录
+export const compRoot = path.resolve(projRoot, './components');
+/// packages目录
+export const pkgRoot = path.resolve(projRoot, './packages');
+/// file - packages.json \\\
+export const pkgFileRoot = path.resolve(projRoot, './package.json');
+/// file - lerna.json \\\
+export const lernaFileRoot = path.resolve(projRoot, './lerna.json');
+/// file - rollup.config.js \\\
+export const rollupFileRoot = path.resolve(projRoot, './rollup.config.ts');
\ No newline at end of file
diff --git a/tools/lib/utils.ts b/tools/lib/utils.ts
new file mode 100644
index 0000000..a544066
--- /dev/null
+++ b/tools/lib/utils.ts
@@ -0,0 +1,140 @@
+import chalk from "chalk";
+import fs from "fs";
+import { projRoot } from "./paths";
+
+
+export function yellow(str: string, isBold: boolean = false) {
+ isBold ? console.log(chalk.bold.yellow(str)) : console.log(chalk.yellow(str))
+}
+
+export function green(str: string, isBold: boolean = false) {
+ isBold ? console.log(chalk.bold.green(str)) : console.log(chalk.green(str))
+}
+
+export function blue(str: string, isBold: boolean = false) {
+ isBold ? console.log(chalk.bold.blue(str)) : console.log(chalk.blue(str))
+}
+
+export function red(str: string, isBold: boolean = false) {
+ isBold ? console.log(chalk.bold.red(str)) : console.log(chalk.red(str))
+}
+
+export function errorAndExit(e) {
+ red(e.message)
+ process.exit(1)
+}
+
+
+export const targets = (dir: 'packages' | 'components' = 'packages') => {
+ const componentsAllPaths = Object.create(null);
+ const uiFoldersPath = fs.readdirSync(dir).filter(uiFolderPath => {
+ if (fs.statSync(`${projRoot}/${dir}/${uiFolderPath}`).isDirectory()) {
+ return true
+ }
+ })
+
+ // uiFoldersPath.forEach(uiPath => {
+ // const pkg = require(`${projRoot}/${dir}/${uiPath}/package.json`)
+ // if (pkg.private || !pkg.buildFormCreateOptions) {
+ // blue(`\n info: ${projRoot}/${dir}/${uiPath}/package.json private is true or buildFormCreateOptions is not exists!`)
+ // }
+ // })
+
+ if (dir === 'packages') {
+ const packagesFolderPath = []
+ for (let index = 0; index < uiFoldersPath.length; index++) {
+ const uiPath = uiFoldersPath[index];
+ if (!fs.statSync(`${projRoot}/${dir}/${uiPath}`).isDirectory()) {
+ continue;
+ }
+ const pkg = require(`${projRoot}/${dir}/${uiPath}/package.json`)
+ fs.rmdirSync(`${projRoot}/${dir}/${uiPath}/dist`, { recursive: true });
+ if (pkg.private || !pkg.buildFormCreateOptions) {
+ red(`\n info: ${projRoot}/${dir}/${uiPath}/package.json private is true or buildFormCreateOptions is not exists!`)
+ continue;
+ }
+ packagesFolderPath.push(`${projRoot}/${dir}/${uiPath}`)
+ if (packagesFolderPath.length) {
+ componentsAllPaths[uiPath] = packagesFolderPath
+ }
+ }
+ }
+
+ if (dir === 'components') {
+ uiFoldersPath.forEach(uiPath => {
+ const componentFolderPath = []
+ const alen = fs.readdirSync(`${projRoot}/${dir}/${uiPath}`).length
+ for (let index = 0; index < alen; index++) {
+ const comPath = fs.readdirSync(`${projRoot}/${dir}/${uiPath}`)[index];
+ if (!fs.statSync(`${projRoot}/${dir}/${uiPath}/${comPath}`).isDirectory()) {
+ continue;
+ }
+ const pkg = require(`${projRoot}/${dir}/${uiPath}/${comPath}/package.json`)
+ fs.rmdirSync(`${projRoot}/${dir}/${uiPath}/${comPath}/dist`, { recursive: true });
+ if (pkg.private || !pkg.buildFormCreateOptions) {
+ red(`\n info: ${projRoot}/${dir}/${uiPath}/${comPath}/package.json private is true or buildFormCreateOptions is not exists!`)
+ continue;
+ }
+ componentFolderPath.push(`${projRoot}/${dir}/${uiPath}/${comPath}`)
+ }
+ if (componentFolderPath.length) {
+ componentsAllPaths[uiPath] = componentFolderPath
+ }
+ })
+ }
+
+
+ return componentsAllPaths
+}
+
+
+export const getSingleComponentPaths = (dir: string = 'components', libname: string = '', comname: string = '') => {
+ const fpath = Object.create(null)
+ const _rootPath = dir
+ const _libPath = libname
+ const _compPath = comname
+
+ if (!fs.statSync(`${projRoot}/${_rootPath}/${_libPath}/${_compPath}`).isDirectory()) {
+ return
+ }
+
+ const pkg = require(`${projRoot}/${_rootPath}/${_libPath}/${_compPath}/package.json`)
+ fs.rmdirSync(`${projRoot}/${_rootPath}/${_libPath}/${_compPath}/dist`, { recursive: true });
+ if (pkg.private || !pkg.buildFormCreateOptions) {
+ red(`\n info: ${projRoot}/${_rootPath}/${_libPath}/${_compPath}/package.json private is true or buildFormCreateOptions is not exists!`)
+ return
+ }
+ fpath[_libPath] = [`${projRoot}/${_rootPath}/${_libPath}/${_compPath}`]
+
+ return fpath
+}
+
+export const getSinglePackagePaths = (dir: string = 'packages', libname: string = '') => {
+ const fpath = Object.create(null)
+ const _rootPath = dir
+ const _libPath = libname
+
+ if (!fs.statSync(`${projRoot}/${_rootPath}/${_libPath}`).isDirectory()) {
+ return
+ }
+
+ const pkg = require(`${projRoot}/${_rootPath}/${_libPath}/package.json`)
+ fs.rmdirSync(`${projRoot}/${_rootPath}/${_libPath}/dist`, { recursive: true });
+ if (pkg.private || !pkg.buildFormCreateOptions) {
+ red(`\n info: ${projRoot}/${_rootPath}/${_libPath}/package.json private is true or buildFormCreateOptions is not exists!`)
+ return
+ }
+ fpath[_libPath] = [`${projRoot}/${_rootPath}/${_libPath}`]
+
+ return fpath
+}
+
+/// Get all the folder names under the current folder
+export const getFolderNames = (folder: string, uiFolder: string) => {
+ return fs.readdirSync(`${folder}/${uiFolder}`).map(uiFolderPath => {
+ if (fs.statSync(`${projRoot}/${folder}/${uiFolder}`).isDirectory()) {
+ fs.rmdirSync(`${projRoot}/${folder}/${uiFolder}/dist`, { recursive: true });
+ return `${uiFolder}/${uiFolderPath}`
+ }
+ })
+}
\ No newline at end of file
diff --git a/tools/rollup/plugin/index.ts b/tools/rollup/plugin/index.ts
new file mode 100644
index 0000000..71c0eb4
--- /dev/null
+++ b/tools/rollup/plugin/index.ts
@@ -0,0 +1,69 @@
+/*
+ * @Author : djkloop
+ * @Date : 2021-09-19 13:53:31
+ * @LastEditors : djkloop
+ * @LastEditTime : 2021-09-19 14:11:52
+ * @Description : 头部注释
+ * @FilePath : /form-create2/tools/rollup/plugin/index.ts
+ */
+import vue from 'rollup-plugin-vue';
+import postcss from 'rollup-plugin-postcss';
+import { cssUrl } from '@sixian/css-url';
+import externals from 'rollup-plugin-node-externals';
+import nodeResolve from '@rollup/plugin-node-resolve';
+import commonjs from '@rollup/plugin-commonjs';
+import babel from '@rollup/plugin-babel';
+
+export const createRollupPlugins = () => {
+
+ const rollupPlugins = [
+ vue({
+ preprocessStyles: true,
+ })
+ ];
+
+ /// css settings
+ rollupPlugins.push(postcss({
+ minimize: true,
+ extract: false,
+ plugins: [
+ cssUrl({
+ imgExtensions: /\.(png|jpg|jpeg|gif|svg)$/,
+ fontExtensions: /\.(ttf|woff|woff2|eot)$/,
+ limit: 8192,
+ hash: false,
+ slash: false
+ })
+ ]
+ }));
+
+
+ /// devDependencies
+ rollupPlugins.push(externals({
+ devDeps: true
+ }));
+
+ /// j
+ rollupPlugins.push(nodeResolve({
+ extensions: ['.js', '.json', '.jsx', '.ts', '.tsx'],
+ preferBuiltins: true,
+ browser: true
+ }));
+
+ /// commonjs
+ rollupPlugins.push(commonjs());
+
+ rollupPlugins.push(babel({
+ babelHelpers: 'bundled',
+ exclude: 'node_modules/**',
+ extensions: ['.js', '.jsx', '.mjs', '.ts', '.tsx', '.vue'],
+ }));
+
+
+ // if (visualizer) {
+
+ // }
+
+
+ return rollupPlugins
+}
\ No newline at end of file
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..116a8d9
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,21 @@
+
+{
+ "compilerOptions": {
+ "target": "ESNext",
+ "sourceMap": true,
+ "allowUnreachableCode": true,
+ "allowSyntheticDefaultImports": true,
+ "allowJs": true,
+ "experimentalDecorators": true,
+ "moduleResolution": "node",
+ "noImplicitThis": true,
+ "noImplicitAny": false,
+ "importHelpers": true,
+ "jsx": "preserve"
+ },
+ "include": [
+ "*.vue",
+ "*",
+ "types/typing.d.ts"
+ ]
+}
\ No newline at end of file
diff --git a/types/index.d.ts b/types/index.d.ts
new file mode 100644
index 0000000..337be3b
--- /dev/null
+++ b/types/index.d.ts
@@ -0,0 +1,31 @@
+import {Rule} from "@form-create/element-ui";
+
+export interface MenuItem {
+ label: string,
+ name: string,
+ icon: string;
+}
+
+export interface Menu {
+ title: string;
+ name: string;
+ list: MenuItem[]
+}
+
+export interface MenuList extends Array