├── src ├── components │ ├── naiveui │ │ ├── components │ │ │ ├── design │ │ │ │ ├── DesignForm.js │ │ │ │ └── DesignConfig.vue │ │ │ ├── configs │ │ │ │ ├── RichtextEditor.vue │ │ │ │ ├── Switch.vue │ │ │ │ ├── Time.vue │ │ │ │ ├── Number.vue │ │ │ │ ├── Rate.vue │ │ │ │ ├── Alert.vue │ │ │ │ ├── Input.vue │ │ │ │ ├── Grid.vue │ │ │ │ ├── Divider.vue │ │ │ │ ├── Text.vue │ │ │ │ ├── Date.vue │ │ │ │ ├── Slider.vue │ │ │ │ ├── Transfer.vue │ │ │ │ ├── DynamicTags.vue │ │ │ │ ├── Upload.vue │ │ │ │ ├── Button.vue │ │ │ │ ├── Color.vue │ │ │ │ ├── Radio.vue │ │ │ │ ├── Table.vue │ │ │ │ ├── Checkbox.vue │ │ │ │ ├── Select.vue │ │ │ │ ├── SelectTree.vue │ │ │ │ └── Cascader.vue │ │ │ ├── custom │ │ │ │ ├── RichTextEditor.vue │ │ │ │ └── table │ │ │ │ │ ├── GTableItem.vue │ │ │ │ │ └── GTable.vue │ │ │ ├── ComponentGroup.vue │ │ │ ├── NaiveHeader.vue │ │ │ ├── CodeEditor.vue │ │ │ ├── NaiveFormConfig.vue │ │ │ └── generate │ │ │ │ └── GenerateForm.vue │ │ ├── config │ │ │ └── index.ts │ │ ├── types │ │ │ └── NaiveWidgetTypes.d.ts │ │ ├── styles │ │ │ ├── scrollbar.less │ │ │ ├── table.less │ │ │ └── index.less │ │ ├── utils │ │ │ ├── index.ts │ │ │ └── generateCode.ts │ │ ├── mixins │ │ │ └── eventMixin.js │ │ ├── enums │ │ │ └── index.ts │ │ └── FormDesign.vue │ └── SvgIcon.vue ├── index.d.ts ├── assets │ └── logo.png ├── icons │ └── svg │ │ ├── divider.svg │ │ ├── alert.svg │ │ ├── table.svg │ │ ├── selectTree.svg │ │ ├── tree.svg │ │ ├── dynamicTags.svg │ │ ├── question.svg │ │ ├── text.svg │ │ ├── input.svg │ │ ├── textarea.svg │ │ ├── insert.svg │ │ ├── select.svg │ │ ├── switch.svg │ │ ├── time.svg │ │ ├── radio.svg │ │ ├── button.svg │ │ ├── transfer.svg │ │ ├── preview.svg │ │ ├── copy.svg │ │ ├── richtext-editor.svg │ │ ├── slider.svg │ │ ├── cascader.svg │ │ ├── checkbox.svg │ │ ├── dynamicTable.svg │ │ ├── upload.svg │ │ ├── item.svg │ │ ├── password.svg │ │ ├── clearable.svg │ │ ├── generate-code.svg │ │ ├── grid.svg │ │ ├── date.svg │ │ ├── move.svg │ │ ├── delete.svg │ │ ├── img-upload.svg │ │ ├── rate.svg │ │ ├── number.svg │ │ ├── color.svg │ │ └── generate-json.svg ├── main.ts ├── env.d.ts └── App.vue ├── public └── favicon.ico ├── tsconfig.node.json ├── .gitignore ├── index.html ├── tsconfig.json ├── vite.config.ts ├── package.json ├── LICENSE └── README.md /src/components/naiveui/components/design/DesignForm.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/index.d.ts: -------------------------------------------------------------------------------- 1 | declare interface Window { 2 | $message: any; 3 | } 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LvHuaiSheng/naiveui-form-generate/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LvHuaiSheng/naiveui-form-generate/HEAD/src/assets/logo.png -------------------------------------------------------------------------------- /src/components/naiveui/config/index.ts: -------------------------------------------------------------------------------- 1 | import * as naiveui from './naiveui' 2 | 3 | export { naiveui } 4 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "esnext", 5 | "moduleResolution": "node" 6 | }, 7 | "include": ["vite.config.ts"] 8 | } 9 | -------------------------------------------------------------------------------- /src/components/naiveui/types/NaiveWidgetTypes.d.ts: -------------------------------------------------------------------------------- 1 | export type RowData= { 2 | parentKey: string | null // 父级key 3 | key: string // key 4 | label: any 5 | value: any, 6 | children?:Array | [] //下级数据 7 | } 8 | 9 | -------------------------------------------------------------------------------- /src/icons/svg/divider.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | import naive from 'naive-ui'; 4 | import 'virtual:svg-icons-register' // 引入SVG注册脚本 5 | import './components/naiveui/styles/index.less' 6 | createApp(App) 7 | .use(naive) 8 | .mount('#app') 9 | 10 | -------------------------------------------------------------------------------- /src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module '*.vue' { 4 | import type { DefineComponent } from 'vue' 5 | // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types 6 | const component: DefineComponent<{}, {}, any> 7 | export default component 8 | } 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /src/icons/svg/alert.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/components/naiveui/styles/scrollbar.less: -------------------------------------------------------------------------------- 1 | ::-webkit-scrollbar { 2 | width: 5px; 3 | height: 5px; 4 | } 5 | ::-webkit-scrollbar-thumb { 6 | border-radius: 1em; 7 | background-color: rgba(50, 50, 50, 0.3); 8 | } 9 | ::-webkit-scrollbar-track { 10 | border-radius: 1em; 11 | background-color: rgba(50, 50, 50, 0.1); 12 | } 13 | .n-layout-sider-scroll-container,.widget-form-container{ 14 | scrollbar-width: thin; 15 | } 16 | -------------------------------------------------------------------------------- /src/components/naiveui/utils/index.ts: -------------------------------------------------------------------------------- 1 | // 验证是否外部地址 2 | export function isExternal(path: string) { 3 | return /^(https?:|mailto:|tel:)/.test(path) 4 | } 5 | 6 | // 复制文本 7 | export function copy(text: string) { 8 | const input = document.createElement('textarea') 9 | input.value = text 10 | document.body.appendChild(input) 11 | input.select() 12 | document.execCommand('copy') 13 | document.body.removeChild(input) 14 | } 15 | -------------------------------------------------------------------------------- /src/icons/svg/table.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/icons/svg/selectTree.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/icons/svg/tree.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/icons/svg/dynamicTags.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/icons/svg/question.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "useDefineForClassFields": true, 5 | "module": "esnext", 6 | "moduleResolution": "node", 7 | "strict": false, 8 | "jsx": "preserve", 9 | "sourceMap": true, 10 | "resolveJsonModule": true, 11 | "isolatedModules": true, 12 | "esModuleInterop": true, 13 | "lib": ["esnext", "dom"], 14 | "skipLibCheck": true 15 | }, 16 | "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], 17 | "references": [{ "path": "./tsconfig.node.json" }] 18 | } 19 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 18 | 19 | 24 | -------------------------------------------------------------------------------- /src/icons/svg/text.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/input.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/naiveui/styles/table.less: -------------------------------------------------------------------------------- 1 | .table-theme1{ 2 | border-spacing: 0; /* 控制单元格之间的距离 */ 3 | border-collapse: collapse; /* 控制是否合并边框:separate:缺省值 边框不合并;collapse:边框合并 */ 4 | border: 1px solid #000; 5 | tr,td,th { 6 | border: 1px solid; 7 | border-color: #000 !important; 8 | border-collapse: collapse; /* 控制是否合并边框 */ 9 | border-spacing: 0; 10 | height: auto !important; 11 | //position: relative; 12 | //left: 0; 13 | //right: 0; 14 | //top: 0; 15 | //bottom: 0; 16 | .widget-col-list{ 17 | //display: inline-block; 18 | display: inline-flex !important; 19 | width: 100%; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/icons/svg/textarea.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/insert.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/select.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/switch.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/time.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/radio.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/button.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import {defineConfig} from 'vite' 2 | import vue from '@vitejs/plugin-vue' 3 | import {resolve} from 'path' 4 | import {createSvgIconsPlugin} from 'vite-plugin-svg-icons' 5 | // https://vitejs.dev/config/ 6 | function pathResolve(dir: string) { 7 | return resolve(process.cwd(), '.', dir); 8 | } 9 | export default defineConfig({ 10 | 11 | plugins: [ 12 | createSvgIconsPlugin({ 13 | // 指定需要缓存的图标文件夹 14 | iconDirs: [resolve(process.cwd(), 'src/icons/svg')], 15 | // 指定symbolId格式 16 | symbolId: 'icon-[name]', 17 | }), 18 | vue()], 19 | /** 20 | * 在生产中服务时的基本公共路径。 21 | * @default '/' 22 | */ 23 | base: '/naiveui-form-generate', 24 | }, 25 | ) 26 | -------------------------------------------------------------------------------- /src/icons/svg/transfer.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/icons/svg/preview.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "naiveui-form-generate", 3 | "private": true, 4 | "version": "0.0.0", 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "vite build", 8 | "preview": "vite preview" 9 | }, 10 | "dependencies": { 11 | "ace-builds": "^1.4.12", 12 | "lodash": "^4.17.21", 13 | "naive-ui": "^2.30.6", 14 | "uuid": "^8.3.2", 15 | "vue": "^3.2.25", 16 | "vue3-i18n-plugin": "^1.0.9", 17 | "vuedraggable": "^4.0.1", 18 | "vuex": "^4.0.2", 19 | "wangeditor": "^4.7.15" 20 | }, 21 | "devDependencies": { 22 | "@types/lodash": "^4.14.182", 23 | "@types/uuid": "^8.3.4", 24 | "@vitejs/plugin-vue": "^2.3.3", 25 | "@vue/compiler-sfc": "^3.2.37", 26 | "fast-glob": "^3.2.11", 27 | "less": "^4.1.2", 28 | "less-loader": "^9.1.0", 29 | "typescript": "^4.5.4", 30 | "vite": "^2.9.9", 31 | "vite-plugin-svg-icons": "^2.0.1", 32 | "vue-tsc": "^0.34.7" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/icons/svg/copy.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/richtext-editor.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/naiveui/mixins/eventMixin.js: -------------------------------------------------------------------------------- 1 | export default { 2 | methods:{ 3 | /** 4 | * 改变事件 5 | * @param e 入参 6 | */ 7 | handleChange(e){ 8 | console.log('触发change事件:',e) 9 | let customFn = new Function('form','view','e', this.element.options.change) 10 | customFn.call(this,this.model,this.widgetForm, e) 11 | }, 12 | /** 13 | * 点击事件 14 | * @param e 入参 15 | */ 16 | handleClick(e){ 17 | console.log('触发click事件:',e) 18 | }, 19 | /** 20 | * 带回调的点击事件 - 示例 21 | * @param e 入参 22 | */ 23 | /*handleClickCallback(e){ 24 | let customFn = (rule, value, callback) => { 25 | let tmpFunc = new Function('form','e', this.selectWidget.options.change) 26 | return tmpFunc.call(this,this.widgetForm, e) 27 | } 28 | customFn.call(this,this.widgetForm, e) 29 | }*/ 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/icons/svg/slider.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/naiveui/enums/index.ts: -------------------------------------------------------------------------------- 1 | export enum CodeType { 2 | Form = 'form', 3 | Model = 'model' 4 | } 5 | 6 | export enum PlatformType { 7 | NaiveUi, 8 | } 9 | 10 | export enum ComponentType { 11 | Input = 'input', 12 | Number = 'number', 13 | Radio = 'radio', 14 | Checkbox = 'checkbox', 15 | Time = 'time', 16 | Date = 'date', 17 | Rate = 'rate', 18 | Select = 'select', 19 | Switch = 'switch', 20 | Slider = 'slider', 21 | Color = 'color', 22 | // 高级组件 23 | Upload = 'upload', 24 | RichtextEditor = 'richtext-editor', 25 | Cascader = 'cascader', 26 | Tree = 'tree', 27 | Table = 'table', 28 | Grid = 'grid', 29 | DynamicTable = 'dynamicTable', 30 | SelectTree = 'selectTree', 31 | Transfer = 'transfer', 32 | Alert = 'alert', 33 | Text = 'text', 34 | Divider = 'divider', 35 | DynamicTags = 'dynamicTags', 36 | Button = 'button', 37 | } 38 | 39 | export function checkComponent(test: any): test is ComponentType { 40 | return (Object.values(ComponentType).indexOf(test) !== -1); 41 | } 42 | -------------------------------------------------------------------------------- /src/icons/svg/cascader.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/checkbox.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/dynamicTable.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/icons/svg/upload.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/item.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/password.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 LvHuaiSheng 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 | -------------------------------------------------------------------------------- /src/icons/svg/clearable.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/generate-code.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/grid.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/date.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/naiveui/components/configs/RichtextEditor.vue: -------------------------------------------------------------------------------- 1 | 24 | 49 | 50 | 51 | 54 | -------------------------------------------------------------------------------- /src/icons/svg/move.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/naiveui/components/custom/RichTextEditor.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 63 | -------------------------------------------------------------------------------- /src/components/naiveui/components/ComponentGroup.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 56 | -------------------------------------------------------------------------------- /src/components/naiveui/components/configs/Switch.vue: -------------------------------------------------------------------------------- 1 | 31 | 56 | 57 | 58 | 61 | -------------------------------------------------------------------------------- /src/icons/svg/delete.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/img-upload.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/svg/rate.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/SvgIcon.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 53 | 54 | 68 | -------------------------------------------------------------------------------- /src/components/naiveui/components/configs/Time.vue: -------------------------------------------------------------------------------- 1 | 39 | 64 | 65 | 66 | 69 | -------------------------------------------------------------------------------- /src/components/naiveui/components/configs/Number.vue: -------------------------------------------------------------------------------- 1 | 40 | 65 | 66 | 67 | 70 | -------------------------------------------------------------------------------- /src/components/naiveui/components/configs/Rate.vue: -------------------------------------------------------------------------------- 1 | 50 | 75 | 76 | 77 | 80 | -------------------------------------------------------------------------------- /src/components/naiveui/components/NaiveHeader.vue: -------------------------------------------------------------------------------- 1 | 63 | 64 | 76 | -------------------------------------------------------------------------------- /src/icons/svg/number.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/naiveui/components/CodeEditor.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 81 | -------------------------------------------------------------------------------- /src/components/naiveui/components/configs/Alert.vue: -------------------------------------------------------------------------------- 1 | 46 | 74 | 75 | 76 | 79 | -------------------------------------------------------------------------------- /src/components/naiveui/components/configs/Input.vue: -------------------------------------------------------------------------------- 1 | 56 | 81 | 82 | 83 | 86 | -------------------------------------------------------------------------------- /src/components/naiveui/components/configs/Grid.vue: -------------------------------------------------------------------------------- 1 | 38 | 80 | 81 | 82 | 85 | -------------------------------------------------------------------------------- /src/components/naiveui/components/configs/Divider.vue: -------------------------------------------------------------------------------- 1 | 29 | 78 | 79 | 80 | 83 | -------------------------------------------------------------------------------- /src/components/naiveui/components/configs/Text.vue: -------------------------------------------------------------------------------- 1 | 25 | 74 | 75 | 76 | 79 | -------------------------------------------------------------------------------- /src/components/naiveui/components/configs/Date.vue: -------------------------------------------------------------------------------- 1 | 41 | 86 | 87 | 88 | 91 | -------------------------------------------------------------------------------- /src/icons/svg/color.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/naiveui/utils/generateCode.ts: -------------------------------------------------------------------------------- 1 | import {CodeType, PlatformType} from '../enums' 2 | 3 | export default function ( 4 | widgetForm: any, 5 | codeType: CodeType, 6 | platformType: PlatformType 7 | ) { 8 | if (codeType === CodeType.Form) { 9 | return ` 13 | 14 | 41 | ` 42 | } 43 | if (codeType === CodeType.Model) { 44 | return ` 53 |
54 | 55 |
56 | 60 |
61 | 62 | 94 | ` 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # naiveui-form-generate 2 | 3 |

基于naiveui、typescript的表单生成器,支持复杂表格Tree等常用组件

4 |

5 | 6 | 7 | 8 | 9 |

10 | 11 | 12 | ### 简介 13 | 14 | [NaiveUi Form Generate](https://gitee.com/sourcenet/naiveui-form-generate),一个基于 Vue3.0、Vite、Naive UI 表单生成器。 15 | 16 | ### 预览 17 | 18 | [预览地址](http://nge.sourcenet.cc/naiveui-form-generate) 19 | 20 | ### 特别提示 21 | 推荐从Gitee仓库拉取代码,[NaiveUi Form Generate](https://gitee.com/sourcenet/naiveui-form-generate),GitHub提交老是被墙,代码也许不是最新的 22 | 23 | ### 功能/计划 24 | 🕙筹划 🔲筹备 🚧进行中 ✅完成 25 | 26 | > 支持组件常用事件(组件可在线设计的属性都可在事件内动态修改,如:动态显隐、必填、校验规则、样式等等) 27 | - ✅ click事件 28 | - ✅ change事件 29 | - 🔲 focus事件 30 | - 🔲 hover事件 31 | - 🔲 blur事件 32 | - 🚧 select事件 33 | - 🔲 update事件 34 | - 🔲 form提交前事件 35 | - 🔲 form保存后事件 36 | 37 | > 基础组件 38 | - ✅ 单行/多行/密码输入组件 39 | - ✅ 数字组件 40 | - ✅ 单选 41 | - ✅ 多选 42 | - ✅ 时间选择 43 | - ✅ 日期选择(年份、月份、季度等) 44 | - ✅ 评分 45 | - ✅ 开关 46 | - ✅ 滑块(横向、竖向) 47 | - ✅ 颜色选择器 48 | 49 | > 高级组件 50 | - ✅ 树形选择 51 | - ✅ 文件上传 52 | - ✅ 穿梭框 53 | - ✅ 级联选择 54 | - ✅ 树形组件 55 | - ✅ 富文本编辑器 56 | - ✅ 动态标签 57 | - 🕙 动态表格(主要用作子表的使用,支持弹窗/抽屉/行内编辑等多种样式) 58 | 59 | > 布局组件 60 | - ✅ naiveui的新版栅格布局 61 | - 🚧 静态表格(可启用原生样式,实现线上、线下合同表单的一比一样式) 62 | - 🕙 标签页 63 | 64 | > 其它组件 65 | - ✅ 普通文本 66 | - ✅ Alert组件 67 | - ✅ Divider分割线 68 | - ✅ 按钮 69 | 70 | > 其它优化 71 | - 🚀 单个组件化封装(typescript) 72 | - 🚀 细节优化 73 | - 更多...... 74 | 75 | ### 文档 76 | - 待编写 77 | 78 | ### 构建 79 | 80 | ```shell 81 | # 克隆项目 82 | #github 83 | git clone https://github.com/LvHuaiSheng/naiveui-form-generate.git 84 | 85 | #gitee 86 | git clone https://gitee.com/sourcenet/naiveui-form-generate.git 87 | 88 | # 进入项目目录 89 | cd naiveui-form-generate 90 | 91 | # 安装依赖(建议使用pnpm: https://pnpm.io/zh/installation) 92 | pnpm i # 或者 npm i 93 | 94 | # 启动 95 | npm run dev 96 | ``` 97 | 98 | ### 发布 99 | 100 | ```shell 101 | # 构建测试环境 102 | npm run build:test 103 | 104 | # 构建github pages环境 105 | npm run build:github 106 | 107 | # 构建生产环境 108 | npm run build 109 | ``` 110 | 111 | ### 其他指令 112 | 113 | 114 | ### 规范 115 | 116 | #### git commit 规范 117 | 118 | - `feat` 增加新功能 119 | - `fix` 修复问题/BUG 120 | - `style` 代码风格相关无影响运行结果的 121 | - `perf` 优化/性能提升 122 | - `refactor` 重构 123 | - `revert` 撤销修改 124 | - `test` 测试相关 125 | - `docs` 文档/注释 126 | - `chore` 依赖更新/脚手架配置修改等 127 | - `workflow` 工作流改进 128 | - `ci` 持续集成 129 | - `types` 类型定义文件更改 130 | - `wip` 开发中 131 | - `mod` 不确定分类的修改 132 | - `release` 发布 133 | 134 | 135 | -------------------------------------------------------------------------------- /src/components/naiveui/components/configs/Slider.vue: -------------------------------------------------------------------------------- 1 | 63 | 95 | 96 | 97 | 100 | -------------------------------------------------------------------------------- /src/components/naiveui/components/configs/Transfer.vue: -------------------------------------------------------------------------------- 1 | 71 | 106 | 107 | 112 | -------------------------------------------------------------------------------- /src/components/naiveui/components/configs/DynamicTags.vue: -------------------------------------------------------------------------------- 1 | 78 | 112 | 113 | 114 | 117 | -------------------------------------------------------------------------------- /src/components/naiveui/components/configs/Upload.vue: -------------------------------------------------------------------------------- 1 | 73 | 98 | 99 | 100 | 103 | -------------------------------------------------------------------------------- /src/components/naiveui/components/configs/Button.vue: -------------------------------------------------------------------------------- 1 | 89 | 123 | 124 | 125 | 128 | -------------------------------------------------------------------------------- /src/icons/svg/generate-json.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/naiveui/components/configs/Color.vue: -------------------------------------------------------------------------------- 1 | 83 | 129 | 130 | 131 | 134 | -------------------------------------------------------------------------------- /src/components/naiveui/components/configs/Radio.vue: -------------------------------------------------------------------------------- 1 | 73 | 122 | 123 | 124 | 129 | -------------------------------------------------------------------------------- /src/components/naiveui/components/configs/Table.vue: -------------------------------------------------------------------------------- 1 | 68 | 123 | 124 | 125 | 134 | -------------------------------------------------------------------------------- /src/components/naiveui/components/configs/Checkbox.vue: -------------------------------------------------------------------------------- 1 | 73 | 122 | 123 | 124 | 129 | -------------------------------------------------------------------------------- /src/components/naiveui/components/NaiveFormConfig.vue: -------------------------------------------------------------------------------- 1 | 77 | 78 | 119 | -------------------------------------------------------------------------------- /src/components/naiveui/components/configs/Select.vue: -------------------------------------------------------------------------------- 1 | 108 | 176 | 177 | 178 | 183 | -------------------------------------------------------------------------------- /src/components/naiveui/components/custom/table/GTableItem.vue: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 183 | 184 | 189 | -------------------------------------------------------------------------------- /src/components/naiveui/components/generate/GenerateForm.vue: -------------------------------------------------------------------------------- 1 | 81 | 82 | 207 | -------------------------------------------------------------------------------- /src/components/naiveui/components/design/DesignConfig.vue: -------------------------------------------------------------------------------- 1 | 105 | 106 | 270 | -------------------------------------------------------------------------------- /src/components/naiveui/FormDesign.vue: -------------------------------------------------------------------------------- 1 | 162 | 163 | 365 | -------------------------------------------------------------------------------- /src/components/naiveui/styles/index.less: -------------------------------------------------------------------------------- 1 | @import 'src/components/naiveui/styles/scrollbar.less'; 2 | @import 'src/components/naiveui/styles/table.less'; 3 | @primary-color: #18a058; 4 | @primary-background-color: #eafaef; 5 | // Color variables (appears count calculates by raw css) 6 | @color0: #ffffff; // Appears 15 times 7 | @color1: #18a058; // Appears 9 times 8 | @color2: #f0a020; // Appears 7 times 9 | @color3: #e4e7ed; // Appears 3 times 10 | @color4: #f4f6fc; // Appears 3 times 11 | @color5: #e1e1e1; // Appears 3 times 12 | @color6: #e0e0e0; // Appears 2 times 13 | @color7: #fafafa; // Appears 2 times 14 | @color8: #cccccc; // Appears 2 times 15 | 16 | 17 | // Height variables (appears count calculates by raw css) 18 | @height1: calc(100% - 45px); // Appears 2 times 19 | @height2: 100%; // Appears 9 times 20 | @height3: 45px; // Appears 3 times 21 | @height4: 28px; // Appears 4 times 22 | @height8: 3px; // Appears 3 times 23 | 24 | html { 25 | height: @height2; 26 | margin: 0; 27 | } 28 | body { 29 | height: @height2; 30 | margin: 0; 31 | /* 文字不可选中 */ 32 | -webkit-user-select:none; 33 | -moz-user-select:none; 34 | -ms-user-select:none; 35 | user-select:none; 36 | } 37 | #app { 38 | -moz-osx-font-smoothing: grayscale; 39 | -webkit-font-smoothing: antialiased; 40 | color: #2c3e50; 41 | font-family: 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif; 42 | height: @height2; 43 | min-height: @height2; 44 | } 45 | .fc-style { 46 | height: @height2; 47 | * { 48 | -moz-box-sizing: border-box; 49 | -webkit-box-sizing: border-box; 50 | box-sizing: border-box; 51 | } 52 | &:after { 53 | -moz-box-sizing: border-box; 54 | -webkit-box-sizing: border-box; 55 | box-sizing: border-box; 56 | } 57 | &:before { 58 | -moz-box-sizing: border-box; 59 | -webkit-box-sizing: border-box; 60 | box-sizing: border-box; 61 | } 62 | .fc-container { 63 | background: @color0; 64 | height: @height2; 65 | .fc-main { 66 | position: relative; 67 | } 68 | } 69 | .center-container { 70 | border-left: 1px solid @color6; 71 | border-right: 1px solid @color6; 72 | .btn-bar { 73 | background-color: @color0; 74 | border-bottom: 2px solid @color3; 75 | font-size: 18px; 76 | height: @height3 !important; 77 | line-height: @height3; 78 | padding: 0 10px; 79 | text-align: right; 80 | .svg-icon { 81 | font-size: 16px; 82 | margin-right: 5px; 83 | } 84 | } 85 | } 86 | .components { 87 | height: @height2; 88 | padding: 8px 0; 89 | width: 100%; 90 | .widget-cate { 91 | font-size: 13px; 92 | padding: 8px 12px; 93 | } 94 | ul { 95 | margin: 0; 96 | overflow: hidden; 97 | padding: 0 10px 10px; 98 | position: relative; 99 | } 100 | .form-edit-widget-label { 101 | border: 1px solid @color4; 102 | display: block; 103 | float: left; 104 | font-size: 12px; 105 | left: 0; 106 | line-height: 26px; 107 | margin: 1%; 108 | overflow: hidden; 109 | position: relative; 110 | text-overflow: ellipsis; 111 | white-space: nowrap; 112 | min-width: 100px; 113 | text-align: center; 114 | &:hover { 115 | border: 1px dashed@primary-color; 116 | } 117 | &:hover>a { 118 | color:@primary-color; 119 | } 120 | } 121 | .form-edit-widget-label>a { 122 | background: @color4; 123 | border: 1px solid @color4; 124 | color: #333333; 125 | cursor: move; 126 | display: block; 127 | padding: 0 5px; 128 | .svg-icon { 129 | display: inline-block; 130 | font-size: 14px; 131 | //margin-left: 8px; 132 | margin-right: 6px; 133 | vertical-align: middle; 134 | } 135 | span { 136 | display: inline-block; 137 | vertical-align: middle; 138 | } 139 | } 140 | } 141 | .widget-form-container { 142 | bottom: 0; 143 | left: 0; 144 | position: absolute; 145 | right: 0; 146 | top: 0; 147 | overflow: auto; 148 | .widget-form-list { 149 | background: @color0; 150 | border: 1px dashed #999999; 151 | margin: 10px; 152 | min-height: calc(100vh - 65px); 153 | .widget-item-container { 154 | position: relative; 155 | .widget-view-action { 156 | background:@primary-color; 157 | bottom: -2px; 158 | height: @height4; 159 | line-height: @height4; 160 | position: absolute; 161 | right: 0; 162 | z-index: 10; 163 | .svg-icon { 164 | color: @color0; 165 | cursor: pointer; 166 | font-size: 14px; 167 | margin: 0 5px; 168 | } 169 | } 170 | .widget-view-drag { 171 | background:@primary-color; 172 | height: @height4; 173 | left: 0; 174 | line-height: @height4; 175 | position: absolute; 176 | top: -2px; 177 | z-index: 10; 178 | .svg-icon { 179 | color: @color0; 180 | cursor: move; 181 | font-size: 14px; 182 | margin: 0 5px; 183 | } 184 | } 185 | } 186 | .widget-col-list { 187 | background: @color0; 188 | border: 1px dashed @color8; 189 | min-height: 50px; 190 | height: auto; 191 | } 192 | .widget-view { 193 | background-color: rgba(236,245,255,0.3); 194 | border: 1px dashed rgba(170,170,170,0.7); 195 | margin: 2px; 196 | //padding-bottom: 18px; 197 | position: relative; 198 | .widget-view-description { 199 | color: #909399; 200 | font-size: 13px; 201 | height: 15px; 202 | line-height: 15px; 203 | margin-top: 6px; 204 | } 205 | &:after { 206 | bottom: 0; 207 | display: block; 208 | left: 0; 209 | position: absolute; 210 | right: 0; 211 | top: 0; 212 | } 213 | &:hover { 214 | background: @primary-background-color; 215 | outline-offset: 0; 216 | outline: 1px solid@primary-color; 217 | .widget-view-drag { 218 | display: block; 219 | } 220 | } 221 | &:hover.active { 222 | border: 1px solid@primary-color; 223 | outline-offset: 0; 224 | outline: 2px solid@primary-color; 225 | } 226 | } 227 | .widget-view.active { 228 | border: 1px solid@primary-color; 229 | outline: 2px solid@primary-color; 230 | } 231 | .widget-view.ghost { 232 | background: @color1; 233 | border: 2px solid @color1; 234 | box-sizing: border-box; 235 | content: ''; 236 | font-size: 0; 237 | height: @height8; 238 | outline-width: 0; 239 | overflow: hidden; 240 | padding: 0; 241 | } 242 | .widget-col { 243 | background-color: rgba(253,246,236,0.3); 244 | padding: 5px; 245 | &:hover { 246 | background: #fdf6ec; 247 | outline-offset: 0px; 248 | outline: 1px solid @color2; 249 | } 250 | &:hover.active { 251 | border: 1px solid @color2; 252 | outline-offset: 0; 253 | outline: 2px solid @color2; 254 | } 255 | .widget-view-action.widget-col-action { 256 | background: @color2; 257 | bottom: -2px; 258 | height: @height4; 259 | line-height: @height4; 260 | position: absolute; 261 | right: -2px; 262 | z-index: 10; 263 | .svg-icon { 264 | color: @color0; 265 | cursor: move; 266 | font-size: 14px; 267 | margin: 0 5px; 268 | } 269 | .svg-icon.delete{ 270 | cursor: pointer; 271 | } 272 | } 273 | .widget-view-drag.widget-col-drag { 274 | background: @color2; 275 | height: @height4; 276 | left: -2px; 277 | line-height: @height4; 278 | position: absolute; 279 | top: -2px; 280 | z-index: 10; 281 | .svg-icon { 282 | color: @color0; 283 | cursor: move; 284 | font-size: 14px; 285 | margin: 0 5px; 286 | } 287 | } 288 | &:after{ 289 | display: none; 290 | } 291 | } 292 | .widget-col.active { 293 | border: 1px solid @color2; 294 | outline: 2px solid @color2; 295 | } 296 | .widget-col.ghost { 297 | background: @color1; 298 | border: 2px solid @color1; 299 | box-sizing: border-box; 300 | content: ''; 301 | font-size: 0; 302 | height: @height8; 303 | outline-width: 0; 304 | overflow: hidden; 305 | padding: 0; 306 | } 307 | .ghost { 308 | background: @color1; 309 | border: 2px solid @color1; 310 | box-sizing: border-box; 311 | content: ''; 312 | font-size: 0; 313 | height: @height8; 314 | outline-width: 0; 315 | overflow: hidden; 316 | padding: 0; 317 | } 318 | } 319 | .n-form--inline .widget-form-list{ 320 | width: 100%; 321 | display: inline-flex; 322 | align-items: flex-start; 323 | align-content: space-around; 324 | } 325 | .ghost { 326 | background: @color1; 327 | border: 2px solid @color1; 328 | position: relative; 329 | &:after { 330 | background: @color1; 331 | } 332 | } 333 | li.ghost { 334 | font-size: 0; 335 | height: 5px; 336 | list-style: none; 337 | overflow: hidden; 338 | } 339 | } 340 | .widget-config-container { 341 | position: relative; 342 | .config-tab { 343 | cursor: pointer; 344 | display: inline-block; 345 | font-size: 14px; 346 | font-weight: 500; 347 | height: 41px; 348 | line-height: 41px; 349 | position: relative; 350 | text-align: center; 351 | width: 145px; 352 | } 353 | .config-tab.active { 354 | border-bottom: 2px solid@primary-color; 355 | } 356 | .config-content { 357 | background: @color0; 358 | overflow: auto; 359 | padding: 10px; 360 | h4 { 361 | border-bottom: 1px solid @color5; 362 | padding-bottom: 10px; 363 | } 364 | .label { 365 | font-size: 14px; 366 | font-weight: 500; 367 | margin: 0 5px; 368 | &:first-child { 369 | margin-left: 0; 370 | } 371 | } 372 | .drag-item { 373 | cursor: move; 374 | font-size: 16px; 375 | margin: 0 5px; 376 | } 377 | } 378 | .ghost { 379 | background: @color0; 380 | border: 1px dashed@primary-color; 381 | &:after{ 382 | background: @color0; 383 | bottom: 0; 384 | content: ''; 385 | display: block; 386 | left: 0; 387 | position: absolute; 388 | right: 0; 389 | top: 0; 390 | } 391 | } 392 | ul { 393 | margin: 0; 394 | padding: 0; 395 | } 396 | li.ghost { 397 | display: block; 398 | font-size: 0; 399 | list-style: none; 400 | position: relative; 401 | } 402 | } 403 | .form-empty { 404 | color: @color8; 405 | font-size: 20px; 406 | left: 50%; 407 | margin-left: -150px; 408 | position: absolute; 409 | text-align: center; 410 | top: 200px; 411 | width: 300px; 412 | } 413 | .widget-empty { 414 | background-position: 50%; 415 | } 416 | } 417 | .fc-form-item-block{ 418 | .n-form-item-blank{ 419 | display: block !important; 420 | } 421 | } 422 | .code-bord{ 423 | color: #7b7979; 424 | background: #e8e8e8; 425 | font-size: 16px; 426 | padding-left: 5px; 427 | } 428 | -------------------------------------------------------------------------------- /src/components/naiveui/components/configs/SelectTree.vue: -------------------------------------------------------------------------------- 1 | 135 | 344 | 345 | 346 | 351 | -------------------------------------------------------------------------------- /src/components/naiveui/components/custom/table/GTable.vue: -------------------------------------------------------------------------------- 1 | 2 | 85 | 86 | 334 | 335 | 364 | -------------------------------------------------------------------------------- /src/components/naiveui/components/configs/Cascader.vue: -------------------------------------------------------------------------------- 1 | 163 | 386 | 387 | 388 | 393 | --------------------------------------------------------------------------------