├── .DS_Store ├── .cz-config.js ├── .eslintignore ├── .eslintrc.js ├── .github └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── babel.config.js ├── examples ├── .DS_Store ├── App.vue ├── index.html └── main.js ├── gulpfile.js ├── package-lock.json ├── package.json ├── src ├── components │ ├── ColorPicker.vue │ ├── CustomAlert.vue │ ├── DragBox.vue │ ├── DragTool.vue │ ├── FcDesigner.vue │ ├── Fetch.vue │ ├── IconRefresh.vue │ ├── Required.vue │ ├── Struct.vue │ ├── TableOptions.vue │ └── Validate.vue ├── config │ ├── base │ │ ├── field.js │ │ ├── form.js │ │ └── validate.js │ ├── menu.js │ └── rule │ │ ├── alert.js │ │ ├── button.js │ │ ├── cascader.js │ │ ├── checkbox.js │ │ ├── col.js │ │ ├── color.js │ │ ├── date.js │ │ ├── divider.js │ │ ├── editor.js │ │ ├── index.js │ │ ├── input.js │ │ ├── number.js │ │ ├── radio.js │ │ ├── rate.js │ │ ├── row.js │ │ ├── select.js │ │ ├── slider.js │ │ ├── space.js │ │ ├── span.js │ │ ├── switch.js │ │ ├── tab.js │ │ ├── tabPane.js │ │ ├── time.js │ │ ├── transfter.js │ │ ├── tree.js │ │ └── upload.js ├── index.js ├── locale │ ├── en.js │ └── zh-cn.js ├── style │ ├── fonts │ │ └── fc-icons.woff │ └── index.css └── utils │ ├── form.js │ ├── index.js │ └── tabname.js ├── tsconfig.json ├── types └── index.d.ts ├── vite.config.build.js ├── vite.config.locale.js ├── vite.config.preview.js └── vue.config.js /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SX-Code/form-designer-naiveui/176f48e9d0d3bc22dcfe9bd0ad4ef17b453b5dab/.DS_Store -------------------------------------------------------------------------------- /.cz-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | types: [ 3 | {value: 'feat', name: 'feat: 新功能'}, 4 | {value: 'fix', name: 'fix: 修复'}, 5 | {value: 'docs', name: 'docs: 文档变更'}, 6 | {value: 'style', name: 'style: 代码格式(不影响代码运行的变动)'}, 7 | {value: 'cli', name: 'cli: 脚手架优化(不影响代码运行的变动)'}, 8 | {value: 'refactor', name: 'refactor: 重构(既不是增加feature,也不是修复bug)'}, 9 | {value: 'perf', name: 'perf: 性能优化'}, 10 | {value: 'test', name: 'test: 增加测试'}, 11 | {value: 'chore', name: 'chore: 构建过程或辅助工具的变动'}, 12 | {value: 'revert', name: 'revert: 回退'}, 13 | {value: 'build', name: 'build: 打包'} 14 | ], 15 | // override the messages, defaults are as follows 16 | messages: { 17 | type: '请选择提交类型:', 18 | scope: '请输入文件修改范围(可选):', 19 | // used if allowCustomScopes is true 20 | customScope: '请输入修改范围(可选):', 21 | subject: '请简要描述提交(必填):', 22 | body: '请输入详细描述(可选,待优化去除,跳过即可):', 23 | // breaking: 'List any BREAKING CHANGES (optional):\n', 24 | footer: '请输入要关闭的issue(待优化去除,跳过即可):', 25 | confirmCommit: '确认使用以上信息提交?(y/n/e/h)' 26 | }, 27 | allowCustomScopes: true, 28 | // allowBreakingChanges: ['feat', 'fix'], 29 | skipQuestions: ['body', 'footer'], 30 | // limit subject length, commitlint默认是72 31 | subjectLimit: 72 32 | } -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | **/dist 4 | **/node_modules 5 | **/examples 6 | **/*.d.ts 7 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 'env': { 3 | 'browser': true, 4 | 'node': true, 5 | 'es6': true, 6 | 'jest': true, 7 | 'commonjs': true 8 | }, 9 | 'extends': [ 10 | 'eslint:recommended', 11 | 'plugin:vue/essential', 12 | ], 13 | 'parserOptions': { 14 | 'ecmaVersion': 2018, 15 | 'sourceType': 'module', 16 | 'ecmaFeatures': { 17 | 'experimentalObjectRestSpread': true, 18 | 'jsx': true 19 | }, 20 | 'parser': 'babel-eslint', 21 | }, 22 | 'plugins': [ 23 | 'vue' 24 | ], 25 | 'rules': { 26 | 'indent': [ 27 | 'error', 28 | 4 29 | ], 30 | 'quotes': [ 31 | 'error', 32 | 'single' 33 | ], 34 | 'block-spacing': 'error', 35 | 'no-unused-vars': 'warn', 36 | 'object-curly-spacing': 'error', 37 | 'no-console': 'warn', 38 | 'vue/valid-v-model': 'warn', 39 | 'vue/no-template-key': 'warn', 40 | 'vue/valid-v-for': 'warn', 41 | 'vue/require-v-for-key': 'warn', 42 | } 43 | }; 44 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | stats.html 8 | 9 | # Runtime data 10 | pids 11 | *.pid 12 | *.seed 13 | *.pid.lock 14 | 15 | # Directory for instrumented libs generated by jscoverage/JSCover 16 | lib-cov 17 | 18 | # Coverage directory used by tools like istanbul 19 | coverage 20 | 21 | # nyc test coverage 22 | .nyc_output 23 | 24 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 25 | .grunt 26 | 27 | # Bower dependency directory (https://bower.io/) 28 | bower_components 29 | 30 | # node-waf configuration 31 | .lock-wscript 32 | 33 | # Compiled binary addons (https://nodejs.org/api/addons.html) 34 | build/Release 35 | 36 | # Dependency directories 37 | node_modules/ 38 | jspm_packages/ 39 | 40 | # TypeScript v1 declaration files 41 | typings/ 42 | 43 | # Optional npm cache directory 44 | .npm 45 | 46 | # Optional eslint cache 47 | .eslintcache 48 | 49 | # Optional REPL history 50 | .node_repl_history 51 | 52 | # Output of 'npm pack' 53 | *.tgz 54 | 55 | # Yarn Integrity file 56 | .yarn-integrity 57 | 58 | # dotenv environment variables file 59 | .env 60 | 61 | # next.js build output 62 | .next 63 | .idea 64 | 65 | # custom 66 | yarn.lock 67 | /index.html 68 | dist 69 | locale -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 更新说明 2 | 3 | ### 3.1.3(2023.03.18) 4 | 5 | - 优化 `Struct` 组件 6 | 7 | ### 3.1.2(2023.03.17) 8 | 9 | - 增加 `config.showFormConfig` 配置项,控制是否显示表单配置 10 | - 增加 `config.showConfig` 配置项,是否隐藏右侧配置栏 11 | - 增加 `childrenLen` 配置子组件初始生成几个 12 | - 优化 `setOption` 方法 13 | - 优化必填功能 14 | - 优化 `validate` 配置 15 | 16 | ### 3.1.1(2023.01.31) 17 | 18 | - 新增 watch 配置项 19 | - 修复 select 组件选择多选后页面卡死问题 20 | - 优化 setRule 方法 21 | - select 组件支持配置远程搜索 22 | 23 | ### 3.1.0 24 | 25 | - 支持多语言 26 | - 优化 ts 27 | - 优化数字组件输入范围 28 | - 修复验证规则类型不能修改问题 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 xaboy 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. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # form-create-designer-naiveui 2 | 3 | **这个是 Vue3 版本** 4 | 5 | **form-create-designer-naiveui 是基于 [@form-create/naive-ui](https://github.com/xaboy/form-create) vue3版本实现的表单设计器组件。可以通过拖拽的方式快速创建表单,提高开发者对表单的开发效率,节省开发者的时间。** 6 | 7 | **[form-create-designer](https://github.com/xaboy/form-create) 是基于 [@form-create/element-ui](https://github.com/xaboy/form-create) 开发的表单设计器,本项目更换原项目的UI框架为 [Naive UI](https://www.naiveui.com) ,做出的更改如下:** 8 | 9 | - Element Plus v2.0.1 -> Naive UI v2.34.3 10 | - codemirror v5.60.0 -> v6.0.1 11 | - 自定义ColorPicker组件,便于定制组件颜色 12 | - 更新部分组件为Vue 3版本 13 | 14 | **[文档](http://designer.form-create.com/guide/) | [在线演示](http://web.sxcode.rr.nu/form-designer) | [form-create 文档](http://form-create.com/v3/guide/)** 15 | 16 | > 如果对您有帮助,您可以点右上角 "Star" 支持一下 谢谢!本项目可继续完善,如有任何建议或问题[请在这里提出](https://github.com/SX-Code/form-designer-naiveui/issues) 17 | 18 | 19 | 20 | 21 | ![demo1](https://gcore.jsdelivr.net/gh/sx-code/tuchuang@main/form-create-designer/designer-review.png) 22 | 23 | ## 引入 24 | 25 | **NodeJs:** 26 | 27 | ```shell 28 | npm i form-designer-naiveui 29 | ``` 30 | 31 | 请自行导入`NaiveUI`并挂载 32 | 33 | ```js 34 | import formCreate from '@form-create/naive-ui' 35 | import FcDesigner from 'form-designer-naiveui' 36 | 37 | app.use(formCreate) 38 | app.use(FcDesigner) 39 | ``` 40 | 41 | ## 使用 42 | 43 | ```html 44 | 45 | ``` 46 | 47 | ## 设置多语言 48 | 通过 locale 配置项设置语言 49 | 50 | ```vue 51 | 54 | 55 | 65 | ``` 66 | 67 | ## 组件`props` 68 | 69 | - **menu**`MenuList` 重新配置拖拽的组件 70 | 71 | - **height**`int|string` 设计器组件高度, 默认`100%` 72 | 73 | - **locale**`object` 设置多语言 74 | 75 | - **config**`Config` 设置多语言 76 | 77 | - **mask** `boolean` 设置拖拽表单中的组件是否可以操作 78 | 79 | ## 组件方法 80 | 81 | - 获取当前生成表单的生成规则 82 | 83 | ```ts 84 | type getRule = () => Rule[] 85 | ``` 86 | **示例: `this.$refs.designer.getRule()`** 87 | 88 | - 获取当前表单的全局配置 89 | 90 | ```ts 91 | type getOption = () => Object 92 | ``` 93 | 94 | - 设置当前生成表单的规则 95 | 96 | ```ts 97 | type setRule = (rules: Rule[]) => void; 98 | ``` 99 | 100 | - 设置当前表单的全局配置 101 | 102 | ```ts 103 | type setOption = (option: Object) => void; 104 | ``` 105 | 106 | - 增加一组拖拽组件 107 | 108 | ```ts 109 | type addMenu = (menu: Menu) => void; 110 | ``` 111 | - 删除一组拖拽组件 112 | 113 | ```ts 114 | type removeMenu = (name: string) => void; 115 | ``` 116 | 117 | - 批量覆盖插入拖拽组件 118 | 119 | ```ts 120 | type setMenuItem = (name: string, items: MenuItem[]) => void; 121 | ``` 122 | 123 | - 插入一个拖拽组件到分组 124 | 125 | ```ts 126 | type appendMenuItem = (name:string, item: MenuItem) => void; 127 | ``` 128 | 129 | - 删除一个拖拽组件 130 | 131 | ```ts 132 | type removeMenuItem = (item: string | MenuItem) => void; 133 | ``` 134 | 135 | - 新增一个拖拽组件的生成规则 136 | 137 | ```ts 138 | type addComponent = (item: DragRule) => void; 139 | ``` 140 | > **提示! 内置的三个组件分组`name`分别为: `main`,`aide`,`layout`** 141 | 142 | ## 联系 143 | 144 | ##### email : 2627311935@qq.com 145 | 146 | ## License 147 | 148 | [MIT](http://opensource.org/licenses/MIT) 149 | 150 | Copyright (c) 2021-present xaboy 151 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 'presets': [['@vue/cli-plugin-babel/preset', {'useBuiltIns': false}]], 3 | 'plugins': ['@vue/babel-plugin-jsx'] 4 | } 5 | -------------------------------------------------------------------------------- /examples/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SX-Code/form-designer-naiveui/176f48e9d0d3bc22dcfe9bd0ad4ef17b453b5dab/examples/.DS_Store -------------------------------------------------------------------------------- /examples/App.vue: -------------------------------------------------------------------------------- 1 | 43 | 44 | 250 | 251 | 335 | -------------------------------------------------------------------------------- /examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | form-create-designer 示例 6 | 7 | 8 |
9 |
10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue'; 2 | import formCreate from '@form-create/naive-ui'; 3 | import App from './App.vue'; 4 | import FcDesigner from '../src/index'; 5 | import { 6 | create, 7 | NLayout, 8 | NLayoutContent, 9 | NLayoutSider, 10 | NLayoutHeader, 11 | NButton, 12 | NPopconfirm, 13 | NSpace, 14 | NRow, 15 | NCol, 16 | NForm, 17 | NDivider, 18 | NModal, 19 | NFormItem, 20 | NRadio, 21 | NRadioGroup, 22 | NInput, 23 | NSwitch, 24 | NSelect, 25 | NInputNumber, 26 | NPopover, 27 | NIcon, 28 | NGrid, 29 | NGridItem, 30 | NRadioButton, 31 | NDataTable, 32 | NCheckboxGroup, 33 | NCheckbox, 34 | NSkeleton, 35 | NTimePicker, 36 | NDatePicker, 37 | NConfigProvider, 38 | NSlider, 39 | NRate, 40 | NColorPicker, 41 | NCascader, 42 | NUpload, 43 | NText, 44 | NP, 45 | NUploadDragger, 46 | NTransfer, 47 | NTree, 48 | NAlert, 49 | NTooltip, 50 | NTabs, 51 | NTabPane, 52 | NTab, 53 | } from 'naive-ui'; 54 | 55 | const naive = create({ 56 | components: [NLayout, NLayoutContent, NLayoutSider, NLayoutHeader, 57 | NButton, NPopconfirm, NSpace, NRow, NCol, NForm, NDivider, NModal, 58 | NFormItem, NRadio, NRadioGroup, NInput, NSwitch, NSelect, NInputNumber, 59 | NPopover, NIcon, NGrid, NGridItem, NRadioButton, NDataTable, NCheckboxGroup, 60 | NCheckbox, NSkeleton, NTimePicker, NDatePicker, NConfigProvider, NSlider, NRate, 61 | NColorPicker, NCascader, NUpload, NText, NP, NUploadDragger, NTransfer, NTree, 62 | NAlert, NTooltip, NTabs, NTabPane, NTab] 63 | }) 64 | 65 | const app = createApp(App); 66 | app.use(naive, { size: 'small' }); 67 | app.use(formCreate); 68 | app.use(FcDesigner); 69 | 70 | 71 | app.mount('#app') 72 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp'); 2 | const execa = require('execa'); 3 | const fs = require('fs'); 4 | 5 | gulp.task('default', async function (cb) { 6 | await execa('node_modules/.bin/rimraf', ['locale']); 7 | fs.readdirSync('src/locale').forEach(async function (file) { 8 | const res = /^(.*)\.js$/.exec(file); 9 | if (res) { 10 | await execa('./node_modules/.bin/vite', ['build', '--config', './vite.config.locale.js', '-m', res[1]]); 11 | } 12 | cb(); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "form-designer-naiveui", 3 | "version": "1.0.9", 4 | "description": "好用的vue可视化表单设计器组件", 5 | "unpkg": "./dist/index.umd.js", 6 | "jsdelivr": "./dist/index.umd.js", 7 | "typings": "./types/index.d.ts", 8 | "main": "./dist/index.umd.js", 9 | "module": "./dist/index.es.js", 10 | "exports": { 11 | ".": { 12 | "import": "./dist/index.es.js", 13 | "require": "./dist/index.umd.js" 14 | }, 15 | "./locale/en" : { 16 | "import": "./locale/en.mjs", 17 | "require": "./locale/en.umd.js" 18 | }, 19 | "./locale/zh-cn": { 20 | "import": "./locale/zh-cn.mjs", 21 | "require": "./locale/zh-cn.umd.js" 22 | } 23 | }, 24 | "scripts": { 25 | "clean": "rimraf dist/", 26 | "dev": "vue-cli-service serve", 27 | "rollup": "rollup -c ./rollup.config.ts", 28 | "build": "vite build --config ./vite.config.build.js", 29 | "build:locale": "gulp -f gulpfile.js", 30 | "build:preview": "vite build --config ./vite.config.preview.js" 31 | }, 32 | "repository": { 33 | "type": "git", 34 | "url": "git+https://github.com/sx-code/form-designer-naiveui.git" 35 | }, 36 | "keywords": [ 37 | "表单设计器", 38 | "@form-create", 39 | "form-builder", 40 | "form-designer", 41 | "draggable", 42 | "form", 43 | "components", 44 | "vue3", 45 | "naive-ui", 46 | "json-form", 47 | "dynamic-form" 48 | ], 49 | "files": [ 50 | "README.md", 51 | "package.json", 52 | "LICENSE", 53 | "CHANGELOG.md", 54 | "src", 55 | "types", 56 | "dist", 57 | "locale" 58 | ], 59 | "author": "swcode", 60 | "license": "MIT", 61 | "bugs": { 62 | "url": "https://github.com/sx-code/form-designer-naiveui/issues" 63 | }, 64 | "homepage": "http://designer.form-create.com", 65 | "publishConfig": { 66 | "access": "public" 67 | }, 68 | "devDependencies": { 69 | "@element-plus/icons-vue": "^0.2.6", 70 | "@sixian/css-url": "^1.0.3", 71 | "@types/chalk": "^2.2.0", 72 | "@types/shelljs": "^0.8.9", 73 | "@vitejs/plugin-vue": "^3.1.2", 74 | "@vitejs/plugin-vue-jsx": "^2.0.1", 75 | "@vue/babel-plugin-jsx": "^1.0.7", 76 | "@vue/cli-plugin-babel": "^4.5.13", 77 | "@vue/cli-service": "^4.5.3", 78 | "@vue/compiler-sfc": "^3.0.11", 79 | "babel-eslint": "^10.1.0", 80 | "chalk": "^4.1.2", 81 | "commander": "^6.0.0", 82 | "commitizen": "^4.1.2", 83 | "cross-env": "^7.0.2", 84 | "css-loader": "^4.2.1", 85 | "cssnano": "^5.1.13", 86 | "cssnano-preset-advanced": "^5.3.8", 87 | "cz-conventional-changelog": "^3.2.0", 88 | "cz-customizable": "^6.3.0", 89 | "dayjs": "^1.10.7", 90 | "eslint": "^7.7.0", 91 | "eslint-plugin-vue": "^6.2.2", 92 | "esno": "^0.9.1", 93 | "execa": "^5.1.1", 94 | "fast-glob": "^3.2.7", 95 | "figlet": "^1.5.0", 96 | "fs-extra": "^10.0.0", 97 | "gulp": "^4.0.2", 98 | "html-webpack-plugin": "^4.3.0", 99 | "humps": "^2.0.1", 100 | "husky": "^4.2.5", 101 | "jsonlint-mod": "^1.7.6", 102 | "lint-staged": "^10.2.11", 103 | "naive-ui": "^2.34.3", 104 | "npm-run-all": "^4.1.5", 105 | "ora": "^5.0.0", 106 | "postcss": "^8.4.17", 107 | "rimraf": "^3.0.2", 108 | "rollup-plugin-visualizer": "^5.8.2", 109 | "shelljs": "^0.8.4", 110 | "stringify-author": "^0.1.3", 111 | "tslib": "^2.3.1", 112 | "typescript": "^4.4.3", 113 | "vite": "^3.1.4", 114 | "vite-plugin-banner": "^0.5.0", 115 | "vite-plugin-css-injected-by-js": "^2.1.0", 116 | "vue": "^3.1.5", 117 | "vue-loader": "^15.9.3", 118 | "vue-style-loader": "^4.1.2", 119 | "vue-template-compiler": "^2.6.11" 120 | }, 121 | "config": { 122 | "commitizen": { 123 | "path": "./node_modules/cz-customizable" 124 | } 125 | }, 126 | "husky": { 127 | "hooks": { 128 | "pre-commit": "lint-staged" 129 | } 130 | }, 131 | "lint-staged": { 132 | "*.{js,jsx,vue}": [ 133 | "eslint --fix", 134 | "git add" 135 | ] 136 | }, 137 | "dependencies": { 138 | "@codemirror/autocomplete": "^6.5.1", 139 | "@codemirror/lang-javascript": "^6.1.6", 140 | "@codemirror/lang-json": "^6.0.1", 141 | "@codemirror/theme-one-dark": "^6.1.1", 142 | "@form-create/component-wangeditor": "^3.1", 143 | "@form-create/naive-ui": "^3.1.18", 144 | "@form-create/utils": "^3.1.15", 145 | "codemirror": "^6.0.1", 146 | "vuedraggable": "4.1.0" 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/components/ColorPicker.vue: -------------------------------------------------------------------------------- 1 | 11 | 38 | -------------------------------------------------------------------------------- /src/components/CustomAlert.vue: -------------------------------------------------------------------------------- 1 | 11 | 25 | -------------------------------------------------------------------------------- /src/components/DragBox.vue: -------------------------------------------------------------------------------- 1 | 34 | -------------------------------------------------------------------------------- /src/components/DragTool.vue: -------------------------------------------------------------------------------- 1 | 51 | 52 | 82 | 83 | 165 | -------------------------------------------------------------------------------- /src/components/FcDesigner.vue: -------------------------------------------------------------------------------- 1 | 175 | 963 | -------------------------------------------------------------------------------- /src/components/Fetch.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 161 | 167 | -------------------------------------------------------------------------------- /src/components/IconRefresh.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 15 | -------------------------------------------------------------------------------- /src/components/Required.vue: -------------------------------------------------------------------------------- 1 | 9 | 54 | 55 | 61 | -------------------------------------------------------------------------------- /src/components/Struct.vue: -------------------------------------------------------------------------------- 1 | 35 | 134 | 135 | 146 | -------------------------------------------------------------------------------- /src/components/TableOptions.vue: -------------------------------------------------------------------------------- 1 | 12 | 117 | 122 | -------------------------------------------------------------------------------- /src/components/Validate.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 240 | 241 | 272 | -------------------------------------------------------------------------------- /src/config/base/field.js: -------------------------------------------------------------------------------- 1 | import IconRefresh from '../../components/IconRefresh.vue'; 2 | import { markRaw } from 'vue'; 3 | 4 | export default function field({ t }) { 5 | return [ 6 | { 7 | type: 'input', 8 | field: 'field', 9 | value: '', 10 | title: t('form.field'), 11 | }, { 12 | type: 'input', 13 | field: 'title', 14 | value: '', 15 | title: t('form.title'), 16 | }, { 17 | type: 'input', 18 | field: 'info', 19 | value: '', 20 | title: t('form.info'), 21 | }, { 22 | type: 'Struct', 23 | field: '_control', 24 | value: [], 25 | title: t('form.control'), 26 | props: { 27 | defaultValue: [], 28 | validate(val) { 29 | if (!Array.isArray(val)) return false; 30 | if (!val.length) return true; 31 | return !val.some(({ rule }) => { 32 | return !Array.isArray(rule); 33 | }); 34 | } 35 | } 36 | }, { 37 | type: 'col', 38 | props: { 39 | span: 24 40 | }, 41 | children: [ 42 | { 43 | type: 'n-space', 44 | children: [ 45 | { 46 | type: 'n-button', 47 | props: { 48 | type: 'info', 49 | size: 'tiny', 50 | }, 51 | inject: true, 52 | on: { 53 | click({ $f }) { 54 | const rule = $f.activeRule; 55 | if (rule) { 56 | rule.__fc__.updateKey(); 57 | rule.value = undefined; 58 | rule.__fc__.$api.sync(rule); 59 | } 60 | }, 61 | }, 62 | native: true, 63 | children: [{ type: 'i', class: 'fc-icon icon-delete' }, t('form.clear')] 64 | }, { 65 | type: 'n-button', 66 | props: { 67 | type: 'success', 68 | size: 'tiny' 69 | }, 70 | inject: true, 71 | on: { 72 | click({ $f }) { 73 | const rule = $f.activeRule; 74 | if (rule) { 75 | rule.__fc__.updateKey(true); 76 | rule.__fc__.$api.sync(rule); 77 | } 78 | }, 79 | }, 80 | native: true, 81 | children: [{type: 'template', slot: 'icon', children: [{type: 'n-icon', props: {component: markRaw(IconRefresh)}}] }, t('form.refresh')] 82 | }, 83 | ] 84 | } 85 | ] 86 | } 87 | ]; 88 | } 89 | -------------------------------------------------------------------------------- /src/config/base/form.js: -------------------------------------------------------------------------------- 1 | export default function form({ t }) { 2 | return [ 3 | { 4 | type: 'radio', 5 | field: 'labelPlacement', 6 | value: 'left', 7 | title: t('form.labelPlacement'), 8 | options: [ 9 | { value: 'left', label: 'left' }, 10 | { value: 'top', label: 'top' }, 11 | ] 12 | }, 13 | { 14 | type: 'radio', 15 | field: 'requireMarkPlacement', 16 | value: 'right', 17 | title: t('form.placementRequireMark'), 18 | options: [ 19 | { value: 'left', label: 'left' }, 20 | { value: 'right', label: 'right' }, 21 | { value: 'right-hanging', label: 'right-hanging' }, 22 | ] 23 | }, 24 | { 25 | type: 'radio', 26 | field: 'showRequireMark', 27 | value: undefined, 28 | title: t('form.showRequireMark'), 29 | info: t('form.showRequireMarkInfo'), 30 | options: [ 31 | { value: false, label: t('form.hideRequireMarkLabel') }, 32 | ] 33 | }, 34 | { 35 | type: 'select', 36 | field: 'size', 37 | value: 'small', 38 | title: t('form.size'), 39 | options: [ 40 | { value: 'large', label: 'large' }, 41 | { value: 'medium', label: 'medium' }, 42 | { value: 'small', label: 'small' }, 43 | { value: 'tiny', label: 'tiny' }, 44 | ] 45 | }, 46 | { 47 | type: 'input', 48 | field: 'labelWidth', 49 | value: 'auto', 50 | title: t('form.labelWidth'), 51 | }, 52 | { 53 | type: 'switch', 54 | field: 'show-feedback', 55 | value: true, 56 | title: t('form.showFeedback'), 57 | props: { 58 | size: 'small', 59 | } 60 | }, 61 | { 62 | type: 'switch', 63 | field: 'formCreateSubmitBtn', 64 | value: true, 65 | title: t('form.submitBtn'), 66 | props: { 67 | size: 'small', 68 | } 69 | }, 70 | { 71 | type: 'switch', 72 | field: 'formCreateResetBtn', 73 | value: false, 74 | title: t('form.resetBtn'), 75 | props: { 76 | size: 'small', 77 | } 78 | }, 79 | ]; 80 | } 81 | -------------------------------------------------------------------------------- /src/config/base/validate.js: -------------------------------------------------------------------------------- 1 | export default function validate() { 2 | return [ 3 | { 4 | type: 'validate', 5 | field: 'validate', 6 | value: [] 7 | }, 8 | ]; 9 | } -------------------------------------------------------------------------------- /src/config/menu.js: -------------------------------------------------------------------------------- 1 | import input from './rule/input' 2 | import number from './rule/number' 3 | import radio from './rule/radio'; 4 | import checkbox from './rule/checkbox'; 5 | import select from './rule/select'; 6 | import _switch from './rule/switch'; 7 | import time from './rule/time'; 8 | import date from './rule/date'; 9 | import slider from './rule/slider'; 10 | import rate from './rule/rate'; 11 | import color from './rule/color'; 12 | import cascader from './rule/cascader'; 13 | import upload from './rule/upload'; 14 | import transfter from './rule/transfter'; 15 | import tree from './rule/tree'; 16 | import editor from './rule/editor'; 17 | import alert from './rule/alert'; 18 | import button from './rule/button'; 19 | import span from './rule/span'; 20 | import divider from './rule/divider'; 21 | import row from './rule/row'; 22 | import tab from './rule/tab'; 23 | import space from './rule/space'; 24 | 25 | export default function createMenu({ t }) { 26 | return [ 27 | { 28 | name: 'main', 29 | title: t('menu.main'), 30 | list: [ 31 | input, number, radio, checkbox, select, _switch, time, date, slider, 32 | rate, color, cascader, upload, transfter, tree, editor 33 | ] 34 | }, 35 | { 36 | name: 'aide', 37 | title: t('menu.aide'), 38 | list: [ 39 | alert, button, span, divider 40 | ] 41 | }, 42 | { 43 | name: 'layout', 44 | title: t('menu.layout'), 45 | list: [ 46 | row, tab, space 47 | ] 48 | }, 49 | ] 50 | } -------------------------------------------------------------------------------- /src/config/rule/alert.js: -------------------------------------------------------------------------------- 1 | import { localeProps } from '../../utils'; 2 | 3 | const label = '提示'; 4 | const name = 'CustomAlert'; 5 | 6 | export default { 7 | icon: 'icon-alert', 8 | label, 9 | name, 10 | rule({ t }) { 11 | return { 12 | type: name, 13 | props: { 14 | title: t('components.n-alert.name'), 15 | type: 'success', 16 | description: t('components.n-alert.description') 17 | }, 18 | children: [] 19 | }; 20 | }, 21 | props(_, { t }) { 22 | return localeProps(t, name + '.props', [ 23 | { 24 | type: 'input', 25 | field: 'title', 26 | title: '标题' 27 | }, 28 | { 29 | type: 'select', 30 | field: 'type', 31 | title: '类型', 32 | value: 'default', 33 | options: [ 34 | { label: 'default', value: 'default' }, 35 | { label: 'success', value: 'success' }, 36 | { label: 'warning', value: 'warning' }, 37 | { label: 'info', value: 'info' }, 38 | { label: 'error', value: 'error' } 39 | ] 40 | }, 41 | { 42 | type: 'input', 43 | field: 'description', 44 | title: '描述' 45 | }, 46 | { 47 | type: 'switch', 48 | field: 'closable', 49 | title: '是否可关闭', 50 | props: { 51 | size: 'small' 52 | } 53 | }, 54 | { 55 | type: 'switch', 56 | field: 'showIcon', 57 | title: '是否显示图标', 58 | value: true, 59 | props: { 60 | size: 'small' 61 | } 62 | }, 63 | { 64 | type: 'switch', 65 | field: 'center', 66 | title: '组件居中', 67 | props: { 68 | size: 'small' 69 | } 70 | }, 71 | { 72 | type: 'switch', 73 | field: 'width', 74 | title: '设置宽度', 75 | value: false, 76 | children: [ 77 | { type: 'span', children: ['百分比宽度'], slot: 'checked' }, 78 | { type: 'span', children: ['精确值宽度'], slot: 'unchecked' }, 79 | ], 80 | control: [ 81 | { 82 | value: true, 83 | rule: [ 84 | { 85 | type: 'input', 86 | field: 'widthPercent', 87 | props: { placeholder: '宽度' }, 88 | children: [ 89 | { 90 | type:'i', 91 | slot: 'suffix', 92 | children: ['%'] 93 | }, 94 | ] 95 | } 96 | ] 97 | }, 98 | { 99 | value: false, 100 | rule: [ 101 | { 102 | type: 'input', 103 | field: 'widthPx', 104 | props: { placeholder: '宽度' }, 105 | children: [ 106 | { 107 | type:'i', 108 | slot: 'suffix', 109 | children: ['px'] 110 | }, 111 | ] 112 | } 113 | ] 114 | } 115 | ] 116 | } 117 | ]); 118 | } 119 | }; 120 | -------------------------------------------------------------------------------- /src/config/rule/button.js: -------------------------------------------------------------------------------- 1 | import { localeProps } from '../../utils'; 2 | 3 | const label = '按钮'; 4 | const name = 'n-button'; 5 | 6 | export default { 7 | icon: 'icon-button', 8 | label, 9 | name, 10 | mask: false, 11 | rule({ t }) { 12 | return { 13 | type: name, 14 | props: {}, 15 | children: [t('components.n-button.name')], 16 | }; 17 | }, 18 | props(_, { t }) { 19 | return localeProps(t, name + '.props', [ 20 | { 21 | type: 'input', 22 | field: 'formCreateChild', 23 | title: '按钮的内容', 24 | }, 25 | { 26 | type: 'select', 27 | field: 'size', 28 | title: '按钮的尺寸', 29 | value: 'medium', 30 | options: [ 31 | { label: 'large', value: 'large' }, 32 | { label: 'medium', value: 'medium' }, 33 | { label: 'small', value: 'small' }, 34 | { label: 'tiny', value: 'tiny' }, 35 | ] 36 | }, 37 | { 38 | type: 'select', 39 | field: 'tag', 40 | title: '按钮需要被渲染成什么标签', 41 | value: 'button', 42 | options: [ 43 | { label: 'button', value: 'button' }, 44 | { label: 'a', value: 'a' } 45 | ] 46 | }, 47 | { 48 | type: 'select', 49 | field: 'type', 50 | title: '按钮的类型', 51 | value: 'default', 52 | options: [ 53 | { label: 'default', value: 'default' }, 54 | { label: 'tertiary', value: 'tertiary' }, 55 | { label: 'primary', value: 'primary' }, 56 | { label: 'success', value: 'success' }, 57 | { label: 'info', value: 'info' }, 58 | { label: 'warning', value: 'warning' }, 59 | { label: 'error', value: 'error' } 60 | ] 61 | }, 62 | { 63 | type: 'switch', 64 | field: 'disabled', 65 | title: '是否禁用状态', 66 | props: { 67 | size: 'small' 68 | } 69 | }, 70 | { 71 | type: 'switch', 72 | field: 'secondary', 73 | title: '是否是次要按钮', 74 | props: { 75 | size: 'small' 76 | } 77 | }, 78 | { 79 | type: 'switch', 80 | field: 'tertiary', 81 | title: '是否是三级按钮', 82 | props: { 83 | size: 'small' 84 | } 85 | }, 86 | { 87 | type: 'switch', 88 | field: 'quaternary', 89 | title: '是否是四级按钮', 90 | props: { 91 | size: 'small' 92 | } 93 | }, 94 | { 95 | type: 'switch', 96 | field: 'text', 97 | title: '是否显示为文本按钮', 98 | props: { 99 | size: 'small' 100 | } 101 | }, 102 | { 103 | type: 'switch', 104 | field: 'dashed', 105 | title: '按钮边框是否为虚线', 106 | props: { 107 | size: 'small' 108 | } 109 | }, 110 | { 111 | type: 'switch', 112 | field: 'ghost', 113 | title: '按钮是否透明', 114 | props: { 115 | size: 'small' 116 | } 117 | }, 118 | { 119 | type: 'switch', 120 | field: 'round', 121 | title: '是否圆角按钮', 122 | props: { 123 | size: 'small' 124 | } 125 | }, 126 | { 127 | type: 'switch', 128 | field: 'circle', 129 | title: '是否圆形按钮', 130 | props: { 131 | size: 'small' 132 | } 133 | }, 134 | { 135 | type: 'switch', 136 | field: 'strong', 137 | title: '按钮文字是否加粗', 138 | props: { 139 | size: 'small' 140 | } 141 | }, 142 | { 143 | type: 'switch', 144 | field: 'loading', 145 | title: '是否加载中状态', 146 | props: { 147 | size: 'small' 148 | } 149 | }, 150 | { 151 | type: 'ColorPicker', 152 | field: 'color', 153 | title: '按钮颜色', 154 | props: { 155 | actions: ['clear'] 156 | } 157 | }, 158 | { 159 | type: 'ColorPicker', 160 | field: 'textColor', 161 | title: '按钮文字颜色', 162 | props: { 163 | actions: ['clear'] 164 | } 165 | } 166 | ]); 167 | } 168 | }; 169 | -------------------------------------------------------------------------------- /src/config/rule/cascader.js: -------------------------------------------------------------------------------- 1 | import uniqueId from '@form-create/utils/lib/unique'; 2 | import { localeProps, makeOptionsRule, makeRequiredRule } from '../../utils/index'; 3 | 4 | const label = '级联选择器'; 5 | const name = 'cascader'; 6 | 7 | export default { 8 | icon: 'icon-cascader', 9 | label, 10 | name, 11 | rule({ t }) { 12 | const opt = t('props.option'); 13 | return { 14 | type: name, 15 | field: uniqueId(), 16 | title: t('components.cascader.name'), 17 | info: '', 18 | effect: { 19 | fetch: '' 20 | }, 21 | $required: false, 22 | props: { 23 | options: [1, 2].map(value => { 24 | return { 25 | label: opt + value, 26 | value, 27 | children: [], 28 | } 29 | }), 30 | } 31 | }; 32 | }, 33 | props(_, { t }) { 34 | return localeProps(t, name + '.props', [ 35 | makeRequiredRule(), 36 | makeOptionsRule(t, 'props.options', false), 37 | { 38 | type: 'input', 39 | field: 'placeholder', 40 | title: '提示信息' 41 | }, 42 | { 43 | type: 'switch', 44 | field: 'disabled', 45 | title: '是否禁用', 46 | props: { 47 | size: 'small' 48 | } 49 | }, 50 | { 51 | type: 'switch', 52 | field: 'clearable', 53 | title: '值是否可清除', 54 | props: { 55 | size: 'small' 56 | } 57 | }, 58 | { 59 | type: 'switch', 60 | field: 'filterable', 61 | title: '是否可搜索', 62 | info: t('components.cascader.props.filterableInfo'), 63 | props: { 64 | size: 'small' 65 | } 66 | }, 67 | { 68 | type: 'switch', 69 | field: 'multiple', 70 | title: '是否支持多选', 71 | props: { 72 | size: 'small' 73 | } 74 | }, 75 | { 76 | type: 'switch', 77 | field: 'cascade', 78 | title: '在多选时是否关联选项', 79 | props: { 80 | size: 'small' 81 | } 82 | }, 83 | { 84 | type: 'inputNumber', 85 | field: 'maxTagCount', 86 | title: '多选标签的最大显示数量', 87 | props: { 88 | min: 0, 89 | placeholder: '全部显示' 90 | } 91 | }, 92 | { 93 | type: 'select', 94 | field: 'checkStrategy', 95 | title: '勾选策略', 96 | value: 'all', 97 | info: t('components.cascader.props.checkStrategyInfo'), 98 | options: [ 99 | { label: t('components.cascader.props.all'), value: 'all' }, 100 | { label: t('components.cascader.props.parent'), value: 'parent' }, 101 | { label: t('components.cascader.props.child'), value: 'child' } 102 | ] 103 | }, 104 | { 105 | type: 'switch', 106 | field: 'clearFilterAfterSelect', 107 | title: '是否在可过滤和多选的情况下选中一个选项后保留当前的搜索关键词', 108 | value: true, 109 | props: { 110 | checkedValue: false, 111 | uncheckedValue: true, 112 | size: 'small' 113 | } 114 | }, 115 | { 116 | type: 'switch', 117 | field: 'showPath', 118 | title: '是否在选择器中显示选项路径', 119 | value: true, 120 | props: { 121 | size: 'small' 122 | } 123 | }, 124 | { 125 | type: 'input', 126 | field: 'separator', 127 | title: '数据分隔符', 128 | props: { 129 | placeholder: '/' 130 | } 131 | }, 132 | { 133 | type: 'input', 134 | field: 'labelField', 135 | title: '自定义 label 字段名', 136 | info: t('components.cascader.props.customInfo'), 137 | props: { 138 | placeholder: 'label' 139 | } 140 | }, 141 | { 142 | type: 'input', 143 | field: 'valueField', 144 | title: '自定义 value 字段名', 145 | props: { 146 | placeholder: 'value' 147 | } 148 | }, 149 | { 150 | type: 'select', 151 | field: 'placement', 152 | title: '菜单的弹出位置', 153 | value: 'bottom', 154 | options: [ 155 | { label: 'top-start', value: 'top-start' }, 156 | { label: 'top', value: 'top' }, 157 | { label: 'top-end', value: 'top-end' }, 158 | { label: 'right-start', value: 'right-start' }, 159 | { label: 'right', value: 'right' }, 160 | { label: 'right-end', value: 'right-end' }, 161 | { label: 'bottom-start', value: 'bottom-start' }, 162 | { label: 'bottom', value: 'bottom' }, 163 | { label: 'bottom-end', value: 'bottom-end' }, 164 | { label: 'left-start', value: 'left-start' }, 165 | { label: 'left', value: 'left' }, 166 | { label: 'left-end', value: 'left-end' }, 167 | ] 168 | } 169 | ]); 170 | } 171 | }; 172 | -------------------------------------------------------------------------------- /src/config/rule/checkbox.js: -------------------------------------------------------------------------------- 1 | import { uniqueId } from "@form-create/utils"; 2 | import { localeProps, makeOptionsRule, makeRequiredRule } from "../../utils"; 3 | 4 | const label = '多选框' 5 | const name = 'checkbox' 6 | 7 | export default { 8 | icon: 'icon-checkbox', 9 | label, 10 | name, 11 | rule({ t }) { 12 | const opt = t('props.option'); 13 | return { 14 | type: name, 15 | field: uniqueId(), 16 | title: t('components.checkbox.name'), 17 | info: '', 18 | effect: { 19 | fetch: '' 20 | }, 21 | $required: false, 22 | props: {}, 23 | options: [1, 2].map(value => { 24 | return { 25 | label: opt + value, 26 | value, 27 | } 28 | }) 29 | }; 30 | }, 31 | props(_, { t }) { 32 | return localeProps(t, name + '.props', [ 33 | makeRequiredRule(), makeOptionsRule(t, 'options'), 34 | { 35 | type: 'switch', 36 | field: 'disabled', 37 | title: '是否禁用', 38 | props: { 39 | size: 'small' 40 | } 41 | }, 42 | { 43 | type: 'inputNumber', 44 | field: 'min', 45 | title: '可被勾选的 checkbox 的最小数量', 46 | props: { min: 0 }, 47 | }, 48 | { 49 | type: 'inputNumber', 50 | field: 'max', 51 | title: '可被勾选的 checkbox 的最大数量', 52 | props: { min: 0 } 53 | } 54 | ]); 55 | } 56 | }; -------------------------------------------------------------------------------- /src/config/rule/col.js: -------------------------------------------------------------------------------- 1 | import {localeProps} from '../../utils'; 2 | 3 | const name = 'col'; 4 | 5 | export default { 6 | name, 7 | label: '格子', 8 | drag: true, 9 | dragBtn: false, 10 | inside: true, 11 | mask: false, 12 | rule() { 13 | return { 14 | type: name, 15 | props: {span: 12}, 16 | children: [] 17 | }; 18 | }, 19 | props(_, {t}) { 20 | return localeProps(t, name + '.props', [ 21 | {type: 'slider', field: 'span', title: '栅格占据的列数', value: 12, props: {min: 0, max: 24}}, 22 | {type: 'slider', field: 'offset', title: '栅格左侧的间隔格数', props: {min: 0, max: 24}}, 23 | {type: 'slider', field: 'push', title: '栅格向右移动格数', props: {min: 0, max: 24}}, 24 | {type: 'slider', field: 'pull', title: '栅格向左移动格数', props: {min: 0, max: 24}}]); 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /src/config/rule/color.js: -------------------------------------------------------------------------------- 1 | import uniqueId from '@form-create/utils/lib/unique'; 2 | import { localeProps, makeRequiredRule } from '../../utils'; 3 | 4 | const label = '颜色选择器'; 5 | const name = 'colorPicker'; 6 | 7 | export default { 8 | icon: 'icon-color', 9 | label, 10 | name, 11 | rule({ t }) { 12 | return { 13 | type: name, 14 | field: uniqueId(), 15 | title: t('components.colorPicker.name'), 16 | info: '', 17 | $required: false, 18 | props: {}, 19 | }; 20 | }, 21 | props(_, { t }) { 22 | return localeProps(t, name + '.props', [ 23 | makeRequiredRule(), 24 | { 25 | type: 'switch', 26 | field: 'disabled', 27 | title: '是否禁用', 28 | props: { 29 | size: 'small' 30 | } 31 | }, 32 | { 33 | type: 'switch', 34 | field: 'showAlpha', 35 | title: '是否可调节 alpha 通道', 36 | value: true, 37 | props: { 38 | size: 'small' 39 | } 40 | }, 41 | { 42 | type: 'ColorPicker', 43 | field: 'defaultValue', 44 | title: '默认的颜色值', 45 | props: { 46 | defaultValue: '#000000' 47 | } 48 | }, 49 | { 50 | type: 'select', 51 | field: 'actions', 52 | title: '显示按钮', 53 | props: { 54 | multiple: true 55 | }, 56 | options: [ 57 | { label: t('components.colorPicker.props.confirm'), value: 'confirm' }, 58 | { label: t('components.colorPicker.props.clear'), value: 'clear' }, 59 | ] 60 | }, 61 | { 62 | type: 'select', 63 | field: 'modes', 64 | title: '颜色选择器支持颜色的格式', 65 | info: t('components.colorPicker.props.modesInfo'), 66 | value: ['rgb','hex','hsl'], 67 | props: { 68 | multiple: true, 69 | }, 70 | options: [ 71 | { label: 'hsl', value: 'hsl' }, 72 | { label: 'hsv', value: 'hsv' }, 73 | { label: 'hex', value: 'hex' }, 74 | { label: 'rgb', value: "rgb", disabled: true } 75 | ] 76 | } 77 | ]); 78 | } 79 | }; 80 | -------------------------------------------------------------------------------- /src/config/rule/date.js: -------------------------------------------------------------------------------- 1 | import uniqueId from '@form-create/utils/lib/unique'; 2 | import { localeProps, makeRequiredRule } from '../../utils'; 3 | 4 | const label = '日期选择器'; 5 | const name = 'datePicker'; 6 | 7 | export default { 8 | icon: 'icon-date', 9 | label, 10 | name, 11 | rule({ t }) { 12 | return { 13 | type: name, 14 | field: uniqueId(), 15 | title: t('components.datePicker.name'), 16 | info: '', 17 | $required: false, 18 | props: {}, 19 | }; 20 | }, 21 | props(_, { t }) { 22 | return localeProps(t, name + '.props', [ 23 | makeRequiredRule(), 24 | { 25 | type: 'Struct', 26 | field: 'pickerOptions', 27 | title: '当前时间日期选择器特有的选项', 28 | props: { defaultValue: {} } 29 | }, 30 | { 31 | type: 'switch', 32 | field: 'inputReadonly', 33 | title: '设置输入框为只读', 34 | info: t('components.datePicker.props.inputReadonlyInfo'), 35 | props: { 36 | size: 'small' 37 | } 38 | }, 39 | { 40 | type: 'switch', 41 | field: 'disabled', 42 | title: '禁用', 43 | props: { 44 | size: 'small' 45 | } 46 | }, 47 | { 48 | type: 'switch', 49 | field: 'clearable', 50 | title: '是否支持清除', 51 | value: false, 52 | props: { 53 | size: 'small' 54 | } 55 | }, 56 | { 57 | type: 'select', 58 | field: 'type', 59 | title: '日期选择器的类型', 60 | value: 'date', 61 | options: [ 62 | { label: t('aboutTime.date'), value: 'date' }, 63 | { label: t('aboutTime.datetime'), value: 'datetime' }, 64 | { label: t('aboutTime.daterange'), value: 'daterange' }, 65 | { label: t('aboutTime.datetimerange'), value: 'datetimerange' }, 66 | { label: t('aboutTime.month'), value: 'month' }, 67 | { label: t('aboutTime.monthrange'), value: 'monthrange'}, 68 | { label: t('aboutTime.year'), value: 'year' }, 69 | { label: t('aboutTime.yearrange'), value: 'yearrange'}, 70 | { label: t('aboutTime.quarter'), value: 'quarter' }, 71 | { label: t('aboutTime.quarterrange'), value: 'quarterrange' }, 72 | ] 73 | }, 74 | { 75 | type: 'input', 76 | field: 'placeholder', 77 | title: '非范围选择时的占位内容' 78 | }, 79 | { 80 | type: 'input', 81 | field: 'format', 82 | title: '显示在输入框中的格式', 83 | }, 84 | { 85 | type: 'select', 86 | field: 'placement', 87 | title: '面板的弹出位置', 88 | value: 'bottom', 89 | options: [ 90 | { label: 'top-start', value: 'top-start' }, 91 | { label: 'top', value: 'top' }, 92 | { label: 'top-end', value: 'top-end' }, 93 | { label: 'right-start', value: 'right-start' }, 94 | { label: 'right', value: 'right' }, 95 | { label: 'right-end', value: 'right-end' }, 96 | { label: 'bottom-start', value: 'bottom-start' }, 97 | { label: 'bottom', value: 'bottom' }, 98 | { label: 'bottom-end', value: 'bottom-end' }, 99 | { label: 'left-start', value: 'left-start' }, 100 | { label: 'left', value: 'left' }, 101 | { label: 'left-end', value: 'left-end' }, 102 | ] 103 | } 104 | ]); 105 | } 106 | }; 107 | -------------------------------------------------------------------------------- /src/config/rule/divider.js: -------------------------------------------------------------------------------- 1 | import { localeProps } from '../../utils'; 2 | 3 | const label = '分割线'; 4 | const name = 'n-divider'; 5 | 6 | export default { 7 | icon: 'icon-divider', 8 | label, 9 | name, 10 | rule() { 11 | return { 12 | type: name, 13 | props: {}, 14 | wrap: { show: false }, 15 | native: false, 16 | children: [''], 17 | }; 18 | }, 19 | props(_, { t }) { 20 | return localeProps(t, name + '.props', [ 21 | { 22 | type: 'switch', 23 | field: 'vertical', 24 | title: '是否垂直分隔', 25 | props: { 26 | size: 'small' 27 | } 28 | }, 29 | { 30 | type: 'input', 31 | field: 'formCreateChild', 32 | title: '设置分割线文案', 33 | }, 34 | { 35 | type: 'select', 36 | field: 'titlePlacement', 37 | title: '标题的位置', 38 | value: 'center', 39 | options: [ 40 | { label: 'left', value: 'left' }, 41 | { label: 'right', value: 'right' }, 42 | { label: 'center', value: 'center' } 43 | ] 44 | } 45 | ]); 46 | } 47 | }; 48 | -------------------------------------------------------------------------------- /src/config/rule/editor.js: -------------------------------------------------------------------------------- 1 | import uniqueId from '@form-create/utils/lib/unique'; 2 | import { localeProps, makeRequiredRule } from '../../utils'; 3 | 4 | const label = '富文本框'; 5 | const name = 'fc-editor'; 6 | 7 | export default { 8 | icon: 'icon-editor', 9 | label, 10 | name, 11 | rule({ t }) { 12 | return { 13 | type: name, 14 | field: uniqueId(), 15 | title: t('components.fc-editor.name'), 16 | info: '', 17 | $required: false, 18 | props: {}, 19 | }; 20 | }, 21 | props(_, { t }) { 22 | return localeProps(t, name + '.props', [ 23 | makeRequiredRule(), 24 | { 25 | type: 'switch', 26 | field: 'disabled', 27 | title: '是否禁用', 28 | props: { 29 | size: 'small' 30 | } 31 | } 32 | ]); 33 | } 34 | }; -------------------------------------------------------------------------------- /src/config/rule/index.js: -------------------------------------------------------------------------------- 1 | import input from './input'; 2 | import number from './number'; 3 | import radio from './radio'; 4 | import checkbox from './checkbox'; 5 | import select from './select'; 6 | import _switch from './switch'; 7 | import time from './time'; 8 | import date from './date'; 9 | import slider from './slider'; 10 | import rate from './rate'; 11 | import color from './color'; 12 | import cascader from './cascader'; 13 | import upload from './upload'; 14 | import transfter from './transfter'; 15 | import tree from './tree'; 16 | import editor from './editor'; 17 | import alert from './alert'; 18 | import button from './button'; 19 | import span from './span'; 20 | import divider from './divider'; 21 | import row from './row'; 22 | import col from './col'; 23 | import tab from './tab'; 24 | import tabPane from './tabPane'; 25 | import space from './space'; 26 | 27 | const ruleList = { 28 | [input.name]: input, 29 | [number.name]: number, 30 | [radio.name]: radio, 31 | [checkbox.name]: checkbox, 32 | [select.name]: select, 33 | [_switch.name]: _switch, 34 | [time.name]: time, 35 | [date.name]: date, 36 | [slider.name]: slider, 37 | [rate.name]: rate, 38 | [color.name]: color, 39 | [cascader.name]: cascader, 40 | [upload.name]: upload, 41 | [transfter.name]: transfter, 42 | [tree.name]: tree, 43 | [editor.name]: editor, 44 | [alert.name]: alert, 45 | [button.name]: button, 46 | [span.name]: span, 47 | [divider.name]: divider, 48 | [row.name]: row, 49 | [col.name]: col, 50 | [tab.name]: tab, 51 | [tabPane.name]: tabPane, 52 | [space.name]: space 53 | }; 54 | 55 | export default ruleList; -------------------------------------------------------------------------------- /src/config/rule/input.js: -------------------------------------------------------------------------------- 1 | import uniqueId from '@form-create/utils/lib/unique'; 2 | import { localeProps, makeRequiredRule } from '../../utils'; 3 | const label = '输入框'; 4 | const name = 'input'; 5 | 6 | export default { 7 | icon: 'icon-input', 8 | label, 9 | name, 10 | rule({ t }) { 11 | return { 12 | type: name, 13 | field: uniqueId(), 14 | title: t('components.input.name'), 15 | info: '', 16 | $required: false, 17 | props: {} 18 | }; 19 | }, 20 | props(_, { t }) { 21 | return localeProps(t, name + '.props', 22 | [ 23 | makeRequiredRule(), 24 | { type: 'switch', field: 'round', title: '输入框是否圆角', props: { size: "small" } }, 25 | { 26 | type: 'select', 27 | field: 'type', 28 | title: '类型', 29 | options: [ 30 | { label: 'text', value: 'text' }, { label: 'textarea', value: 'textarea' }, 31 | { label: 'number', value: 'number' }, { label: 'password', value: 'password' } 32 | ] 33 | }, 34 | { type: 'inputNumber', field: 'maxlength', title: '最大输入长度', props: { min: 0, size: "small" } }, 35 | { type: 'inputNumber', field: 'minlength', title: '最小输入长度', props: { min: 0, size: "small" } }, 36 | { type: 'switch', field: 'showCount', title: '是否显示输入字数统计', props: { size: "small" } }, 37 | { type: 'input', field: 'placeholder', title: '输入框占位文本' }, 38 | { type: 'switch', field: 'clearable', title: '是否可清空', props: { size: "small" } }, 39 | { 40 | type: 'radio', field: 'showPasswordOn', title: '显示密码的时机', options: [ 41 | { value: 'click', label: 'click' }, 42 | { value: 'mousedown', label: 'mousedown' },] 43 | }, 44 | { type: 'switch', field: 'disabled', title: '禁用', props: { size: "small" } }, 45 | { 46 | type: 'inputNumber', 47 | field: 'rows', 48 | info: t('components.input.props.rowsInfo'), 49 | title: '输入框行数', 50 | props: { min: 0 } 51 | }, 52 | { type: 'switch', field: 'readonly', title: '是否只读', props: { size: "small" } }, 53 | { type: 'switch', field: 'autofocus', title: '自动获取焦点', props: { size: "small" } } 54 | ] 55 | ); 56 | } 57 | }; -------------------------------------------------------------------------------- /src/config/rule/number.js: -------------------------------------------------------------------------------- 1 | import uniqueId from '@form-create/utils/lib/unique'; 2 | import { localeProps, makeRequiredRule } from '../../utils'; 3 | 4 | const label = '计数器' 5 | const name = 'inputNumber' 6 | 7 | export default { 8 | icon: 'icon-number', 9 | label, 10 | name, 11 | rule({ t }) { 12 | return { 13 | type: name, 14 | field: uniqueId(), 15 | title: t('components.inputNumber.name'), 16 | info: '', 17 | $required: false, 18 | props: {} 19 | } 20 | }, 21 | props(_, { t }) { 22 | return localeProps(t, name + '.props', [makeRequiredRule(), { 23 | type: 'inputNumber', 24 | field: 'min', 25 | title: '设置计数器允许的最小值' 26 | }, { 27 | type: 'inputNumber', 28 | field: 'max', 29 | title: '设置计数器允许的最大值', 30 | }, { 31 | type: 'inputNumber', 32 | field: 'precision', 33 | title: '数值保留的精度值', 34 | value: 0, 35 | props: { min: 0 } 36 | }, { 37 | type: 'inputNumber', 38 | field: 'step', 39 | title: '计数器步长', 40 | props: { min: 0 } 41 | }, { 42 | type: 'switch', 43 | field: 'disabled', 44 | title: '是否禁用计数器', 45 | props: { 46 | size: 'small', 47 | } 48 | }, { 49 | type: 'switch', 50 | field: 'showButton', 51 | title: '是否有按钮', 52 | value: true, 53 | props: { 54 | size: 'small', 55 | } 56 | }, { 57 | type: 'select', 58 | field: 'buttonPlacement', 59 | title: '加减按钮的位置', 60 | value: 'right', 61 | options: [{ label: 'right', value: 'right' }, { label: 'both', value: 'both' }] 62 | }, { 63 | type: 'input', 64 | field: 'placeholder', 65 | title: '提示信息', 66 | } 67 | ]) 68 | } 69 | }; -------------------------------------------------------------------------------- /src/config/rule/radio.js: -------------------------------------------------------------------------------- 1 | import uniqueId from '@form-create/utils/lib/unique'; 2 | import { localeProps, makeOptionsRule, makeRequiredRule } from '../../utils/index'; 3 | 4 | const lable = '单选框'; 5 | const name = 'radio' 6 | 7 | export default { 8 | icon: 'icon-radio', 9 | lable, 10 | name, 11 | rule({ t }) { 12 | const opt = t('props.option'); 13 | return { 14 | type: name, 15 | field: uniqueId(), 16 | title: t('components.radio.name'), 17 | info: '', 18 | effect: { 19 | fetch: '' 20 | }, 21 | $required: false, 22 | props: {}, 23 | options: [1, 2].map(value => { 24 | return { 25 | label: opt + value, 26 | value, 27 | } 28 | }) 29 | }; 30 | }, 31 | props(_, {t}) { 32 | return localeProps(t, name + '.props', [ 33 | makeRequiredRule(), 34 | makeOptionsRule(t, 'options'), 35 | { 36 | type: 'switch', 37 | field: 'disabled', 38 | title: '是否禁用', 39 | props: { 40 | size: 'small', 41 | } 42 | }, 43 | { 44 | type: 'switch', 45 | field: 'type', 46 | title: '按钮形式', 47 | value: 'default', 48 | props: { 49 | checkedValue: 'button', 50 | uncheckedValue: 'default', 51 | size: 'small' 52 | } 53 | }, 54 | ]) 55 | } 56 | } -------------------------------------------------------------------------------- /src/config/rule/rate.js: -------------------------------------------------------------------------------- 1 | import uniqueId from '@form-create/utils/lib/unique'; 2 | import { localeProps, makeRequiredRule } from '../../utils'; 3 | 4 | const label = '评分'; 5 | const name = 'rate'; 6 | 7 | export default { 8 | icon: 'icon-rate', 9 | label, 10 | name, 11 | rule({ t }) { 12 | return { 13 | type: name, 14 | field: uniqueId(), 15 | title: t('components.rate.name'), 16 | info: '', 17 | $required: false, 18 | props: {}, 19 | }; 20 | }, 21 | props(_, { t }) { 22 | return localeProps(t, name + '.props', [ 23 | makeRequiredRule(), 24 | { 25 | type: 'radio', 26 | field: 'size', 27 | value: 'medium', 28 | title: '图标尺寸', 29 | info: t('components.rate.props.sizeInfo'), 30 | options: [ 31 | { value: 'large', label: 'large' }, 32 | { value: 'medium', label: 'medium' }, 33 | { value: 'small', label: 'small' }, 34 | ] 35 | }, 36 | { 37 | type: 'inputNumber', 38 | field: 'count', 39 | title: '图标个数', 40 | value: 5, 41 | props: { 42 | min: 1, 43 | } 44 | }, 45 | { 46 | type: 'inputNumber', 47 | field: 'defaultValue', 48 | title: '默认已激活图标个数', 49 | value: 0, 50 | props: { 51 | min: 0, 52 | } 53 | }, 54 | { 55 | type: 'switch', 56 | field: 'readonly', 57 | title: '只读,交互失效', 58 | props: { 59 | size: 'small', 60 | } 61 | }, 62 | { 63 | type: 'switch', 64 | field: 'clearable', 65 | title: '是否可清空', 66 | info: t('components.rate.props.clearableInfo'), 67 | props: { 68 | size: 'small', 69 | } 70 | }, 71 | { 72 | type: 'switch', 73 | field: 'allowHalf', 74 | title: '允许只激活一半图标', 75 | props: { 76 | size: 'small', 77 | } 78 | }, 79 | { 80 | type: 'ColorPicker', 81 | field: 'color', 82 | title: '已激活图标颜色', 83 | props: { 84 | defaultValue: '#FFCC33', 85 | } 86 | } 87 | ]); 88 | } 89 | }; 90 | -------------------------------------------------------------------------------- /src/config/rule/row.js: -------------------------------------------------------------------------------- 1 | import { localeProps } from '../../utils'; 2 | 3 | const label = '栅格布局'; 4 | const name = 'row'; 5 | 6 | export default { 7 | icon: 'icon-row', 8 | label, 9 | name, 10 | mask: false, 11 | rule() { 12 | return { 13 | type: 'FcRow', 14 | props: {}, 15 | children: [] 16 | }; 17 | }, 18 | children: 'col', 19 | childrenLen: 2, 20 | props(_, { t }) { 21 | return localeProps(t, name + '.props', [ 22 | { 23 | type: 'inputNumber', 24 | field: 'gutter', 25 | title: '栅格间隔', 26 | props: { min: 0 } 27 | } 28 | ]); 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /src/config/rule/select.js: -------------------------------------------------------------------------------- 1 | import uniqueId from '@form-create/utils/lib/unique'; 2 | import { localeProps, makeOptionsRule, makeRequiredRule } from '../../utils/index'; 3 | 4 | const label = '选择器'; 5 | const name = 'select'; 6 | 7 | export default { 8 | icon: 'icon-select', 9 | label, 10 | name, 11 | rule({ t }) { 12 | const opt = t('props.option'); 13 | return { 14 | type: name, 15 | field: uniqueId(), 16 | title: t('components.select.name'), 17 | info: '', 18 | effect: { 19 | fetch: '' 20 | }, 21 | $required: false, 22 | props: {}, 23 | options: [1, 2].map(value => { 24 | return { 25 | label: opt + value, 26 | value, 27 | } 28 | }) 29 | }; 30 | }, 31 | watch: { 32 | multiple({ rule }) { 33 | rule.key = uniqueId(); 34 | } 35 | }, 36 | props(_, { t }) { 37 | return localeProps(t, name + '.props', [ 38 | makeRequiredRule(), 39 | makeOptionsRule(t, 'options'), 40 | { 41 | type: 'switch', 42 | field: 'multiple', 43 | title: '是否多选', 44 | props: { 45 | size: 'small' 46 | } 47 | }, 48 | { 49 | type: 'switch', 50 | field: 'disabled', 51 | title: '是否禁用', 52 | props: { 53 | size: 'small' 54 | } 55 | }, 56 | { 57 | type: 'switch', 58 | field: 'clearable', 59 | title: '是否可以清空选项' , 60 | props: { 61 | size: 'small' 62 | } 63 | }, 64 | { 65 | type: 'inputNumber', 66 | field: 'maxTagCount', 67 | title: '多选标签的最大显示数量', 68 | props: { 69 | min: 0, 70 | placeholder: '全部显示' 71 | } 72 | }, 73 | { 74 | type: 'input', 75 | field: 'placeholder', 76 | title: '占位符' 77 | }, 78 | { 79 | type: 'switch', 80 | field: 'filterable', 81 | title: '是否可以过滤', 82 | props: { 83 | size: 'small' 84 | } 85 | }, 86 | { 87 | type: 'switch', 88 | field: 'tag', 89 | title: '是否允许用户创建新条目', 90 | props: { 91 | size: 'small' 92 | } 93 | }, 94 | { 95 | type: 'switch', 96 | field: 'remote', 97 | title: '是否要异步获取选项', 98 | info: t('components.select.props.remoteInfo'), 99 | props: { 100 | size: 'small' 101 | } 102 | }, 103 | { 104 | type: 'Struct', 105 | field: 'onSearch', 106 | title: '自定义远程搜索方法' 107 | }, 108 | { 109 | type: 'switch', 110 | field: 'clearFilterAfterSelect', 111 | title: '是否在可过滤和多选的情况下选中一个选项后保留当前的搜索关键词', 112 | value: true, 113 | props: { 114 | checkedValue: false, 115 | uncheckedValue: true, 116 | size: 'small' 117 | } 118 | }, 119 | { 120 | type: 'select', 121 | field: 'placement', 122 | title: '菜单的弹出位置', 123 | value: 'bottom', 124 | options: [ 125 | { label: 'top-start', value: 'top-start' }, 126 | { label: 'top', value: 'top' }, 127 | { label: 'top-end', value: 'top-end' }, 128 | { label: 'right-start', value: 'right-start' }, 129 | { label: 'right', value: 'right' }, 130 | { label: 'right-end', value: 'right-end' }, 131 | { label: 'bottom-start', value: 'bottom-start' }, 132 | { label: 'bottom', value: 'bottom' }, 133 | { label: 'bottom-end', value: 'bottom-end' }, 134 | { label: 'left-start', value: 'left-start' }, 135 | { label: 'left', value: 'left' }, 136 | { label: 'left-end', value: 'left-end' }, 137 | ] 138 | } 139 | ]); 140 | } 141 | }; 142 | -------------------------------------------------------------------------------- /src/config/rule/slider.js: -------------------------------------------------------------------------------- 1 | import uniqueId from '@form-create/utils/lib/unique'; 2 | import { localeProps, makeRequiredRule } from '../../utils'; 3 | 4 | const label = '滑块'; 5 | const name = 'slider'; 6 | 7 | export default { 8 | icon: 'icon-slider', 9 | label, 10 | name, 11 | rule({ t }) { 12 | return { 13 | type: name, 14 | field: uniqueId(), 15 | title: t('components.slider.name'), 16 | info: '', 17 | $required: false, 18 | props: {}, 19 | }; 20 | }, 21 | props(_, { t }) { 22 | return localeProps(t, name + '.props', [ 23 | makeRequiredRule(), 24 | { 25 | type: 'switch', 26 | field: 'disabled', 27 | title: '是否禁用', 28 | props: { 29 | size: 'small' 30 | } 31 | }, 32 | { 33 | type: 'inputNumber', 34 | field: 'defaultValue', 35 | title: '默认值', 36 | props: { min: 0 } 37 | }, 38 | { 39 | type: 'inputNumber', 40 | field: 'min', 41 | title: '最小值', 42 | props: { min: 0 } 43 | }, 44 | { 45 | type: 'inputNumber', 46 | field: 'max', 47 | title: '最大值', 48 | props: { min: 0 }, 49 | }, 50 | { 51 | type: 'inputNumber', 52 | field: 'step', 53 | title: '步长', 54 | value: 1, 55 | props: { min: 0 }, 56 | }, 57 | { 58 | type: 'switch', 59 | field: 'range', 60 | title: '是否为范围选择', 61 | props: { 62 | disabled: true, 63 | size: 'small' 64 | } 65 | }, 66 | { 67 | type: 'switch', 68 | field: 'reverse', 69 | title: '是否倒转轨道', 70 | value: false, 71 | props: { 72 | size: 'small' 73 | } 74 | }, 75 | { 76 | type: 'switch', 77 | field: 'vertical', 78 | title: '是否启用垂直模式', 79 | props: { 80 | size: 'small' 81 | } 82 | }, 83 | { 84 | type: 'switch', 85 | field: 'tooltip', 86 | title: '是否展示 tooltip', 87 | value: true, 88 | props: { 89 | size: 'small' 90 | } 91 | }, 92 | { 93 | type: 'switch', 94 | field: 'showTooltip', 95 | title: '是否一直显示 tooltip', 96 | info: t('components.slider.props.showTooltipInfo'), 97 | value: false, 98 | props: { 99 | size: 'small' 100 | } 101 | }, 102 | { 103 | type: 'select', 104 | field: 'placement', 105 | title: 'Tooltip 的弹出位置', 106 | options: [ 107 | { label: 'top-start', value: 'top-start' }, 108 | { label: 'top', value: 'top' }, 109 | { label: 'top-end', value: 'top-end' }, 110 | { label: 'right-start', value: 'right-start' }, 111 | { label: 'right', value: 'right' }, 112 | { label: 'right-end', value: 'right-end' }, 113 | { label: 'bottom-start', value: 'bottom-start' }, 114 | { label: 'bottom', value: 'bottom' }, 115 | { label: 'bottom-end', value: 'bottom-end' }, 116 | { label: 'left-start', value: 'left-start' }, 117 | { label: 'left', value: 'left' }, 118 | { label: 'left-end', value: 'left-end' }, 119 | ] 120 | } 121 | ]); 122 | } 123 | }; 124 | -------------------------------------------------------------------------------- /src/config/rule/space.js: -------------------------------------------------------------------------------- 1 | import { localeProps } from '../../utils'; 2 | 3 | const label = '间距'; 4 | const name = 'div'; 5 | 6 | export default { 7 | icon: 'icon-space', 8 | label, 9 | name, 10 | rule() { 11 | return { 12 | type: name, 13 | wrap: { 14 | show: false 15 | }, 16 | native: false, 17 | style: { 18 | width: '100%', 19 | height: '20px', 20 | }, 21 | children: [] 22 | }; 23 | }, 24 | props(_, { t }) { 25 | return [ 26 | { 27 | type: 'object', 28 | field: 'formCreateStyle', 29 | native: true, 30 | props: { 31 | rule: localeProps(t, name + '.props', [ 32 | { 33 | type: 'input', 34 | field: 'height', 35 | title: 'height', 36 | props: { 37 | size: 'small' 38 | } 39 | }, 40 | ]) 41 | } 42 | } 43 | 44 | ]; 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /src/config/rule/span.js: -------------------------------------------------------------------------------- 1 | import {localeProps} from '../../utils'; 2 | 3 | const label = '文字'; 4 | const name = 'span'; 5 | 6 | export default { 7 | icon: 'icon-span', 8 | label, 9 | name, 10 | rule({t}) { 11 | return { 12 | type: name, 13 | title: t('components.span.name'), 14 | native: false, 15 | children: [t('components.span.name')], 16 | }; 17 | }, 18 | props(_, {t}) { 19 | return localeProps(t, name + '.props', [ 20 | { 21 | type: 'input', 22 | field: 'formCreateTitle', 23 | title: 'title', 24 | }, 25 | { 26 | type: 'input', 27 | field: 'formCreateChild', 28 | title: '内容', 29 | props: { 30 | type: 'textarea' 31 | } 32 | } 33 | ]); 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /src/config/rule/switch.js: -------------------------------------------------------------------------------- 1 | import uniqueId from '@form-create/utils/lib/unique'; 2 | import { localeProps, makeRequiredRule } from '../../utils'; 3 | 4 | const label = '开关'; 5 | const name = 'switch'; 6 | 7 | export default { 8 | icon: 'icon-switch', 9 | label, 10 | name, 11 | rule({ t }) { 12 | return { 13 | type: name, 14 | field: uniqueId(), 15 | title: t('components.switch.name'), 16 | info: '', 17 | $required: false, 18 | props: {}, 19 | }; 20 | }, 21 | props(_, { t }) { 22 | return localeProps(t, name + '.props', [ 23 | makeRequiredRule(), 24 | { 25 | type: 'switch', 26 | field: 'disabled', 27 | title: '是否禁用', 28 | props: { 29 | size: 'small', 30 | } 31 | }, 32 | { 33 | type: 'radio', 34 | field: 'size', 35 | title: '尺寸', 36 | info: t('components.switch.props.sizeInfo'), 37 | value: 'medium', 38 | options: [ 39 | { value: 'small', label: 'small' }, 40 | { value: 'medium', label: 'medium' }, 41 | { value: 'large', label: 'large' } 42 | ] 43 | }, 44 | { 45 | type: 'input', 46 | field: 'checkedValue', 47 | title: '选中时对应的值' 48 | }, 49 | { 50 | type: 'input', 51 | field: 'uncheckedValue', 52 | title: '未选中时对应的值' 53 | }, 54 | ]); 55 | } 56 | }; 57 | -------------------------------------------------------------------------------- /src/config/rule/tab.js: -------------------------------------------------------------------------------- 1 | import { localeProps } from '../../utils'; 2 | import tabname from '../../utils/tabname'; 3 | 4 | const label = '标签页'; 5 | const name = 'tab'; 6 | 7 | export default { 8 | icon: 'icon-tab', 9 | label, 10 | name, 11 | children: 'tab-pane', 12 | childrenLen: 2, 13 | mask: false, 14 | rule({ t }) { 15 | return { 16 | type: 'n-tabs', 17 | style: 'width:100%;', 18 | props: { 19 | type: 'line', 20 | defaultValue: String(tabname()), 21 | }, 22 | children: [] 23 | }; 24 | }, 25 | props(_, { t }) { 26 | return localeProps(t, name + '.props', [ 27 | { 28 | type: 'input', 29 | field: 'defaultValue', 30 | title: '默认展示标签页的标识', 31 | info: t('components.tab.props.defaultValueInfo') 32 | }, 33 | { 34 | type: 'radio', 35 | field: 'trigger', 36 | value: 'click', 37 | title: '触发 tab 的方式', 38 | options: [ 39 | { value: 'click', label: 'click' }, 40 | { value: 'hover', label: 'hover' }, 41 | ] 42 | }, 43 | { 44 | type: 'radio', 45 | field: 'size', 46 | value: 'medium', 47 | title: '标签页的尺寸', 48 | options: [ 49 | { value: 'small', label: 'small' }, 50 | { value: 'medium', label: 'medium' }, 51 | { value: 'large', label: 'large' }, 52 | ] 53 | }, 54 | { 55 | type: 'select', 56 | field: 'type', 57 | title: '标签类型', 58 | value: 'bar', 59 | options: [ 60 | { label: 'bar', value: 'bar' }, 61 | { label: 'line', value: 'line' }, 62 | { label: 'card', value: 'card' }, 63 | { label: 'segment', value: 'segment' } 64 | ], 65 | control: [ 66 | { 67 | handle(val) { 68 | return val === 'card'; 69 | }, 70 | rule: [{ 71 | type: 'switch', 72 | field: 'closable', 73 | title: '标签是否可关闭', 74 | info: t('components.tab.props.closableInfo') 75 | }] 76 | }, 77 | { 78 | handle(val) { 79 | return val === 'line' || val === 'bar'; 80 | }, 81 | rule: [{ 82 | type: 'select', 83 | field: 'justifyContent', 84 | title: 'flex 布局下主轴的排列方式', 85 | info: t('components.tab.props.justifyContentInfo'), 86 | props: { 87 | clearable: true, 88 | }, 89 | options: [ 90 | { label: 'end', value: 'end' }, 91 | { label: 'start', value: 'start' }, 92 | { label: 'center', value: 'center' }, 93 | { label: 'space-evenly', value: 'space-evenly' }, 94 | { label: 'space-around', value: 'space-around' }, 95 | { label: 'space-between', value: 'space-between' }, 96 | ], 97 | }] 98 | } 99 | ] 100 | }, 101 | { 102 | type: 'switch', 103 | field: 'animated', 104 | title: '标签页切换是否使用动画', 105 | value: true, 106 | props: { 107 | size: 'small' 108 | } 109 | }, 110 | { 111 | type: 'inputNumber', 112 | field: 'barWidth', 113 | title: '标签条的宽度', 114 | props: { 115 | min: 0, 116 | clearable: true, 117 | } 118 | }, 119 | { 120 | type: 'inputNumber', 121 | field: 'tabsPadding', 122 | title: '全部标签最左和最右的 padding', 123 | value: 0, 124 | props: { 125 | min: 0, 126 | } 127 | }, 128 | ]); 129 | } 130 | }; 131 | -------------------------------------------------------------------------------- /src/config/rule/tabPane.js: -------------------------------------------------------------------------------- 1 | import { localeProps } from '../../utils'; 2 | import tabname from '../../utils/tabname'; 3 | 4 | const label = '标签页'; 5 | const name = 'tab-pane'; 6 | 7 | export default { 8 | label, 9 | name, 10 | inside: true, 11 | drag: true, 12 | dragBtn: false, 13 | mask: false, 14 | rule({ t }) { 15 | return { 16 | type: 'n-tab-pane', 17 | props: { 18 | tab: t('components.tab.name'), 19 | name: String(tabname()), 20 | }, 21 | children: [] 22 | }; 23 | }, 24 | props(_, { t }) { 25 | return localeProps(t, name + '.props', [ 26 | { 27 | type: 'input', 28 | field: 'tab', 29 | title: '选项卡标题' 30 | }, 31 | { 32 | type: 'switch', 33 | field: 'closable', 34 | title: '是否允许关闭标签', 35 | info: t('components.tab-pane.props.closableInfo'), 36 | }, 37 | { 38 | type: 'switch', 39 | field: 'disabled', 40 | title: '是否禁用' 41 | }, 42 | { 43 | type: 'input', 44 | field: 'name', 45 | title: '标签页标识', 46 | info: t('components.tab-pane.props.nameInfo') 47 | }, 48 | { 49 | type: 'select', 50 | field: 'displayDirective', 51 | title: '选择性渲染使用的指令', 52 | value: 'if', 53 | options: [ 54 | { label: t('components.tab-pane.props.if'), value: 'if' }, 55 | { label: t('components.tab-pane.props.show'), value: 'show' }, 56 | { label: t('components.tab-pane.props.showLazy'), value: 'show:lazy' }, 57 | ] 58 | } 59 | ]); 60 | } 61 | }; 62 | -------------------------------------------------------------------------------- /src/config/rule/time.js: -------------------------------------------------------------------------------- 1 | import uniqueId from '@form-create/utils/lib/unique'; 2 | import { localeProps, makeRequiredRule } from '../../utils'; 3 | 4 | const label = '时间选择器'; 5 | const name = 'timePicker'; 6 | 7 | export default { 8 | icon: 'icon-time', 9 | label, 10 | name, 11 | rule({ t }) { 12 | return { 13 | type: name, 14 | field: uniqueId(), 15 | title: t('components.timePicker.name'), 16 | info: '', 17 | $required: false, 18 | props: {}, 19 | }; 20 | }, 21 | props(_, { t }) { 22 | return localeProps(t, name + '.props', [ 23 | makeRequiredRule(), 24 | { 25 | type: 'Struct', 26 | field: 'pickerOptions', 27 | title: '当前时间日期选择器特有的选项', 28 | props: { defaultValue: {} } 29 | }, 30 | { 31 | type: 'switch', 32 | field: 'inputReadonly', 33 | title: '设置输入框为只读', 34 | info: t('components.timePicker.props.inputReadonlyInfo'), 35 | props: { 36 | size: 'small' 37 | } 38 | }, 39 | { 40 | type: 'switch', 41 | field: 'disabled', 42 | title: '禁用', 43 | props: { 44 | size: 'small' 45 | } 46 | }, 47 | { 48 | type: 'switch', 49 | field: 'clearable', 50 | title: '是否可清空', 51 | value: false, 52 | props: { 53 | size: 'small' 54 | } 55 | }, 56 | { 57 | type: 'input', 58 | field: 'placeholder', 59 | title: '选择框的占位符', 60 | }, 61 | { 62 | type: 'input', 63 | field: 'timeZone', 64 | title: '时区', 65 | props: { 66 | disabled: true 67 | } 68 | }, 69 | { 70 | type: 'switch', 71 | field: 'use-12-hours', 72 | title: '是否使用 12 小时制的面板', 73 | value: false, 74 | props: { 75 | size: 'small' 76 | } 77 | }, 78 | { 79 | type: 'select', 80 | field: 'placement', 81 | title: '菜单的弹出位置', 82 | value: 'bottom', 83 | options: [ 84 | { label: 'top-start', value: 'top-start' }, 85 | { label: 'top', value: 'top' }, 86 | { label: 'top-end', value: 'top-end' }, 87 | { label: 'right-start', value: 'right-start' }, 88 | { label: 'right', value: 'right' }, 89 | { label: 'right-end', value: 'right-end' }, 90 | { label: 'bottom-start', value: 'bottom-start' }, 91 | { label: 'bottom', value: 'bottom' }, 92 | { label: 'bottom-end', value: 'bottom-end' }, 93 | { label: 'left-start', value: 'left-start' }, 94 | { label: 'left', value: 'left' }, 95 | { label: 'left-end', value: 'left-end' }, 96 | ] 97 | } 98 | ]); 99 | } 100 | }; 101 | -------------------------------------------------------------------------------- /src/config/rule/transfter.js: -------------------------------------------------------------------------------- 1 | import uniqueId from '@form-create/utils/lib/unique'; 2 | import { h } from 'vue'; 3 | import { localeProps } from '../../utils'; 4 | 5 | const label = '穿梭框'; 6 | const name = 'n-transfer'; 7 | 8 | const generateData = () => { 9 | return Array.from({ length: 10 }).map((v, i) => ({ 10 | label: 'Option ' + i, 11 | value: i, 12 | disabled: i % 4 === 0 13 | })) 14 | }; 15 | 16 | export default { 17 | icon: 'icon-transfer', 18 | label, 19 | name, 20 | rule({ t }) { 21 | return { 22 | type: name, 23 | field: uniqueId(), 24 | title: t('components.n-transfer.name'), 25 | info: '', 26 | $required: false, 27 | props: { 28 | options: generateData() 29 | } 30 | }; 31 | }, 32 | props(_, { t }) { 33 | return localeProps(t, name + '.props', [ 34 | { 35 | type: 'Struct', 36 | field: 'options', 37 | title: 'Transfer 的数据源', 38 | props: { defaultValue: [] } 39 | }, 40 | { 41 | type: 'Struct', 42 | field: 'defaultValue', 43 | title: '默认值', 44 | props: { defaultValue: [] } 45 | }, 46 | { 47 | type: 'input', 48 | field: 'sourceTitle', 49 | title: '源项标题' 50 | }, 51 | { 52 | type: 'input', 53 | field: 'targetTitle', 54 | title: '目标项标题' 55 | }, 56 | { 57 | type: 'switch', 58 | field: 'sourceFilterable', 59 | title: '源项是否可过滤', 60 | props: { 61 | size: 'small' 62 | }, 63 | control: [ 64 | { 65 | value: true, 66 | rule: [ 67 | { 68 | type: 'input', 69 | field: 'sourceFilterPlaceholder', 70 | title: '源项搜索框中的占位符' 71 | } 72 | ] 73 | } 74 | ] 75 | }, 76 | { 77 | type: 'switch', 78 | field: 'targetFilterable', 79 | title: '目标项是否可过滤', 80 | props: { 81 | size: 'small' 82 | }, 83 | control: [ 84 | { 85 | value: true, 86 | rule: [ 87 | { 88 | type: 'input', 89 | field: 'targetFilterPlaceholder', 90 | info: t('bug.transfter'), 91 | title: '目标项搜索框中的占位符' 92 | } 93 | ] 94 | } 95 | ] 96 | }, 97 | { 98 | type: 'switch', 99 | field: 'showSelected', 100 | title: '是否显示源列表中选中的项', 101 | value: true, 102 | props: { 103 | size: 'small', 104 | } 105 | }, 106 | ]) 107 | } 108 | 109 | }; 110 | -------------------------------------------------------------------------------- /src/config/rule/tree.js: -------------------------------------------------------------------------------- 1 | import uniqueId from '@form-create/utils/lib/unique'; 2 | import { localeProps, makeOptionsRule, makeRequiredRule } from '../../utils/index'; 3 | 4 | const label = '树形控件'; 5 | const name = 'tree'; 6 | 7 | export default { 8 | icon: 'icon-tree', 9 | label, 10 | name, 11 | rule({ t }) { 12 | const opt = t('props.option'); 13 | return { 14 | type: name, 15 | field: uniqueId(), 16 | title: t('components.tree.name'), 17 | info: '', 18 | effect: { 19 | fetch: '' 20 | }, 21 | $required: false, 22 | props: { 23 | props: { 24 | label: 'label', 25 | }, 26 | nodeKey: 'key', 27 | data: [1, 2].map(value => { 28 | return { 29 | label: opt + value, 30 | key: value, 31 | children: [ 32 | { 33 | label: opt + value + value, 34 | key: value + "" + value, 35 | } 36 | ], 37 | } 38 | }), 39 | }, 40 | }; 41 | }, 42 | props(_, { t }) { 43 | return localeProps(t, name + '.props', [ 44 | makeRequiredRule(), 45 | makeOptionsRule(t, 'props.data', false), 46 | { 47 | type: 'switch', 48 | field: 'accordion', 49 | title: '是否使用手风琴展开模式', 50 | props: { 51 | size: 'small' 52 | } 53 | }, 54 | { 55 | type: 'switch', 56 | field: 'animated', 57 | title: '是否有展开动画', 58 | value: true, 59 | props: { 60 | size: 'small' 61 | } 62 | }, 63 | { 64 | type: 'switch', 65 | field: 'cancelable', 66 | title: '选中之后是否允许取消', 67 | value: true, 68 | props: { 69 | size: 'small' 70 | } 71 | }, 72 | { 73 | type: 'switch', 74 | field: 'cascade', 75 | title: '是否关联选项', 76 | props: { 77 | size: 'small' 78 | } 79 | }, 80 | { 81 | type: 'switch', 82 | field: 'checkable', 83 | title: '是否显示选择框', 84 | value: true, 85 | props: { 86 | size: 'small' 87 | }, 88 | control: [ 89 | { 90 | value: true, 91 | rule: [ 92 | { 93 | type: 'select', 94 | field: 'checkboxPlacement', 95 | title: '复选框的位置', 96 | value: 'left', 97 | options: [ 98 | { label: '左边', value: 'left' }, 99 | { label: '右边', value: 'right' }, 100 | ] 101 | } 102 | ] 103 | } 104 | ] 105 | }, 106 | { 107 | type: 'select', 108 | field: 'checkStrategy', 109 | title: '勾选策略', 110 | value: 'all', 111 | info: t('components.tree.props.checkStrategyInfo'), 112 | options: [ 113 | { label: t('components.tree.props.all'), value: 'all' }, 114 | { label: t('components.tree.props.parent'), value: 'parent' }, 115 | { label: t('components.tree.props.child'), value: 'child' } 116 | ] 117 | }, 118 | { 119 | type: 'input', 120 | field: 'childrenField', 121 | title: '自定义 children 字段名', 122 | info: t('components.tree.props.customInfo'), 123 | props: { 124 | placeholder: 'children' 125 | } 126 | }, 127 | { 128 | type: 'input', 129 | field: 'keyField', 130 | title: '自定义 key 字段名', 131 | props: { 132 | placeholder: 'key' 133 | } 134 | }, 135 | { 136 | type: 'input', 137 | field: 'labelField', 138 | title: '自定义 label 字段名', 139 | props: { 140 | placeholder: 'label' 141 | } 142 | }, 143 | { 144 | type: 'input', 145 | field: 'disabledField', 146 | title: '自定义 disabled 字段名', 147 | props: { 148 | placeholder: 'disabled' 149 | } 150 | }, 151 | ]); 152 | } 153 | }; 154 | -------------------------------------------------------------------------------- /src/config/rule/upload.js: -------------------------------------------------------------------------------- 1 | import uniqueId from '@form-create/utils/lib/unique'; 2 | import { localeProps, makeRequiredRule } from '../../utils'; 3 | 4 | const label = '上传'; 5 | const name = 'upload'; 6 | 7 | export default { 8 | icon: 'icon-upload', 9 | label, 10 | name, 11 | rule({ t }) { 12 | return { 13 | type: name, 14 | field: uniqueId(), 15 | title: t('components.upload.name'), 16 | info: '', 17 | $required: false, 18 | props: { 19 | action: '', 20 | onSuccess(res, file) { 21 | file.url = res.data.url; 22 | }, 23 | limit: 1, 24 | }, 25 | }; 26 | }, 27 | props(_, { t }) { 28 | return localeProps(t, name + '.props', [ 29 | makeRequiredRule(), 30 | { 31 | type: 'input', 32 | field: 'action', 33 | title: '请求提交的地址(必填)' 34 | }, 35 | { 36 | type: 'Struct', 37 | field: 'headers', 38 | title: 'HTTP 请求需要附加的 Headers', 39 | props: { defaultValue: {} } 40 | }, 41 | { 42 | type: 'switch', 43 | field: 'multiple', 44 | title: '是否支持多个文件', 45 | props: { 46 | size: 'small' 47 | } 48 | }, 49 | { 50 | type: 'Struct', 51 | field: 'data', 52 | title: '提交表单需要附加的数据', 53 | props: { 54 | defaultValue: {} 55 | } 56 | }, 57 | { 58 | type: 'input', 59 | field: 'name', 60 | title: '文件在提交表单中的字段名' 61 | }, { 62 | type: 'switch', 63 | field: 'withCredentials', 64 | title: '是否携带 Cookie', 65 | props: { 66 | size: 'small' 67 | } 68 | }, 69 | { 70 | type: 'input', 71 | field: 'accept', 72 | info: t('components.upload.props.acceptInfo'), 73 | title: '接受的文件类型(thumbnail-mode 模式下此参数无效)' 74 | }, 75 | { 76 | type: 'switch', 77 | field: 'defaultUpload', 78 | title: '选择文件时候是否默认上传', 79 | value: true, 80 | props: { 81 | size: 'small' 82 | } 83 | }, 84 | { 85 | type: 'switch', 86 | field: 'disabled', 87 | title: '是否禁用', 88 | props: { 89 | size: 'small' 90 | } 91 | }, 92 | { 93 | type: 'inputNumber', 94 | field: 'max', 95 | title: '限制上传文件数量', 96 | value: 1, 97 | props: { min: 1 }, 98 | }, 99 | { 100 | type: 'switch', 101 | field: 'showCancelButton', 102 | title: '是否显示取消按钮', 103 | value: true, 104 | props: { 105 | size: 'small' 106 | } 107 | }, 108 | { 109 | type: 'switch', 110 | field: 'showDownloadButton', 111 | title: '是否显示下载按钮', 112 | value: false, 113 | props: { 114 | size: 'small' 115 | } 116 | }, 117 | { 118 | type: 'switch', 119 | field: 'showRemoveButton', 120 | title: '是否显示删除按钮', 121 | value: true, 122 | props: { 123 | size: 'small' 124 | } 125 | }, 126 | { 127 | type: 'switch', 128 | field: 'showRetryButton', 129 | title: '是否显示重新上传按钮', 130 | value: true, 131 | props: { 132 | size: 'small' 133 | } 134 | }, 135 | { 136 | type: 'switch', 137 | field: 'showFileList', 138 | title: '是否显示文件列表', 139 | value: true, 140 | props: { 141 | size: 'small' 142 | } 143 | }, 144 | { 145 | type: 'switch', 146 | field: 'showPreviewButton', 147 | title: '是否允许显示预览按钮', 148 | info: t('components.upload.props.showPreviewButtonInfo'), 149 | value: true, 150 | props: { 151 | size: 'small' 152 | } 153 | }, 154 | ]); 155 | } 156 | }; 157 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import './style/index.css'; 2 | import formCreate from './utils/form'; 3 | import {designerForm} from './utils/form'; 4 | import Fetch from './components/Fetch.vue'; 5 | import Struct from './components/Struct.vue'; 6 | import {makeOptionsRule} from './utils/index'; 7 | import DragBox from './components/DragBox.vue'; 8 | import DragTool from './components/DragTool.vue'; 9 | import Required from './components/Required.vue'; 10 | import Validate from './components/Validate.vue'; 11 | import unique from '@form-create/utils/lib/unique'; 12 | import FcDesigner from './components/FcDesigner.vue'; 13 | import draggable from 'vuedraggable/src/vuedraggable'; 14 | import ColorPicker from './components/ColorPicker.vue' 15 | import CustomAlert from './components/CustomAlert.vue'; 16 | import FcEditor from '@form-create/component-wangeditor'; 17 | import TableOptions from './components/TableOptions.vue'; 18 | 19 | designerForm.component('draggable', draggable); 20 | designerForm.component('DragTool', DragTool); 21 | designerForm.component('DragBox', DragBox); 22 | designerForm.component('Required', Required); 23 | designerForm.component('Validate', Validate); 24 | designerForm.component('Struct', Struct); 25 | designerForm.component('TableOptions', TableOptions); 26 | designerForm.component('ColorPicker', ColorPicker); 27 | designerForm.component('CustomAlert', CustomAlert); 28 | designerForm.component('FcEditor', FcEditor); 29 | designerForm.component('Fetch', Fetch); 30 | formCreate.component('FcEditor', FcEditor); 31 | 32 | 33 | designerForm.register('_fc', { 34 | init(fc, rule) { 35 | rule._id = unique(); 36 | if (fc.repeat) 37 | rule.field = unique(); 38 | if (fc.value) { 39 | rule.effect._fc = false; 40 | } 41 | } 42 | }); 43 | 44 | designerForm.register('_fc_tool', { 45 | init(_, rule) { 46 | rule.props.unique = unique(); 47 | } 48 | }); 49 | 50 | const install = function (Vue) { 51 | Vue.component('FcDesigner', FcDesigner); 52 | }; 53 | 54 | FcDesigner.install = install; 55 | FcDesigner.makeOptionsRule = makeOptionsRule; 56 | FcDesigner.formCreate = formCreate; 57 | FcDesigner.designerForm = designerForm 58 | 59 | export default FcDesigner; 60 | 61 | export {formCreate, designerForm, install}; -------------------------------------------------------------------------------- /src/locale/en.js: -------------------------------------------------------------------------------- 1 | const En = { 2 | name: 'en', 3 | form: { 4 | field: 'Field', 5 | title: 'Title', 6 | info: 'Info', 7 | control: 'Control', 8 | clear: 'Clear', 9 | refresh: 'Refresh', 10 | labelPlacement: 'Label position', 11 | size: 'Form size', 12 | labelWidth: 'Label width', 13 | showRequireMark: 'The required asterisk is not displayed', 14 | showRequireMarkInfo: 'It is irreversible!!!', 15 | hideRequireMarkLabel: 'hide', 16 | placementRequireMark: 'Require mark placement', 17 | showFeedback: 'Display verification Feedback', 18 | submitBtn: 'Whether to display the form submit button', 19 | resetBtn: 'Whether to display the form reset button', 20 | submit: 'Submit', 21 | reset: 'Reset', 22 | }, 23 | validate: { 24 | type: 'Value type', 25 | typePlaceholder: 'Please select', 26 | trigger: 'Trigger mode', 27 | mode: 'Verification method', 28 | modes: { 29 | required: 'required', 30 | pattern: 'regular expression', 31 | min: 'minimum value', 32 | max: 'maximum value', 33 | len: 'length', 34 | }, 35 | message: 'Error message', 36 | auto: 'Get automatically', 37 | autoRequired: 'Please enter {title}', 38 | autoMode: 'Please enter the correct {title}', 39 | requiredPlaceholder: 'Please enter a prompt', 40 | }, 41 | tableOptions: { 42 | handle: 'Delete', 43 | add: 'Add', 44 | }, 45 | struct: { 46 | title: 'Edit Data', 47 | submit: 'OK', 48 | cancel: 'Cancel', 49 | error: 'The format of the input content is incorrect', 50 | }, 51 | fetch: { 52 | action: 'Action', 53 | actionRequired: 'Please data action', 54 | method: 'Method', 55 | dataType: 'Date type', 56 | data: 'Attached data', 57 | headers: 'Headers', 58 | parse: 'Analysis function', 59 | parseInfo: 'Parse the interface data and return the data structure required by the component', 60 | parseValidate: 'Please enter the correct parsing function', 61 | }, 62 | designer: { 63 | preview: 'Preview', 64 | clear: 'Clear', 65 | clearConfirm: 'Clear', 66 | clearCancel: 'Cancel', 67 | clearConfirmTitle: 'It will not be restored after cleared, are you sure you want to clear it? ', 68 | config: { 69 | component: 'Component', 70 | form: 'Form', 71 | rule: 'Basic', 72 | props: 'Property', 73 | validate: 'Verify', 74 | }, 75 | }, 76 | menu: { 77 | main: 'Form', 78 | aide: 'Auxiliary', 79 | layout: 'Layout', 80 | }, 81 | props: { 82 | required: 'Is it required', 83 | options: 'Option data', 84 | option: 'Option', 85 | optionsType: { 86 | json: 'JSON', 87 | fetch: 'Fetch', 88 | struct: 'Struct', 89 | } 90 | }, 91 | components: { 92 | radio: { 93 | name: 'Radio', 94 | props: { 95 | disabled: 'Whether to disable', 96 | type: 'Button form', 97 | textColor: 'The text color of the radio when the button is activated', 98 | fill: 'The fill color and border color when the radio in the button form is activated' 99 | } 100 | }, 101 | checkbox: { 102 | name: 'Checkbox', 103 | props: { 104 | type: 'Button type', 105 | disabled: 'Whether to disable', 106 | min: 'The minimum number of checkboxes that can be checked', 107 | max: 'The maximum number of checkboxes that can be checked', 108 | textColor: 'The text color of the checkbox in the button form when it is activated', 109 | fill: 'The fill color and border color of the checkbox in the button form when it is activated' 110 | } 111 | }, 112 | input: { 113 | name: 'Input', 114 | props: { 115 | type: 'Type', 116 | maxlength: 'Maximum input length', 117 | minlength: 'Minimum input length', 118 | showWordLimit: 'Whether to display input word count statistics', 119 | placeholder: 'Input box placeholder text', 120 | clearable: 'Whether it can be cleared', 121 | showPassword: 'Whether to display the switch password icon', 122 | disabled: 'Disabled', 123 | rowsInfo: 'Only works when type is \'textarea\'', 124 | rows: 'Number of input box rows', 125 | readonly: 'Whether read-only', 126 | autofocus: 'Automatically acquire focus' 127 | } 128 | }, 129 | inputNumber: { 130 | name: 'Number', 131 | props: { 132 | min: 'Set the minimum value allowed by the counter', 133 | max: 'Set the maximum value allowed by the counter', 134 | step: 'Counter step size', 135 | precision: 'Precision of input value', 136 | stepStrictly: 'Whether only multiples of step can be entered', 137 | disabled: 'Whether to disable the counter', 138 | showButton: 'Whether to show increase/decrease buttons', 139 | buttonPlacement: 'Placement of add & minus button', 140 | placeholder: 'Placeholder' 141 | } 142 | }, 143 | select: { 144 | name: 'Select', 145 | props: { 146 | multiple: 'Whether to choose multiple', 147 | disabled: 'Whether to disable', 148 | clearable: 'Is it possible to clear the options', 149 | maxTagCount: 'Whether to display the selected value in the form of text when multiple selection', 150 | placeholder: 'Placeholder', 151 | filterable: 'Whether options can be filtered', 152 | tag: 'Whether to allow users to create new entries', 153 | remote: 'Allows options to be fetched asynchronously', 154 | remoteInfo: "Note that if remote is set, filter & create new options won't work on options", 155 | onSearch: 'Callback triggered when a search is conducted', 156 | clearFilterAfterSelect: 'When multiple and filter is true, whether to clear filter keyword after select an option', 157 | placement: "Option menu's placement", 158 | } 159 | }, 160 | switch: { 161 | name: 'Switch', 162 | props: { 163 | disabled: 'Whether to disable', 164 | checkedValue: 'Value of checked state', 165 | uncheckedValue: 'Value of unchecked state', 166 | size: 'Size', 167 | sizeInfo: 'The size of the Switch does not change with the form (Bug?)' 168 | } 169 | }, 170 | slider: { 171 | name: 'Slider', 172 | props: { 173 | defaultValue: 'Default value', 174 | min: 'Max value of the slider', 175 | max: 'Min value of the slider', 176 | disabled: 'Whether the slider is disabled', 177 | step: 'Step size', 178 | tooltip: 'Whether to show tooltip', 179 | range: 'Whether it is a range selection', 180 | vertical: 'Whether to enable vertical mode', 181 | reverse: 'Whether to reverse the track', 182 | placement: "Tooltip's placement", 183 | showTooltip: 'Whether to always show tooltip', 184 | showTooltipInfo: 'Only work with non-range slider', 185 | } 186 | }, 187 | timePicker: { 188 | name: 'TimePicker', 189 | props: { 190 | pickerOptions: 'Options specific to the current time and date picker', 191 | inputReadonly: 'Readonly state', 192 | inputReadonlyInfo: 'Avoids virtual keyboard on touch devices', 193 | disabled: 'Disabled', 194 | editable: 'The text box can be entered', 195 | clearable: 'Whether the value is clearable', 196 | placeholder: 'Placeholder', 197 | 'use-12-hours': 'Whether to use a 12-hour clock panel', 198 | timeZone: 'Time zone to be used to format the value', 199 | placement: "Option menu's placement" 200 | } 201 | }, 202 | datePicker: { 203 | name: 'DatePicker', 204 | props: { 205 | pickerOptions: 'Options specific to the current time and date picker', 206 | inputReadonly: 'Set the readonly attribute of the input', 207 | inputReadonlyInfo: 'Avoids virtual keyboard on touch devices', 208 | disabled: 'Disabled', 209 | type: 'Date picker type', 210 | clearable: 'Whether the date picker is clearable', 211 | placeholder: 'Placeholder', 212 | format: 'The format displayed in the input box', 213 | placement: "Panel's placement", 214 | } 215 | }, 216 | rate: { 217 | name: 'Rate', 218 | props: { 219 | size: 'Icon size', 220 | sizeInfo: 'The size of the rate does not change with the form (Bug?)', 221 | count: 'Number of icons (max rating)', 222 | defaultValue: 'Default value of activated icons', 223 | readonly: 'Readonly state', 224 | allowHalf: 'Allow activating half of the icon', 225 | clearable: 'Whether the rate is clearable', 226 | clearableInfo: "Value will be set to null if you click on current value's corresponding icon", 227 | color: 'The color of the unselected icon', 228 | } 229 | }, 230 | colorPicker: { 231 | name: 'ColorPicker', 232 | props: { 233 | confirm: 'Confrim', 234 | clear: 'Clear', 235 | disabled: 'Whether to disable the color picker', 236 | actions: 'The types of buttons to be shown in the panel', 237 | showAlpha: 'Whether the alpha channel can be adjusted', 238 | defaultValue: 'Default value of the picker', 239 | modes: 'The value format of the picker', 240 | modesInfo: 'Notice that value will follow the mode once you select a new value from the picker' 241 | } 242 | }, 243 | row: { 244 | name: 'Grid Layout', 245 | props: { 246 | gutter: 'Grid Interval', 247 | } 248 | }, 249 | col: { 250 | name: 'Grid', 251 | props: { 252 | span: 'The number of columns occupied by the grid', 253 | offset: 'Number of grids on the left side of the grid', 254 | push: 'The grid moves to the right by the number of grids', 255 | pull: 'The grid moves to the left by the number of grids' 256 | } 257 | }, 258 | tab: { 259 | name: 'Tab', 260 | props: { 261 | type: 'Tabs type', 262 | size: 'Size of tabs', 263 | trigger: 'Trigger of activating a tab', 264 | barWidth: 'The width of the tab bar', 265 | closable: 'Whether to allow the tag to be closed', 266 | animated: 'Whether to activate tab switching animation', 267 | tabsPadding: 'Left & right padding of the group of tabs', 268 | defaultValue: 'Default value in uncontrolled mode', 269 | closableInfo: "Only works when the tag's type is card", 270 | defaultValueInfo: 'After modifying the corresponding tab logo, the value needs to be updated at the same time', 271 | justifyContent: 'Justify-content value of flex layout', 272 | justifyContentInfo: "Only works with 'line' or 'bar' typed tabs", 273 | 274 | } 275 | }, 276 | 'tab-pane': { 277 | name: 'TabPane', 278 | props: { 279 | name: 'Required, the name of the tab', 280 | tab: 'Tab label', 281 | disabled: 'Whether to disable the tabs', 282 | closable: 'Whether to allow the tag to be closed', 283 | nameInfo: 'Modifying the identity needs to update the identity of the parent component synchronously', 284 | closableInfo: "Only works when the tag's type is card", 285 | displayDirective: 'The directive to use in conditionally rendering', 286 | if: "tab-panel's content will be reset after tab changes", 287 | show: "tab-panel's content won't be reset after tab changes", 288 | showLazy: "tab-panel's content will be lazily loaded && won't be reset after tab changes" 289 | } 290 | }, 291 | 'n-divider': { 292 | name: 'Divider', 293 | props: { 294 | vertical: 'Whether to show vertical direction', 295 | formCreateChild: 'Set the dividing line text', 296 | titlePlacement: 'Title placement' 297 | } 298 | }, 299 | cascader: { 300 | name: 'Cascader', 301 | props: { 302 | props: 'Configuration options', 303 | size: 'Size', 304 | cascade: 'Whether to cascade the checkbox selection onto children', 305 | placeholder: 'Input box placeholder text', 306 | disabled: 'Whether to disable', 307 | clearable: 'Whether the cascader is clearable', 308 | filterable: 'Whether the cascader is searchable', 309 | filterableInfo: 'Whether the cascader is searchable', 310 | showPath: 'Whether to show the selected options as a path', 311 | multiple: 'Whether to allow multiple options being selected', 312 | clearFilterAfterSelect: 'When multiple and filter is true, whether to clear filter keyword after select an option', 313 | placement:'Cascader placement', 314 | maxTagCount: 'Max tag count in multiple select mode', 315 | separator: 'Selected option path value separator ', 316 | customInfo: 'All kinds of data will come from the back-end', 317 | labelField: 'The label field in CascaderOption', 318 | valueField: 'The value field in CascaderOption', 319 | checkStrategy: 'Check Strategy', 320 | checkStrategyInfo: 'The way to show checked options', 321 | all: 'showing all checked node', 322 | parent: 'showing all checked parent node', 323 | parentInfo: 'when all child node are checked (not working in single select mode)', 324 | child: 'showing all child node', 325 | } 326 | }, 327 | upload: { 328 | name: 'Upload', 329 | props: { 330 | action: 'The URL to submit data to (required)', 331 | headers: 'The additional HTTP Headers of request', 332 | multiple: 'Allow multiple files to be selected', 333 | data: "The additional fileds data of HTTP request's form data", 334 | name: "The field name for the file(s) in the HTTP request's form data", 335 | withCredentials: 'Any credentials to be sent with the request (e.g. cookie)', 336 | accept: 'Accept the uploaded file type (this parameter is invalid in thumbnail-mode mode)', 337 | acceptInfo: 'Reference https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/input/file#accept', 338 | defaultUpload: 'If file uploaded immediatelly after file is selected', 339 | disabled: 'Whether to disable the upload', 340 | max: 'Uploaded files limit', 341 | showCancelButton: 'Show a cancel button ', 342 | showDownloadButton: 'Show a download button', 343 | showRemoveButton: 'Show a remove button', 344 | showRetryButton: 'Show a retry button', 345 | showFileList: 'Show a file list', 346 | showPreviewButton: 'Show a preview button', 347 | showPreviewButtonInfo: 'when list-type is image-card). Use the on-preview callback for this event', 348 | } 349 | }, 350 | 'n-transfer': { 351 | name: 'Transfer', 352 | props: { 353 | data: 'Transfer\'s data source', 354 | defaultValue: 'Default value', 355 | showSelected: 'Whether to show selected options in the source list', 356 | sourceFilterable: 'The source filterable state', 357 | sourceFilterPlaceholder: 'Placeholder for the source items search box', 358 | targetFilterable: 'The target filterable state', 359 | targetFilterPlaceholder: 'Placeholder for the target items search box', 360 | targetTitle: 'Target items title', 361 | sourceTitle: 'Source items title', 362 | } 363 | }, 364 | tree: { 365 | name: 'Tree', 366 | props: { 367 | accordion: 'Whether to use accrodion expand mode', 368 | animated: 'Whether to show expand animation', 369 | cancelable: "Whether node's select status can be cancelled", 370 | cascade: 'Whether to cascade checkboxes', 371 | checkable: 'Whether to display the selection box', 372 | checkboxPlacement: "Checkbox's placement", 373 | checkStrategy: 'The strategy of setting checked', 374 | checkStrategyInfo: "The strategy of setting checked callback's keys argument", 375 | all: 'setting all checked node', 376 | parent: 'setting all checked parent node', 377 | child: 'setting all child node', 378 | childrenField: 'The children field in TreeOption', 379 | keyField: 'The key field in TreeOption', 380 | labelField: 'The label field in TreeOption', 381 | disabledField: 'The disabled field in TreeOption', 382 | } 383 | }, 384 | 'n-alert': { 385 | name: 'Alert', 386 | description: 'Description', 387 | props: { 388 | title: 'Title', 389 | type: 'Alert type', 390 | description: 'Description', 391 | closable: 'Whether it can be closed', 392 | showIcon: 'Whether to display the icon', 393 | center: 'Center', 394 | width: 'Width' 395 | } 396 | }, 397 | span: { 398 | name: 'Text', 399 | props: { 400 | formCreateTitle: 'Title', 401 | formCreateChild: 'Content' 402 | } 403 | }, 404 | div: { 405 | name: 'Space', 406 | props: { 407 | height: 'height', 408 | } 409 | }, 410 | 'n-button': { 411 | name: 'Button', 412 | props: { 413 | formCreateChild: 'Button content', 414 | size: 'Button size', 415 | type: 'Button type', 416 | color: 'Button color', 417 | textColor: 'Button text color', 418 | round: 'Whether the button shows rounded corners', 419 | circle: 'Whether the button is round', 420 | loading: 'Whether the button shows the loading status', 421 | disabled: 'Whether the button is disabled', 422 | secondary: 'Whether the button is secondary button', 423 | tertiary: 'Whether the button is tertiary button', 424 | quaternary: 'Whether the button is quaternary button', 425 | text: 'Whether to display as a text button', 426 | dashed: "Whether the button's border is a dashed line", 427 | ghost: 'Whether the button is ghost', 428 | strong: 'Whether to use strong text in the button', 429 | tag: 'What tag need the button be rendered as', 430 | } 431 | }, 432 | 'fc-editor': { 433 | name: 'Editor', 434 | props: { 435 | disabled: 'Whether to disable' 436 | } 437 | } 438 | }, 439 | aboutTime: { 440 | date: 'date', 441 | datetime: 'datetime', 442 | daterange: 'daterange', 443 | datetimerange: 'datetimerange', 444 | month: 'month', 445 | monthrange: 'monthrange', 446 | year: 'year', 447 | yearrange: 'yearrange', 448 | quarter: 'quarter', 449 | quarterrange: 'quarterrange', 450 | }, 451 | bug: { 452 | transfter: "Kidding? (NaiveUI's BUG)" 453 | }, 454 | }; 455 | 456 | export default En; 457 | 458 | -------------------------------------------------------------------------------- /src/locale/zh-cn.js: -------------------------------------------------------------------------------- 1 | const ZhCn = { 2 | name: 'zh-cn', 3 | form: { 4 | field: '字段 ID', 5 | title: '字段名称', 6 | info: '提示信息', 7 | control: '联动数据', 8 | clear: '清空值', 9 | refresh: '刷新', 10 | labelPlacement: '标签位置', 11 | size: '表单尺寸', 12 | labelWidth: '标签宽度', 13 | showRequireMark: '不显示必填的星号', 14 | showRequireMarkInfo: '不可逆操作!!!', 15 | hideRequireMarkLabel: '不显示', 16 | placementRequireMark: '必填星号的位置', 17 | showFeedback: '是否展示校验反馈', 18 | submitBtn: '是否显示表单提交按钮', 19 | resetBtn: '是否显示表单重置按钮', 20 | submit: '提交', 21 | reset: '重置', 22 | }, 23 | validate: { 24 | type: '字段类型', 25 | typePlaceholder: '请选择', 26 | trigger: '触发方式', 27 | mode: '验证方式', 28 | modes: { 29 | required: '必填', 30 | pattern: '正则表达式', 31 | min: '最小值', 32 | max: '最大值', 33 | len: '长度', 34 | }, 35 | message: '错误信息', 36 | auto: '自动获取', 37 | autoRequired: '请输入{title}', 38 | autoMode: '请输入正确的{title}', 39 | requiredPlaceholder: '请输入提示语', 40 | }, 41 | tableOptions: { 42 | handle: '操作', 43 | add: '添加', 44 | }, 45 | struct: { 46 | title: '编辑数据', 47 | submit: '确 定', 48 | cancel: '取 消', 49 | error: '输入内容格式有误', 50 | }, 51 | fetch: { 52 | action: '接口', 53 | actionRequired: '请数据接口', 54 | method: '请求方式', 55 | dataType: '提交方式', 56 | data: '附带数据', 57 | headers: 'header信息', 58 | parse: '解析函数', 59 | parseInfo: '解析接口数据,返回组件所需的数据结构', 60 | parseValidate: '请输入正确的解析函数', 61 | }, 62 | designer: { 63 | preview: '预 览', 64 | clear: '清 空', 65 | clearConfirm: '清空', 66 | clearCancel: '取消', 67 | clearConfirmTitle: '清空后将不能恢复,确定要清空吗?', 68 | config: { 69 | component: '组件配置', 70 | form: '表单配置', 71 | rule: '基础配置', 72 | props: '属性配置', 73 | validate: '验证配置', 74 | }, 75 | }, 76 | menu: { 77 | main: '表单组件', 78 | aide: '辅助组件', 79 | layout: '布局组件', 80 | }, 81 | props: { 82 | required: '是否必填', 83 | options: '选项数据', 84 | option: '选项', 85 | optionsType: { 86 | json: 'JSON数据', 87 | fetch: '接口数据', 88 | struct: '静态数据', 89 | } 90 | }, 91 | components: { 92 | radio: { 93 | name: '单选框', 94 | props: { 95 | disabled: '是否禁用', 96 | type: '按钮形式', 97 | textColor: '按钮形式的 Radio 激活时的文本颜色', 98 | fill: '按钮形式的 Radio 激活时的填充色和边框色' 99 | } 100 | }, 101 | checkbox: { 102 | name: '多选框', 103 | props: { 104 | type: '按钮类型', 105 | disabled: '是否禁用', 106 | min: '可被勾选的 checkbox 的最小数量', 107 | max: '可被勾选的 checkbox 的最大数量', 108 | textColor: '按钮形式的 Checkbox 激活时的文本颜色', 109 | fill: '按钮形式的 Checkbox 激活时的填充色和边框色' 110 | } 111 | }, 112 | input: { 113 | name: '输入框', 114 | props: { 115 | type: '类型', 116 | maxlength: '最大输入长度', 117 | minlength: '最小输入长度', 118 | showWordLimit: '是否显示输入字数统计', 119 | placeholder: '输入框占位文本', 120 | clearable: '是否可清空', 121 | showPassword: '是否显示切换密码图标', 122 | disabled: '禁用', 123 | rowsInfo: '只对 type="textarea" 有效', 124 | rows: '输入框行数', 125 | readonly: '是否只读', 126 | resize: '控制是否能被用户缩放', 127 | autofocus: '自动获取焦点' 128 | } 129 | }, 130 | inputNumber: { 131 | name: '计数器', 132 | props: { 133 | min: '设置计数器允许的最小值', 134 | max: '设置计数器允许的最大值', 135 | step: '计数器步长', 136 | precision: '数值保留的精度值', 137 | stepStrictly: '是否只能输入 step 的倍数', 138 | disabled: '是否禁用计数器', 139 | showButton: '是否有按钮', 140 | buttonPlacement: '加减按钮的位置', 141 | placeholder: '提示信息', 142 | } 143 | }, 144 | select: { 145 | name: '选择器', 146 | props: { 147 | multiple: '是否多选', 148 | disabled: '是否禁用', 149 | clearable: '是否可以清空选项', 150 | maxTagCount: '多选标签的最大显示数量', 151 | placeholder: '占位符', 152 | filterable: '是否可以过滤', 153 | tag: '是否允许用户创建新条目', 154 | remote: '是否要异步获取选项', 155 | remoteInfo: '注意开启该选项过滤和创建新条目将不再生效', 156 | onSearch: '搜索时执行的回调', 157 | clearFilterAfterSelect: '是否在可过滤和多选的情况下选中一个选项后保留当前的搜索关键词', 158 | placement: '菜单的弹出位置', 159 | } 160 | }, 161 | switch: { 162 | name: '开关', 163 | props: { 164 | disabled: '是否禁用', 165 | checkedValue: '选中时对应的值', 166 | uncheckedValue: '未选中时对应的值', 167 | size: '尺寸', 168 | sizeInfo: '开关的尺寸不随着表单变化(Bug?)', 169 | } 170 | }, 171 | slider: { 172 | name: '滑块', 173 | props: { 174 | defaultValue: '默认值', 175 | min: '最小值', 176 | max: '最大值', 177 | disabled: '是否禁用', 178 | step: '步长', 179 | tooltip: '是否展示 tooltip', 180 | range: '是否为范围选择', 181 | vertical: '是否启用垂直模式', 182 | reverse: '是否倒转轨道', 183 | placement: "Tooltip 的弹出位置", 184 | showTooltip: '是否一直显示 tooltip', 185 | showTooltipInfo: '仅对非 range 生效', 186 | } 187 | }, 188 | timePicker: { 189 | name: '时间选择器', 190 | props: { 191 | pickerOptions: '当前时间日期选择器特有的选项', 192 | inputReadonly: '设置输入框为只读', 193 | inputReadonlyInfo: '避免在移动设备上打开虚拟键盘', 194 | disabled: '禁用', 195 | editable: '文本框可输入', 196 | clearable: '是否可清空', 197 | placeholder: '选择框的占位符', 198 | 'use-12-hours': '是否使用 12 小时制的面板', 199 | timeZone: '格式化值时使用的市区', 200 | placement: '菜单弹出的位置' 201 | } 202 | }, 203 | datePicker: { 204 | name: '日期选择器', 205 | props: { 206 | pickerOptions: '当前时间日期选择器特有的选项', 207 | inputReadonly: '设置输入框为只读', 208 | inputReadonlyInfo: '避免在移动设备上打开虚拟键盘', 209 | disabled: '禁用', 210 | type: '日期选择器的类型', 211 | clearable: '是否支持清除', 212 | placeholder: '提示信息', 213 | format: '显示在输入框中的格式', 214 | placement: '面板的弹出位置', 215 | } 216 | }, 217 | rate: { 218 | name: '评分', 219 | props: { 220 | size: '图标尺寸', 221 | sizeInfo: '评分的尺寸不随着表单变化(Bug?)', 222 | count: '图标个数', 223 | defaultValue: '默认已激活图标个数', 224 | readonly: '只读,交互失效', 225 | allowHalf: '允许只激活一半图标', 226 | clearable: '是否可清空', 227 | clearableInfo: '在点击当前值对应的图标后值会被设为 null', 228 | color: '已激活图标颜色', 229 | } 230 | }, 231 | colorPicker: { 232 | name: '颜色选择器', 233 | props: { 234 | confirm: '确定', 235 | clear: '清除', 236 | disabled: '是否禁用', 237 | actions: '显示按钮', 238 | showAlpha: '是否可调节 alpha 通道', 239 | defaultValue: '默认的颜色值', 240 | modes: '颜色选择器支持颜色的格式', 241 | modesInfo: '注意一旦你在某个模式下选择了值,颜色选择器值的格式将跟随这个格式' 242 | } 243 | }, 244 | row: { 245 | name: '栅格布局', 246 | props: { 247 | gutter: '栅格间隔', 248 | } 249 | }, 250 | col: { 251 | name: '格子', 252 | props: { 253 | span: '栅格占据的列数', 254 | offset: '栅格左侧的间隔格数', 255 | push: '栅格向右移动格数', 256 | pull: '栅格向左移动格数' 257 | } 258 | }, 259 | tab: { 260 | name: '标签页', 261 | props: { 262 | type: '标签类型', 263 | size: '标签页的尺寸', 264 | trigger: '触发 tab 的方式', 265 | barWidth: '标签条的宽度', 266 | closable: '标签是否可关闭', 267 | animated: '标签页切换是否使用动画', 268 | tabsPadding: '全部标签最左和最右的 padding', 269 | defaultValue: '默认展示标签页的标识', 270 | closableInfo: '只在标签的 type 为 card 时生效', 271 | defaultValueInfo: '修改对应标签页标识后需要同时更新该值', 272 | justifyContent: 'flex 布局下主轴的排列方式', 273 | justifyContentInfo: "只对 'line' 和 'bar' 类型生效", 274 | 275 | } 276 | }, 277 | 'tab-pane': { 278 | name: '标签页', 279 | props: { 280 | name: '标签页标识', 281 | tab: '选项卡标题', 282 | disabled: '是否禁用', 283 | closable: '是否允许关闭标签', 284 | nameInfo: '修改标识需要同步更新父组件的标识', 285 | closableInfo: '只在标签的 type 为 card 时生效', 286 | displayDirective: '选择性渲染使用的指令', 287 | if: '内容会随切换重置', 288 | show: '内容不随切换重置', 289 | showLazy: '内容不随切换重置且延迟加载' 290 | } 291 | }, 292 | 'n-divider': { 293 | name: '分割线', 294 | props: { 295 | vertical: '是否垂直分隔', 296 | formCreateChild: '设置分割线文案', 297 | titlePlacement: '标题的位置' 298 | } 299 | }, 300 | cascader: { 301 | name: '级联选择器', 302 | props: { 303 | props: '配置选项', 304 | size: '尺寸', 305 | cascade: '在多选时是否关联选项', 306 | placeholder: '提示信息', 307 | disabled: '是否禁用', 308 | clearable: '是否支持清空选项', 309 | filterable: '是否可搜索', 310 | filterableInfo: 'remote 被设定时不生效', 311 | showPath: '是否在选择器中显示选项路径', 312 | multiple: '是否支持多选', 313 | clearFilterAfterSelect: '是否在可过滤和多选的情况下选中一个选项后保留当前的搜索关键词', 314 | placement:'菜单的弹出位置', 315 | maxTagCount: '多选标签的最大显示数量', 316 | separator: '数据分隔符', 317 | checkStrategy: '勾选策略', 318 | checkStrategyInfo: '指定显示的勾选节点', 319 | all: '显示全部选中节点', 320 | parent: '只显示父节点', 321 | parentInfo: '当父节点下所有子节点都选中时,对于单选无效', 322 | child: '只显示子节点', 323 | } 324 | }, 325 | upload: { 326 | name: '上传', 327 | props: { 328 | action: '请求提交的地址(必填)', 329 | headers: 'HTTP 请求需要附加的 Headers', 330 | multiple: '是否支持多个文件', 331 | data: '提交表单需要附加的数据', 332 | name: '文件在提交表单中的字段名', 333 | withCredentials: '是否携带 Cookie', 334 | accept: '接受的文件类型(thumbnail-mode 模式下此参数无效)', 335 | acceptInfo: '参考 https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/input/file#accept', 336 | defaultUpload: '选择文件时候是否默认上传', 337 | disabled: '是否禁用', 338 | max: '限制上传文件数量', 339 | showCancelButton: '是否显示取消按钮', 340 | showDownloadButton: '是否显示下载按钮', 341 | showRemoveButton: '是否显示删除按钮', 342 | showRetryButton: '是否显示重新上传按钮', 343 | showFileList: '是否显示文件列表', 344 | showPreviewButton: '是否允许显示预览按钮', 345 | showPreviewButtonInfo: '在 list-type 为 image-card 时生效', 346 | } 347 | }, 348 | 'n-transfer': { 349 | name: '穿梭框', 350 | props: { 351 | data: 'Transfer 的数据源', 352 | defaultValue: '默认值', 353 | showSelected: '是否显示源列表中选中的项', 354 | sourceFilterable: '源项是否可过滤', 355 | sourceFilterPlaceholder: '源项搜索框中的占位符', 356 | targetFilterable: '目标项是否可过滤', 357 | targetFilterPlaceholder: '目标项搜索框中的占位符', 358 | targetTitle: '目标项标题', 359 | sourceTitle: '源项标题', 360 | } 361 | }, 362 | tree: { 363 | name: '树形控件', 364 | props: { 365 | accordion: '是否使用手风琴展开模式', 366 | animated: '是否有展开动画', 367 | cancelable: '选中之后是否允许取消', 368 | cascade: '是否关联选项', 369 | checkable: '是否显示选择框', 370 | checkboxPlacement: '复选框的位置', 371 | checkStrategy: '勾选策略', 372 | checkStrategyInfo: '指定勾选回调返回的值', 373 | all: '回调函数值为全部选中节点', 374 | parent: '回调函数值为父节点', 375 | child: '回调函数值为子节点', 376 | childrenField: '自定义 children 字段名', 377 | keyField: '自定义 key 字段名', 378 | labelField: '自定义 label 字段名', 379 | disabledField: '自定义 disabled 字段名', 380 | } 381 | }, 382 | 'n-alert': { 383 | name: '提示', 384 | description: 'description', 385 | props: { 386 | title: '标题', 387 | type: '类型', 388 | description: '描述', 389 | closable: '是否可关闭', 390 | showIcon: '是否显示图标', 391 | center: '组件居中', 392 | width: '设置宽度' 393 | } 394 | }, 395 | span: { 396 | name: '文字', 397 | props: { 398 | formCreateTitle: '标题', 399 | formCreateChild: '内容' 400 | } 401 | }, 402 | div: { 403 | name: '间距', 404 | props: { 405 | height: '高度', 406 | } 407 | }, 408 | 'n-button': { 409 | name: '按钮', 410 | props: { 411 | formCreateChild: '按钮的内容', 412 | size: '按钮的尺寸', 413 | type: '按钮的类型', 414 | color: '按钮颜色', 415 | textColor: '按钮文字颜色', 416 | round: '按钮是否显示圆角', 417 | circle: '按钮是否为圆形', 418 | loading: '按钮是否显示加载状态', 419 | disabled: '按钮是否禁用', 420 | secondary: '是否是次要按钮', 421 | tertiary: '是否是三级按钮', 422 | quaternary: '是否是四级按钮', 423 | text: '是否显示为文本按钮', 424 | dashed: '按钮边框是否为虚线', 425 | ghost: '按钮是否透明', 426 | tag: '按钮需要被渲染成什么标签', 427 | strong: '按钮文字是否加粗' 428 | } 429 | }, 430 | 'fc-editor': { 431 | name: '富文本框', 432 | props: { 433 | disabled: '是否禁用' 434 | } 435 | } 436 | }, 437 | aboutTime: { 438 | date: '日期', 439 | datetime: '日期时间', 440 | daterange: '日期范围', 441 | datetimerange: '日期时间范围', 442 | month: '月份', 443 | monthrange: '月份范围', 444 | year: '年份', 445 | yearrange: '年份范围', 446 | quarter: '季度', 447 | quarterrange: '季度范围', 448 | }, 449 | bug: { 450 | transfter: "跟我隔这玩呢?(NaiveUI's BUG)" 451 | }, 452 | }; 453 | 454 | export default ZhCn; 455 | 456 | -------------------------------------------------------------------------------- /src/style/fonts/fc-icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SX-Code/form-designer-naiveui/176f48e9d0d3bc22dcfe9bd0ad4ef17b453b5dab/src/style/fonts/fc-icons.woff -------------------------------------------------------------------------------- /src/style/index.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: "fc-icon"; 3 | src: url(fonts/fc-icons.woff) format('woff'); 4 | } 5 | 6 | .fc-icon { 7 | font-family: "fc-icon" !important; 8 | font-size: 16px; 9 | font-style: normal; 10 | -webkit-font-smoothing: antialiased; 11 | -moz-osx-font-smoothing: grayscale; 12 | } 13 | 14 | .icon-add-child:before { 15 | content: "\e789"; 16 | } 17 | 18 | .icon-switch:before { 19 | content: "\e77c"; 20 | } 21 | 22 | .icon-tab:before { 23 | content: "\e77b"; 24 | } 25 | 26 | .icon-button:before { 27 | content: "\e77e"; 28 | } 29 | 30 | .icon-input:before { 31 | content: "\e77f"; 32 | } 33 | 34 | .icon-checkbox:before { 35 | content: "\e780"; 36 | } 37 | 38 | .icon-radio:before { 39 | content: "\e781"; 40 | } 41 | 42 | .icon-rate:before { 43 | content: "\e782"; 44 | } 45 | 46 | .icon-number:before { 47 | content: "\e783"; 48 | } 49 | 50 | .icon-upload:before { 51 | content: "\e784"; 52 | } 53 | 54 | .icon-cascader:before { 55 | content: "\e785"; 56 | } 57 | 58 | .icon-space:before { 59 | content: "\e786"; 60 | } 61 | 62 | .icon-color:before { 63 | content: "\e787"; 64 | } 65 | 66 | .icon-span:before { 67 | content: "\e788"; 68 | } 69 | 70 | .icon-alert:before { 71 | content: "\e78a"; 72 | } 73 | 74 | .icon-row:before { 75 | content: "\e78b"; 76 | } 77 | 78 | .icon-divider:before { 79 | content: "\e78d"; 80 | } 81 | 82 | .icon-select:before { 83 | content: "\e78e"; 84 | } 85 | 86 | .icon-transfer:before { 87 | content: "\e78f"; 88 | } 89 | 90 | .icon-editor:before { 91 | content: "\e790"; 92 | } 93 | 94 | .icon-slider:before { 95 | content: "\e791"; 96 | } 97 | 98 | .icon-tree:before { 99 | content: "\e792"; 100 | } 101 | 102 | .icon-date:before { 103 | content: "\e793"; 104 | } 105 | 106 | .icon-time:before { 107 | content: "\e794"; 108 | } 109 | 110 | .icon-delete:before { 111 | content: "\e770"; 112 | } 113 | 114 | .icon-copy:before { 115 | content: "\e771"; 116 | } 117 | 118 | .icon-import:before { 119 | content: "\e773"; 120 | } 121 | 122 | .icon-add:before { 123 | content: "\e774"; 124 | } 125 | 126 | .icon-preview:before { 127 | content: "\e776"; 128 | } 129 | 130 | .icon-move:before { 131 | content: "\e777"; 132 | } 133 | 134 | -------------------------------------------------------------------------------- /src/utils/form.js: -------------------------------------------------------------------------------- 1 | import formCreate from "@form-create/naive-ui"; 2 | 3 | const viewForm = formCreate; 4 | 5 | const designerForm = formCreate.factory(); 6 | 7 | export default viewForm 8 | 9 | export {designerForm} -------------------------------------------------------------------------------- /src/utils/index.js: -------------------------------------------------------------------------------- 1 | import is, {hasProperty} from '@form-create/utils/lib/type'; 2 | import {parseFn} from '@form-create/utils/lib/json'; 3 | import toCase from '@form-create/utils/lib/tocase'; 4 | import {computed, isRef, unref, ref} from 'vue'; 5 | import ZhCn from '../locale/zh-cn'; 6 | 7 | export function makeRequiredRule() { 8 | return { 9 | type: 'Required', field: 'formCreate$required', title: '是否必填' 10 | }; 11 | } 12 | 13 | export function makeOptionsRule(t, to, flag) { 14 | const options = [ 15 | {'label': t('props.optionsType.json'), 'value': 0}, 16 | {'label': t('props.optionsType.fetch'), 'value': 1}, 17 | ]; 18 | 19 | const control = [ 20 | { 21 | value: 0, 22 | rule: [ 23 | { 24 | type: 'Struct', 25 | field: 'formCreate' + upper(to).replace('.', '>'), 26 | props: {defaultValue: []} 27 | }, 28 | ], 29 | }, 30 | { 31 | value: 1, 32 | rule: [ 33 | { 34 | type: 'Fetch', 35 | field: 'formCreateEffect>fetch', 36 | props: { 37 | to 38 | } 39 | } 40 | ] 41 | } 42 | ]; 43 | 44 | if (flag !== false) { 45 | options.splice(0, 0, {'label': t('props.optionsType.struct'), 'value': 2}); 46 | control.push({ 47 | value: 2, 48 | rule: [ 49 | { 50 | type: 'TableOptions', 51 | field: 'formCreate' + upper(to).replace('.', '>'), 52 | props: {defaultValue: []} 53 | }, 54 | ], 55 | }); 56 | } 57 | 58 | return { 59 | type: 'radio', 60 | title: t('props.options'), 61 | field: '_optionType', 62 | value: flag !== false ? 2 : 0, 63 | options, 64 | props: { 65 | type: 'button', 66 | }, 67 | control 68 | }; 69 | } 70 | 71 | export function upper(str) { 72 | return str.replace(str[0], str[0].toLocaleUpperCase()); 73 | } 74 | 75 | 76 | export const toJSON = function (val) { 77 | const type = /object ([a-zA-Z]*)/.exec(Object.prototype.toString.call(val)); 78 | if (type && _toJSON[type[1].toLowerCase()]) { 79 | return _toJSON[type[1].toLowerCase()](val); 80 | } else { 81 | return val; 82 | } 83 | }; 84 | 85 | const _toJSON = { 86 | object: function (val) { 87 | var json = []; 88 | for (var i in val) { 89 | if (!hasProperty(val, i)) continue; 90 | json.push( 91 | toJSON(i) + ': ' + 92 | ((val[i] != null) ? toJSON(val[i]) : 'null') 93 | ); 94 | } 95 | return '{\n ' + json.join(',\n ') + '\n}'; 96 | }, 97 | function: function (val) { 98 | var exec = (/^ *([\w]+) *\(/).exec(val); 99 | if (exec && exec[1] !== 'function') { 100 | return 'function ' + val; 101 | } 102 | return val; 103 | }, 104 | array: function (val) { 105 | for (var i = 0, json = []; i < val.length; i++) 106 | json[i] = (val[i] != null) ? toJSON(val[i]) : 'null'; 107 | return '[' + json.join(', ') + ']'; 108 | }, 109 | string: function (val) { 110 | var tmp = val.split(''); 111 | for (var i = 0; i < tmp.length; i++) { 112 | var c = tmp[i]; 113 | (c >= ' ') ? 114 | (c === '\\') ? (tmp[i] = '\\\\') : 115 | (c === '"') ? (tmp[i] = '\\"') : 0 : 116 | (tmp[i] = 117 | (c === '\n') ? '\\n' : 118 | (c === '\r') ? '\\r' : 119 | (c === '\t') ? '\\t' : 120 | (c === '\b') ? '\\b' : 121 | (c === '\f') ? '\\f' : 122 | (c = c.charCodeAt(), ('\\u00' + ((c > 15) ? 1 : 0) + (c % 16))) 123 | ); 124 | } 125 | return '"' + tmp.join('') + '"'; 126 | } 127 | }; 128 | 129 | export const deepParseFn = function (target) { 130 | for (let key in target) { 131 | if (Object.prototype.hasOwnProperty.call(target, key)) { 132 | let data = target[key]; 133 | if (Array.isArray(data) || is.Object(data)) { 134 | deepParseFn(data); 135 | } 136 | if (is.String(data)) { 137 | target[key] = parseFn(data); 138 | } 139 | } 140 | } 141 | return target; 142 | }; 143 | 144 | 145 | function get(object, path, defaultValue) { 146 | path = (path || '').split('.'); 147 | 148 | let index = 0, 149 | length = path.length; 150 | 151 | while (object != null && index < length) { 152 | object = object[path[index++]]; 153 | } 154 | return (index && index === length) ? (object !== undefined ? object : defaultValue) : defaultValue; 155 | } 156 | 157 | export const buildTranslator = (locale) => (path, option) => translate(path, option, unref(locale)); 158 | 159 | export const translate = (path, option, locale) => 160 | get(locale, path, '').replace( 161 | /\{(\w+)\}/g, 162 | (_, key) => `${option?.[key] ?? `{${key}}`}` 163 | ) 164 | 165 | export const buildLocaleContext = (locale) => { 166 | const lang = computed(() => unref(locale).name) 167 | const name = computed(() => upper(toCase(lang.value || ''))) 168 | const localeRef = isRef(locale) ? locale : ref(locale) 169 | return { 170 | lang, 171 | name, 172 | locale: localeRef, 173 | t: buildTranslator(locale), 174 | } 175 | } 176 | 177 | export const useLocale = (locale) => { 178 | return buildLocaleContext(computed(() => locale.value || ZhCn)) 179 | } 180 | 181 | 182 | export const localeProps = (t, prefix, rules) => { 183 | return rules.map(rule => { 184 | if (rule.field === 'formCreate$required') { 185 | rule.title = t('props.required') || rule.title; 186 | } else if (rule.field && rule.field !== '_optionType') { 187 | rule.title = t('components.' + prefix + '.' + rule.field) || rule.title; 188 | } 189 | return rule; 190 | }) 191 | } 192 | -------------------------------------------------------------------------------- /src/utils/tabname.js: -------------------------------------------------------------------------------- 1 | let id = 0; 2 | 3 | function resetId() { 4 | id = 0; 5 | } 6 | 7 | 8 | export default function tabname() { 9 | if ([0, 1].indexOf(id++) != -1) return 0; 10 | return id - 2; 11 | } 12 | 13 | export { resetId } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "compilerOptions": { 4 | "target": "ESNext", 5 | "sourceMap": true, 6 | "allowUnreachableCode": true, 7 | "allowSyntheticDefaultImports": true, 8 | "allowJs": true, 9 | "experimentalDecorators": true, 10 | "moduleResolution": "node", 11 | "noImplicitThis": true, 12 | "noImplicitAny": false, 13 | "importHelpers": true, 14 | "jsx": "preserve" 15 | }, 16 | "include": [ 17 | "*.vue", 18 | "*", 19 | "types/typing.d.ts" 20 | ] 21 | } -------------------------------------------------------------------------------- /types/index.d.ts: -------------------------------------------------------------------------------- 1 | import {Rule} from "@form-create/naive-ui"; 2 | import FormCreate from "@form-create/naive-ui"; 3 | import {App, Component} from "@vue/runtime-core"; 4 | 5 | export interface MenuItem { 6 | label: string, 7 | name: string, 8 | icon: string; 9 | } 10 | 11 | export interface Menu { 12 | title: string; 13 | name: string; 14 | list: MenuItem[] 15 | } 16 | 17 | export interface Config { 18 | showBaseForm: Boolean; 19 | showConfig: Boolean; 20 | showFormConfig: Boolean; 21 | } 22 | 23 | export interface MenuList extends Array { 24 | 25 | } 26 | 27 | export interface DragRule { 28 | name: string; 29 | 30 | rule(): Rule; 31 | 32 | props(): Rule[]; 33 | 34 | watch?: { 35 | [key: string]: (arg: { value: any, rule: object, api: object, field: string }) => void; 36 | }; 37 | children?: string; 38 | childrenLen?: number; 39 | inside?: true; 40 | drag?: true | String; 41 | dragBtn?: false; 42 | mask?: false; 43 | } 44 | 45 | declare const FcDesigner: { 46 | install: (app: App, ...options: any[]) => any; 47 | } & Component; 48 | 49 | export default FcDesigner; 50 | 51 | export const formCreate: typeof FormCreate; 52 | export const designerForm: typeof FormCreate; 53 | -------------------------------------------------------------------------------- /vite.config.build.js: -------------------------------------------------------------------------------- 1 | import {defineConfig} from 'vite' 2 | import vue from '@vitejs/plugin-vue' 3 | import vueJSX from '@vitejs/plugin-vue-jsx' 4 | import banner from 'vite-plugin-banner' 5 | import cssnano from 'cssnano' 6 | import visualizer from 'rollup-plugin-visualizer'; 7 | import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js' 8 | import {author, license, name, version} from './package.json' 9 | 10 | const extnedsPlugins = []; 11 | 12 | function getBanner(banner, pkg) { 13 | if (!banner || typeof banner === 'string') { 14 | return banner || ''; 15 | } 16 | 17 | banner = {...pkg, ...(banner === true ? {} : banner)}; 18 | 19 | const author =banner.author 20 | 21 | const license = banner.license || ''; 22 | return ( 23 | '/*!\n' + 24 | ' * form-create 可视化表单设计器\n' + 25 | ` * ${banner.name} v${banner.version}\n` + 26 | ` * (c) ${author || ''}\n` + 27 | (license && ` * Released under the ${license} License.\n`) + 28 | ' */' 29 | ); 30 | } 31 | 32 | const __banner__ = { 33 | author: `2021-${new Date().getFullYear()} ${author}\n * Github https://github.com/xaboy/form-create-designer`, 34 | license, 35 | name, 36 | version 37 | } 38 | 39 | // 打包生产环境才引入的插件 40 | if (process.env.NODE_ENV === 'production') { 41 | // 打包依赖展示 42 | extnedsPlugins.push( 43 | visualizer({ 44 | open: true, 45 | gzipSize: true, 46 | brotliSize: true, 47 | }) 48 | ); 49 | } 50 | 51 | // https://vitejs.dev/config/ 52 | export default defineConfig({ 53 | build: { 54 | lib: { 55 | entry: 'src/index.js', 56 | name: 'FcDesigner', 57 | fileName: format => `index.${format}.js`, 58 | }, 59 | rollupOptions: { 60 | output: { 61 | exports: 'named', 62 | globals: { 63 | vue: 'Vue' 64 | } 65 | }, 66 | external: [ 67 | 'vue', 68 | 'naive-ui', 69 | '@form-create/naive-ui' 70 | ], 71 | 72 | }, 73 | brotliSize: true 74 | }, 75 | css: { 76 | postcss: { 77 | plugins: [ 78 | cssnano({ 79 | preset: 'advanced' 80 | }) 81 | ] 82 | } 83 | }, 84 | plugins: [vue(), vueJSX(), banner(getBanner(__banner__)),cssInjectedByJsPlugin(), ...extnedsPlugins] 85 | }) 86 | -------------------------------------------------------------------------------- /vite.config.locale.js: -------------------------------------------------------------------------------- 1 | import {defineConfig} from 'vite' 2 | import banner from 'vite-plugin-banner' 3 | import {author, license, name, version} from './package.json' 4 | 5 | function getBanner(banner, pkg) { 6 | if (!banner || typeof banner === 'string') { 7 | return banner || ''; 8 | } 9 | 10 | banner = {...pkg, ...(banner === true ? {} : banner)}; 11 | 12 | const author = banner.author 13 | 14 | const license = banner.license || ''; 15 | return ( 16 | '/*!\n' + 17 | ' * form-create 可视化表单设计器\n' + 18 | ` * ${banner.name} v${banner.version}\n` + 19 | ` * (c) ${author || ''}\n` + 20 | (license && ` * Released under the ${license} License.\n`) + 21 | ' */' 22 | ); 23 | } 24 | 25 | function toCase(str) { 26 | return str.replace(/(-[a-z])/g, function (v) { 27 | return v.replace('-', '').toLocaleUpperCase(); 28 | }); 29 | } 30 | 31 | function upper(str) { 32 | return str.replace(str[0], str[0].toLocaleUpperCase()); 33 | } 34 | 35 | const __banner__ = { 36 | author: `2021-${new Date().getFullYear()} ${author}\n * Github https://github.com/xaboy/form-create-designer`, 37 | license, 38 | name, 39 | version 40 | } 41 | 42 | // https://vitejs.dev/config/ 43 | export default defineConfig((env) => { 44 | const name = env.mode || 'en'; 45 | return { 46 | build: { 47 | outDir: 'locale', 48 | lib: { 49 | entry: `src/locale/${name}.js`, 50 | name: 'FcDesigner' + upper(toCase(name)), 51 | fileName: name, 52 | }, 53 | emptyOutDir: false, 54 | }, 55 | 56 | plugins: [banner(getBanner(__banner__))] 57 | }; 58 | }) 59 | -------------------------------------------------------------------------------- /vite.config.preview.js: -------------------------------------------------------------------------------- 1 | import {defineConfig} from 'vite' 2 | import vue from '@vitejs/plugin-vue' 3 | import vueJSX from '@vitejs/plugin-vue-jsx' 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | build: { 7 | cssCodeSplit: true, 8 | rollupOptions: { 9 | input: 'examples/index.html', 10 | output: { 11 | manualChunks: { 12 | vue: ['vue'], 13 | 'naive-ui': ['naive-ui'], 14 | }, 15 | globals: { 16 | vue: 'Vue', 17 | } 18 | }, 19 | }, 20 | chunkSizeWarningLimit: 2000, 21 | }, 22 | plugins: [vue(), vueJSX()] 23 | }) 24 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author : djkloop 3 | * @Date : 2020-08-15 21:16:03 4 | * @LastEditors : djkloop 5 | * @LastEditTime : 2021-09-21 17:18:46 6 | * @Description : 头部注释 7 | * @FilePath : /form-create2/packages/element-ui/vue.config.js 8 | */ 9 | module.exports = { 10 | pages: { 11 | app: { 12 | entry: 'examples/main.js', 13 | template: 'examples/index.html', 14 | filename: 'index.html' 15 | } 16 | }, 17 | configureWebpack: { 18 | module: { 19 | rules: [ 20 | { 21 | test: /\.mjs$/, 22 | include: /node_modules/, 23 | type: 'javascript/auto' 24 | }, 25 | ] 26 | } 27 | } 28 | } 29 | --------------------------------------------------------------------------------