├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── JSON-Schema.md
├── README.md
├── babel.config.js
├── dist
├── README.md
└── package.json
├── jest.config.js
├── npm
├── README.md
├── index.js
└── package.json
├── package-lock.json
├── package.json
├── public
├── favicon.ico
└── index.html
├── src
├── App.vue
├── assets
│ └── logo.png
├── components
│ ├── Formdesign
│ │ ├── iconfont
│ │ │ ├── iconfont.ttf
│ │ │ ├── iconfont.woff
│ │ │ └── iconfont.woff2
│ │ ├── index.vue
│ │ └── meta
│ │ │ ├── base.js
│ │ │ ├── button.js
│ │ │ ├── canvas.js
│ │ │ ├── cascader.js
│ │ │ ├── checkbox.js
│ │ │ ├── collapse.js
│ │ │ ├── colorpicker.js
│ │ │ ├── datetimepicker.js
│ │ │ ├── grid.js
│ │ │ ├── icon.js
│ │ │ ├── input.js
│ │ │ ├── inputnumber.js
│ │ │ ├── ipinput.js
│ │ │ ├── layout.js
│ │ │ ├── radio.js
│ │ │ ├── rate.js
│ │ │ ├── select.js
│ │ │ ├── slider.js
│ │ │ ├── slot.js
│ │ │ ├── switch.js
│ │ │ ├── tabs.js
│ │ │ ├── timepicker.js
│ │ │ ├── transfer.js
│ │ │ └── upload.js
│ ├── Richform
│ │ ├── actions.vue
│ │ ├── autoLayout.vue
│ │ ├── field.vue
│ │ ├── group
│ │ │ ├── collapse.vue
│ │ │ ├── default.vue
│ │ │ ├── grid.vue
│ │ │ └── tabs.vue
│ │ ├── index.vue
│ │ ├── layout.vue
│ │ ├── utils
│ │ │ ├── commonMixin.js
│ │ │ ├── defaultData.js
│ │ │ ├── design.scss
│ │ │ ├── designMixin.js
│ │ │ ├── eventbus.js
│ │ │ ├── http.js
│ │ │ ├── index.js
│ │ │ ├── themeMixin.js
│ │ │ └── validator.js
│ │ ├── vars.scss
│ │ └── widgets
│ │ │ ├── baseMixin.js
│ │ │ ├── button.vue
│ │ │ ├── cascader.vue
│ │ │ ├── checkbox.vue
│ │ │ ├── colorpicker.vue
│ │ │ ├── components
│ │ │ ├── Input
│ │ │ │ └── index.vue
│ │ │ └── IpInput
│ │ │ │ └── index.vue
│ │ │ ├── datetimepicker.vue
│ │ │ ├── draggablelist.vue
│ │ │ ├── expression.vue
│ │ │ ├── icon.vue
│ │ │ ├── input.vue
│ │ │ ├── inputnumber.vue
│ │ │ ├── ipinput.vue
│ │ │ ├── map.vue
│ │ │ ├── multiexp.vue
│ │ │ ├── radio.vue
│ │ │ ├── rate.vue
│ │ │ ├── select.vue
│ │ │ ├── slider.vue
│ │ │ ├── slot.vue
│ │ │ ├── switch.vue
│ │ │ ├── text.vue
│ │ │ ├── timepicker.vue
│ │ │ ├── timeselect.vue
│ │ │ ├── transfer.vue
│ │ │ ├── tree.vue
│ │ │ └── upload.vue
│ ├── SplitLayout
│ │ ├── index.vue
│ │ └── mixin.scss
│ ├── Teleport
│ │ └── index.vue
│ └── index.js
├── i18n
│ ├── index.js
│ └── lang
│ │ ├── en.js
│ │ ├── vi.js
│ │ └── zh-CN.js
├── main.js
├── package.json
├── pages
│ ├── deep-values.vue
│ ├── form-design.vue
│ └── richform.vue
└── router
│ └── index.js
└── vue.config.js
/.eslintignore:
--------------------------------------------------------------------------------
1 | build/*.js
2 | src/assets
3 | public
4 | dist
5 | src
6 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | parserOptions: {
4 | parser: 'babel-eslint',
5 | sourceType: 'module'
6 | },
7 | env: {
8 | browser: true,
9 | node: true,
10 | es6: true,
11 | },
12 | extends: ['plugin:vue/recommended', 'eslint:recommended'],
13 |
14 | // add your custom rules here
15 | //it is base on https://github.com/vuejs/eslint-config-vue
16 | rules: {
17 | "vue/max-attributes-per-line": [2, {
18 | "singleline": 10,
19 | "multiline": {
20 | "max": 1,
21 | "allowFirstLine": false
22 | }
23 | }],
24 | "vue/singleline-html-element-content-newline": "off",
25 | "vue/multiline-html-element-content-newline":"off",
26 | "vue/name-property-casing": ["error", "PascalCase"],
27 | "vue/no-v-html": "off",
28 | 'accessor-pairs': 2,
29 | 'arrow-spacing': [2, {
30 | 'before': true,
31 | 'after': true
32 | }],
33 | 'block-spacing': [2, 'always'],
34 | 'brace-style': [2, '1tbs', {
35 | 'allowSingleLine': true
36 | }],
37 | 'camelcase': [0, {
38 | 'properties': 'always'
39 | }],
40 | 'comma-dangle': [2, 'never'],
41 | 'comma-spacing': [2, {
42 | 'before': false,
43 | 'after': true
44 | }],
45 | 'comma-style': [2, 'last'],
46 | 'constructor-super': 2,
47 | 'curly': [2, 'multi-line'],
48 | 'dot-location': [2, 'property'],
49 | 'eol-last': 2,
50 | 'eqeqeq': ["error", "always", {"null": "ignore"}],
51 | 'generator-star-spacing': [2, {
52 | 'before': true,
53 | 'after': true
54 | }],
55 | 'handle-callback-err': [2, '^(err|error)$'],
56 | 'indent': [2, 2, {
57 | 'SwitchCase': 1
58 | }],
59 | 'jsx-quotes': [2, 'prefer-single'],
60 | 'key-spacing': [2, {
61 | 'beforeColon': false,
62 | 'afterColon': true
63 | }],
64 | 'keyword-spacing': [2, {
65 | 'before': true,
66 | 'after': true
67 | }],
68 | 'new-cap': [2, {
69 | 'newIsCap': true,
70 | 'capIsNew': false
71 | }],
72 | 'new-parens': 2,
73 | 'no-array-constructor': 2,
74 | 'no-caller': 2,
75 | 'no-console': 'off',
76 | 'no-class-assign': 2,
77 | 'no-cond-assign': 2,
78 | 'no-const-assign': 2,
79 | 'no-control-regex': 0,
80 | 'no-delete-var': 2,
81 | 'no-dupe-args': 2,
82 | 'no-dupe-class-members': 2,
83 | 'no-dupe-keys': 2,
84 | 'no-duplicate-case': 2,
85 | 'no-empty-character-class': 2,
86 | 'no-empty-pattern': 2,
87 | 'no-eval': 2,
88 | 'no-ex-assign': 2,
89 | 'no-extend-native': 2,
90 | 'no-extra-bind': 2,
91 | 'no-extra-boolean-cast': 2,
92 | 'no-extra-parens': [2, 'functions'],
93 | 'no-fallthrough': 2,
94 | 'no-floating-decimal': 2,
95 | 'no-func-assign': 2,
96 | 'no-implied-eval': 2,
97 | 'no-inner-declarations': [2, 'functions'],
98 | 'no-invalid-regexp': 2,
99 | 'no-irregular-whitespace': 2,
100 | 'no-iterator': 2,
101 | 'no-label-var': 2,
102 | 'no-labels': [2, {
103 | 'allowLoop': false,
104 | 'allowSwitch': false
105 | }],
106 | 'no-lone-blocks': 2,
107 | 'no-mixed-spaces-and-tabs': 2,
108 | 'no-multi-spaces': 2,
109 | 'no-multi-str': 2,
110 | 'no-multiple-empty-lines': [2, {
111 | 'max': 1
112 | }],
113 | 'no-native-reassign': 2,
114 | 'no-negated-in-lhs': 2,
115 | 'no-new-object': 2,
116 | 'no-new-require': 2,
117 | 'no-new-symbol': 2,
118 | 'no-new-wrappers': 2,
119 | 'no-obj-calls': 2,
120 | 'no-octal': 2,
121 | 'no-octal-escape': 2,
122 | 'no-path-concat': 2,
123 | 'no-proto': 2,
124 | 'no-redeclare': 2,
125 | 'no-regex-spaces': 2,
126 | 'no-return-assign': [2, 'except-parens'],
127 | 'no-self-assign': 2,
128 | 'no-self-compare': 2,
129 | 'no-sequences': 2,
130 | 'no-shadow-restricted-names': 2,
131 | 'no-spaced-func': 2,
132 | 'no-sparse-arrays': 2,
133 | 'no-this-before-super': 2,
134 | 'no-throw-literal': 2,
135 | 'no-trailing-spaces': 2,
136 | 'no-undef': 2,
137 | 'no-undef-init': 2,
138 | 'no-unexpected-multiline': 2,
139 | 'no-unmodified-loop-condition': 2,
140 | 'no-unneeded-ternary': [2, {
141 | 'defaultAssignment': false
142 | }],
143 | 'no-unreachable': 2,
144 | 'no-unsafe-finally': 2,
145 | 'no-unused-vars': [2, {
146 | 'vars': 'all',
147 | 'args': 'none'
148 | }],
149 | 'no-useless-call': 2,
150 | 'no-useless-computed-key': 2,
151 | 'no-useless-constructor': 2,
152 | 'no-useless-escape': 0,
153 | 'no-whitespace-before-property': 2,
154 | 'no-with': 2,
155 | 'one-var': [2, {
156 | 'initialized': 'never'
157 | }],
158 | 'operator-linebreak': [2, 'after', {
159 | 'overrides': {
160 | '?': 'before',
161 | ':': 'before'
162 | }
163 | }],
164 | 'padded-blocks': [2, 'never'],
165 | 'quotes': [2, 'single', {
166 | 'avoidEscape': true,
167 | 'allowTemplateLiterals': true
168 | }],
169 | 'semi': [2, 'never'],
170 | 'semi-spacing': [2, {
171 | 'before': false,
172 | 'after': true
173 | }],
174 | 'space-before-blocks': [2, 'always'],
175 | // 'space-before-function-paren': [2, 'never'],
176 | 'space-in-parens': [2, 'never'],
177 | 'space-infix-ops': 2,
178 | 'space-unary-ops': [2, {
179 | 'words': true,
180 | 'nonwords': false
181 | }],
182 | 'spaced-comment': [2, 'always', {
183 | 'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ',']
184 | }],
185 | 'template-curly-spacing': [2, 'never'],
186 | 'use-isnan': 2,
187 | 'valid-typeof': 2,
188 | 'wrap-iife': [2, 'any'],
189 | 'yield-star-spacing': [2, 'both'],
190 | 'yoda': [2, 'never'],
191 | 'prefer-const': 2,
192 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
193 | 'object-curly-spacing': [2, 'always', {
194 | objectsInObjects: false
195 | }],
196 | 'array-bracket-spacing': [2, 'never']
197 | }
198 | }
199 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | dist/lib
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 | pnpm-debug.log*
14 |
15 | # Editor directories and files
16 | .idea
17 | .vscode
18 | *.suo
19 | *.ntvs*
20 | *.njsproj
21 | *.sln
22 | *.sw?
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # richform
2 |
3 | ## 主要功能
4 | * richform表单组件
5 | * 数据驱动
6 | * 校验规则采用标准的JsonSchema,[JsonSchema文档](https://github.com/jingyuLin1999/richform/blob/main/JSON-Schema.md)
7 | * 可拓展性,widgets下可自定义一些子组件
8 | * 表单设计器
9 | * 基于richform表单的拓展,可动态设计表单
10 | * 表单设计所见即所得
11 | * 可设置字段属性和校验规则
12 | * 签核流程
13 | * 基于RichForm和表单设计器的拓展
14 | * 流程配置。动态添加节点,设计各节点的签核顺序,串并联签核
15 | * 节点个性化。每个节点表单用RichForm显示,数据来源于表单设计器的设计结果
16 | * 节点属性。签核人设置、签核类型(会签,串签)、出口配置
17 | * 已签核状态显示
18 | * 错误处理
19 |
20 | ## 支持vue2.x
21 | vue3.x 请见[richform-plus](https://github.com/jingyuLin1999/richform-plus)
22 |
23 | ## 预览
24 |
25 | ### 在线预览
26 |
27 | [表单设计器](http://156.232.10.2/richform/#/)
28 |
29 | [富表单完整功能](http://156.232.10.2/richform/#/richform)
30 |
31 | ### 本地预览
32 | ```
33 | npm install
34 |
35 | npm run serve
36 | ```
37 | [表单设计器](http://localhost:8080/#/ )
38 | http://localhost:8080/#/
39 |
40 | [富表单完整功能](http://localhost:8080/#/form-design )
41 | http://localhost:8080/#/form-design
42 |
43 | ## 用法
44 | ```
45 | npm i richform -S
46 | ```
47 |
48 | ```html
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | ```
58 |
59 | ```js
60 | import { RichForm, FormDesign } from "richform";
61 | export default {
62 | components: { RichForm,FormDesign},
63 | data() {
64 | return {
65 | schema: {}, // 验证规则
66 | values: {}, // 表单的值
67 | form: {
68 | border: true, // 显示边框
69 | grid: false, // 表单内部栅栏
70 | labelSuffix: ":", // 字段标题后缀内容,默认' : '
71 | labelWidth: "110px", // 标签宽度,默认50px
72 | validator: "input", // submit
73 | labelAlign: "right", // 标签对齐, 默认右对齐, 可选左对齐left
74 | labelInline: true, // 字段标题显示位置, 默认true左侧left,false显示在top上方
75 | actions: [
76 | //声明显示在下方和动作按钮
77 | {
78 | name: "reset", // 按键的唯一标识符
79 | type: "primary", // 按键类型,默认为primary,具体可见element button
80 | title: "重置", // 按键的文字
81 | icon: "el-icon-star-off", // 按键图标 具体可见element icon
82 | right: true, // 如果=true,则显示在右侧
83 | visible: true, // 按键是否可见,同时满足readonly===false和设置为true才会显示,默认为true
84 | tips: "提示信息", // 鼠标悬浮在按键的提示信息
85 | top: true, // 是否在上面, false则在下面
86 | size: "medium" // medium / small / mini, 若未指明,则等同于form.size
87 | },
88 | {
89 | name: "submit", // 按键的唯一标识符
90 | type: "info", // 按键类型,默认为primary,具体可见element button
91 | title: "提交", // 按键的文字
92 | icon: "", // 按键图标 具体可见element icon
93 | right: true, // 如果=true,则显示在右侧
94 | visible: true, // 按键是否可见,同时满足readonly===false和设置为true才会显示,默认为true
95 | tips: "提示信息", // 鼠标悬浮在按键的提示信息
96 | top: true, // 是否在上面, false则在下面
97 | size: "medium" // medium / small / mini, 若未指明,则等同于form.size
98 | }
99 | ],
100 | layout: [
101 | {
102 | title: "名称对方",
103 | widget: "input",
104 | name: "input", // values的箭值,必须有
105 | type: "text",
106 | },
107 | // 更多子组件请见widgets介绍,或者看完整功能
108 | ]
109 | }
110 | }
111 | }
112 | }
113 | ```
114 |
115 | ## 特殊功能
116 | 1、字段选项依赖
117 | ```js
118 | {
119 | title: "下拉选框B",
120 | widget: "select",
121 | name: "selectB",
122 | description: "我的选项依赖于【下拉选框A】",
123 | dict: {
124 | "selectA==选项1": [
125 | {
126 | value: "选项1",
127 | label: "根据[下拉选框A]的值变化A",
128 | },
129 | {
130 | value: "选项2",
131 | label: "根据[下拉选框A]的值变化B",
132 | },
133 | ],
134 | "selectA == 选项2": "http://localhost:8080/#/form-design",
135 | "input == 123456": [
136 | {
137 | value: "input等于123456",
138 | label: "input等于123456",
139 | },
140 | ],
141 | },
142 | options: [
143 | {
144 | value: "选项1",
145 | label: "黄金糕",
146 | },
147 | {
148 | value: "选项2",
149 | label: "双皮奶",
150 | },
151 | ],
152 | }
153 | ```
154 | 补充说明
155 | 当两个select的选项互相依赖时,箭值为条件,值可以有三种形式,若是url则获取数据,若是数组则直接赋值给options
156 | ```js
157 | dict: "http://localhost:8080/#/form-design", // 获取到的值会直接覆盖options
158 | dict: {
159 | [<字段名name> == 'A']: "https://shandawang.com/dict/province", // 字典,
160 | [<字段名name> == 'B']: [{},{}], // options
161 | [<字段名name> == 'any']: "https://shandawang.com/dict/province", // 若等于any且值是url,<字段名name>的值只要变化,就会带上<字段名name>值到后端过滤获取字典
162 | [<字段名name> == 'any']: {filterKey: "id"}, // 若等于any且值是对象,filterKey字段和options都必须有。<字段名name>的值只要变化,就会带上<字段名name>值到options中过滤。有一种特殊应用,当被依赖的字段值变化了,根据被依赖选项({label,value,other})的某个字段的值到当前options过滤,此时可配beRelyFilterKey如 {filterKey: "id",beRelyFilterKey: "other"}
163 | }
164 | ```
165 | 2、字段隐藏依赖
166 | ```js
167 | {
168 | title: "名称对方",
169 | widget: "input",
170 | name: "input",
171 | type: "textarea",
172 | hideRely: "radioA==单选框B",
173 | }
174 | ```
175 | 补充说明
176 | ```js
177 | hideRely:<字段名称nameA> == 'C', // 可以是单值
178 | hideRely:[ // 也可以是多值,只要满足一个条件,就隐藏,且后面条件不会再校验
179 | <字段名称nameA> == 'C',
180 | <字段名称nameB> == 'D',
181 | ]
182 | ```
183 | 3、更多widgets配置详情
184 | 请见src/pages/richform.vue
185 |
186 | ## 深度编辑
187 | values可能是深度嵌套如下
188 | ```js
189 | {
190 | title: {
191 | text: "ECharts 入门示例",
192 | subtext: "Living Expenses in Shenzhen",
193 | },
194 | legend: {
195 | orient: "horizontal", // vertical/horizontal
196 | left: 0,
197 | // top: 0,
198 | bottom: 0,
199 | },
200 | }
201 | ```
202 | 要编辑这种valuse可开启deepValues: true
203 | ```html
204 |
205 | ```
206 | 此时在定义form的name字段和shema结构,需要与values的结构对应
207 | ```js
208 | layout: [{
209 | title: "标题",
210 | widget: "input",
211 | name: "title.text",
212 | }]
213 | ```
214 | [例子](http://117.73.12.76/demo/richform/#/deep-values )
215 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | [
4 | "@vue/app",
5 | {
6 | "useBuiltIns": "entry",
7 | polyfills: [
8 | 'es6.promise',
9 | 'es6.symbol'
10 | ]
11 | }
12 | ]
13 | ],
14 | }
15 |
--------------------------------------------------------------------------------
/dist/README.md:
--------------------------------------------------------------------------------
1 | # richform
2 |
3 | ## 主要功能
4 | * richform表单组件
5 | * 数据驱动
6 | * 校验规则采用标准的JsonSchema,[JsonSchema文档](https://github.com/jingyuLin1999/richform/blob/main/JSON-Schema.md)
7 | * 可拓展性,widgets下可自定义一些子组件
8 | * 表单设计器
9 | * 基于richform表单的拓展,可动态设计表单
10 | * 表单设计所见即所得
11 | * 可设置字段属性和校验规则
12 | * 签核流程
13 | * 基于RichForm和表单设计器的拓展
14 | * 流程配置。动态添加节点,设计各节点的签核顺序,串并联签核
15 | * 节点个性化。每个节点表单用RichForm显示,数据来源于表单设计器的设计结果
16 | * 节点属性。签核人设置、签核类型(会签,串签)、出口配置
17 | * 已签核状态显示
18 | * 错误处理
19 |
20 | ## 支持vue2.x
21 | vue3.x 请见[richform-plus](https://github.com/jingyuLin1999/richform-plus)
22 |
23 | ## 预览
24 |
25 | ### 在线预览
26 |
27 | [表单设计器](http://117.73.12.76/demo/richform/#/ )
28 |
29 | [富表单完整功能](http://117.73.12.76/demo/richform/#/form-design )
30 |
31 | ### 本地预览
32 | ```
33 | npm install
34 |
35 | npm run serve
36 | ```
37 | [表单设计器](http://localhost:8080/#/ )
38 | http://localhost:8080/#/
39 |
40 | [富表单完整功能](http://localhost:8080/#/form-design )
41 | http://localhost:8080/#/form-design
42 |
43 | ## 用法
44 | ```
45 | npm i richform -S
46 | ```
47 |
48 | ```html
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | ```
58 |
59 | ```js
60 | import { RichForm, FormDesign } from "richform";
61 | export default {
62 | components: { RichForm,FormDesign},
63 | data() {
64 | return {
65 | schema: {}, // 验证规则
66 | values: {}, // 表单的值
67 | form: {
68 | border: true, // 显示边框
69 | grid: false, // 表单内部栅栏
70 | labelSuffix: ":", // 字段标题后缀内容,默认' : '
71 | labelWidth: "110px", // 标签宽度,默认50px
72 | validator: "input", // submit
73 | labelAlign: "right", // 标签对齐, 默认右对齐, 可选左对齐left
74 | labelInline: true, // 字段标题显示位置, 默认true左侧left,false显示在top上方
75 | actions: [
76 | //声明显示在下方和动作按钮
77 | {
78 | name: "reset", // 按键的唯一标识符
79 | type: "primary", // 按键类型,默认为primary,具体可见element button
80 | title: "重置", // 按键的文字
81 | icon: "el-icon-star-off", // 按键图标 具体可见element icon
82 | right: true, // 如果=true,则显示在右侧
83 | visible: true, // 按键是否可见,同时满足readonly===false和设置为true才会显示,默认为true
84 | tips: "提示信息", // 鼠标悬浮在按键的提示信息
85 | top: true, // 是否在上面, false则在下面
86 | size: "medium" // medium / small / mini, 若未指明,则等同于form.size
87 | },
88 | {
89 | name: "submit", // 按键的唯一标识符
90 | type: "info", // 按键类型,默认为primary,具体可见element button
91 | title: "提交", // 按键的文字
92 | icon: "", // 按键图标 具体可见element icon
93 | right: true, // 如果=true,则显示在右侧
94 | visible: true, // 按键是否可见,同时满足readonly===false和设置为true才会显示,默认为true
95 | tips: "提示信息", // 鼠标悬浮在按键的提示信息
96 | top: true, // 是否在上面, false则在下面
97 | size: "medium" // medium / small / mini, 若未指明,则等同于form.size
98 | }
99 | ],
100 | layout: [
101 | {
102 | title: "名称对方",
103 | widget: "input",
104 | name: "input", // values的箭值,必须有
105 | type: "text",
106 | },
107 | // 更多子组件请见widgets介绍,或者看完整功能
108 | ]
109 | }
110 | }
111 | }
112 | }
113 | ```
114 |
115 | ## 特殊功能
116 | 1、字段选项依赖
117 | ```js
118 | {
119 | title: "下拉选框B",
120 | widget: "select",
121 | name: "selectB",
122 | description: "我的选项依赖于【下拉选框A】",
123 | dict: {
124 | "selectA==选项1": [
125 | {
126 | value: "选项1",
127 | label: "根据[下拉选框A]的值变化A",
128 | },
129 | {
130 | value: "选项2",
131 | label: "根据[下拉选框A]的值变化B",
132 | },
133 | ],
134 | "selectA == 选项2": "http://localhost:8080/#/form-design",
135 | "input == 123456": [
136 | {
137 | value: "input等于123456",
138 | label: "input等于123456",
139 | },
140 | ],
141 | },
142 | options: [
143 | {
144 | value: "选项1",
145 | label: "黄金糕",
146 | },
147 | {
148 | value: "选项2",
149 | label: "双皮奶",
150 | },
151 | ],
152 | }
153 | ```
154 | 补充说明
155 | 当两个select的选项互相依赖时,箭值为条件,值可以有三种形式,若是url则获取数据,若是数组则直接赋值给options
156 | ```js
157 | dict: "http://localhost:8080/#/form-design", // 获取到的值会直接覆盖options
158 | dict: {
159 | [<字段名name> == 'A']: "https://shandawang.com/dict/province", // 字典,
160 | [<字段名name> == 'B']: [{},{}], // options
161 | [<字段名name> == 'any']: "https://shandawang.com/dict/province", // 若等于any且值是url,<字段名name>的值只要变化,就会带上<字段名name>值到后端过滤获取字典
162 | [<字段名name> == 'any']: {filterKey: "id"}, // 若等于any且值是对象,filterKey字段和options都必须有。<字段名name>的值只要变化,就会带上<字段名name>值到options中过滤。有一种特殊应用,当被依赖的字段值变化了,根据被依赖选项({label,value,other})的某个字段的值到当前options过滤,此时可配beRelyFilterKey如 {filterKey: "id",beRelyFilterKey: "other"}
163 | }
164 | ```
165 | 2、字段隐藏依赖
166 | ```js
167 | {
168 | title: "名称对方",
169 | widget: "input",
170 | name: "input",
171 | type: "textarea",
172 | hideRely: "radioA==单选框B",
173 | }
174 | ```
175 | 补充说明
176 | ```js
177 | hideRely:<字段名称nameA> == 'C', // 可以是单值
178 | hideRely:[ // 也可以是多值,只要满足一个条件,就隐藏,且后面条件不会再校验
179 | <字段名称nameA> == 'C',
180 | <字段名称nameB> == 'D',
181 | ]
182 | ```
183 | 3、更多widgets配置详情
184 | 请见src/pages/richform.vue
185 |
186 | ## 深度编辑
187 | values可能是深度嵌套如下
188 | ```js
189 | {
190 | title: {
191 | text: "ECharts 入门示例",
192 | subtext: "Living Expenses in Shenzhen",
193 | },
194 | legend: {
195 | orient: "horizontal", // vertical/horizontal
196 | left: 0,
197 | // top: 0,
198 | bottom: 0,
199 | },
200 | }
201 | ```
202 | 要编辑这种valuse可开启deepValues: true
203 | ```html
204 |
205 | ```
206 | 此时在定义form的name字段和shema结构,需要与values的结构对应
207 | ```js
208 | layout: [{
209 | title: "标题",
210 | widget: "input",
211 | name: "title.text",
212 | }]
213 | ```
214 | [例子](http://117.73.12.76/demo/richform/#/deep-values )
215 |
--------------------------------------------------------------------------------
/dist/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "richform",
3 | "version": "0.11.50",
4 | "private": false,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "build:prod": "vue-cli-service build --target lib --name richform src/components/index.js",
9 | "lint": "vue-cli-service lint"
10 | },
11 | "main": "lib/richform.umd.min.js",
12 | "module": "lib/richform.umd.min.js",
13 | "dependencies": {
14 | "ajv": "^6.12.6",
15 | "ajv-errors": "^1.0.1",
16 | "axios": "^0.21.1",
17 | "core-js": "^3.6.5",
18 | "element-resize-detector": "^1.2.4",
19 | "element-ui": "^2.15.6",
20 | "jquery": "^3.6.0",
21 | "ramda": "^0.27.1",
22 | "vue-baidu-map": "^0.21.22",
23 | "vue-i18n": "^8.28.2",
24 | "vue-scrollto": "^2.20.0",
25 | "vue2-perfect-scrollbar": "^1.5.0",
26 | "vuedraggable": "^2.24.3",
27 | "vxe-table": "^3.4.15",
28 | "xe-utils": "^3.5.4"
29 | },
30 | "eslintConfig": {
31 | "root": true,
32 | "env": {
33 | "node": true
34 | },
35 | "extends": [
36 | "plugin:vue/essential",
37 | "eslint:recommended"
38 | ],
39 | "parserOptions": {
40 | "parser": "babel-eslint"
41 | },
42 | "rules": {
43 | "generator-star-spacing": "off",
44 | "no-tabs": "off",
45 | "no-unused-vars": "off",
46 | "no-console": "off",
47 | "no-irregular-whitespace": "off",
48 | "no-debugger": "off"
49 | }
50 | },
51 | "files": [
52 | "dist",
53 | "src/i18n/lang"
54 | ],
55 | "browserslist": [
56 | "> 1%",
57 | "last 2 versions"
58 | ],
59 | "author": "ljy",
60 | "license": "ISC",
61 | "repository": {
62 | "type": "git",
63 | "url": "git+https://github.com/jingyuLin1999/richform"
64 | }
65 | }
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
3 | transform: {
4 | '^.+\\.vue$': 'vue-jest',
5 | '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$':
6 | 'jest-transform-stub',
7 | '^.+\\.jsx?$': 'babel-jest'
8 | },
9 | moduleNameMapper: {
10 | '^@/(.*)$': '/src/$1'
11 | },
12 | snapshotSerializers: ['jest-serializer-vue'],
13 | testMatch: [
14 | '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
15 | ],
16 | collectCoverageFrom: ['src/utils/**/*.{js,vue}', '!src/utils/auth.js', '!src/utils/request.js', 'src/components/**/*.{js,vue}'],
17 | coverageDirectory: '/tests/unit/coverage',
18 | // 'collectCoverage': true,
19 | 'coverageReporters': [
20 | 'lcov',
21 | 'text-summary'
22 | ],
23 | testURL: 'http://localhost/'
24 | }
25 |
--------------------------------------------------------------------------------
/npm/README.md:
--------------------------------------------------------------------------------
1 | # richform
2 |
3 | ## 主要功能
4 | * richform表单组件
5 | * 数据驱动
6 | * 校验规则采用标准的JsonSchema,[JsonSchema文档](https://github.com/jingyuLin1999/richform/blob/main/JSON-Schema.md)
7 | * 可拓展性,widgets下可自定义一些子组件
8 | * 表单设计器
9 | * 基于richform表单的拓展,可动态设计表单
10 | * 表单设计所见即所得
11 | * 可设置字段属性和校验规则
12 | * 签核流程
13 | * 基于RichForm和表单设计器的拓展
14 | * 流程配置。动态添加节点,设计各节点的签核顺序,串并联签核
15 | * 节点个性化。每个节点表单用RichForm显示,数据来源于表单设计器的设计结果
16 | * 节点属性。签核人设置、签核类型(会签,串签)、出口配置
17 | * 已签核状态显示
18 | * 错误处理
19 |
20 | ## 支持vue2.x
21 | vue3.x 请见[richform-plus](https://github.com/jingyuLin1999/richform-plus)
22 |
23 | ## 预览
24 |
25 | ### 在线预览
26 |
27 | [表单设计器](http://117.73.12.76/demo/richform/#/ )
28 |
29 | [富表单完整功能](http://117.73.12.76/demo/richform/#/form-design )
30 |
31 | ### 本地预览
32 | ```
33 | npm install
34 |
35 | npm run serve
36 | ```
37 | [表单设计器](http://localhost:8080/#/ )
38 | http://localhost:8080/#/
39 |
40 | [富表单完整功能](http://localhost:8080/#/form-design )
41 | http://localhost:8080/#/form-design
42 |
43 | ## 用法
44 | ```
45 | npm i richform -S
46 | ```
47 |
48 | ```html
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | ```
58 |
59 | ```js
60 | import { RichForm, FormDesign } from "richform";
61 | export default {
62 | components: { RichForm,FormDesign},
63 | data() {
64 | return {
65 | schema: {}, // 验证规则
66 | values: {}, // 表单的值
67 | form: {
68 | border: true, // 显示边框
69 | grid: false, // 表单内部栅栏
70 | labelSuffix: ":", // 字段标题后缀内容,默认' : '
71 | labelWidth: "110px", // 标签宽度,默认50px
72 | validator: "input", // submit
73 | labelAlign: "right", // 标签对齐, 默认右对齐, 可选左对齐left
74 | labelInline: true, // 字段标题显示位置, 默认true左侧left,false显示在top上方
75 | actions: [
76 | //声明显示在下方和动作按钮
77 | {
78 | name: "reset", // 按键的唯一标识符
79 | type: "primary", // 按键类型,默认为primary,具体可见element button
80 | title: "重置", // 按键的文字
81 | icon: "el-icon-star-off", // 按键图标 具体可见element icon
82 | right: true, // 如果=true,则显示在右侧
83 | visible: true, // 按键是否可见,同时满足readonly===false和设置为true才会显示,默认为true
84 | tips: "提示信息", // 鼠标悬浮在按键的提示信息
85 | top: true, // 是否在上面, false则在下面
86 | size: "medium" // medium / small / mini, 若未指明,则等同于form.size
87 | },
88 | {
89 | name: "submit", // 按键的唯一标识符
90 | type: "info", // 按键类型,默认为primary,具体可见element button
91 | title: "提交", // 按键的文字
92 | icon: "", // 按键图标 具体可见element icon
93 | right: true, // 如果=true,则显示在右侧
94 | visible: true, // 按键是否可见,同时满足readonly===false和设置为true才会显示,默认为true
95 | tips: "提示信息", // 鼠标悬浮在按键的提示信息
96 | top: true, // 是否在上面, false则在下面
97 | size: "medium" // medium / small / mini, 若未指明,则等同于form.size
98 | }
99 | ],
100 | layout: [
101 | {
102 | title: "名称对方",
103 | widget: "input",
104 | name: "input", // values的箭值,必须有
105 | type: "text",
106 | },
107 | // 更多子组件请见widgets介绍,或者看完整功能
108 | ]
109 | }
110 | }
111 | }
112 | }
113 | ```
114 |
115 | ## 特殊功能
116 | 1、字段选项依赖
117 | ```js
118 | {
119 | title: "下拉选框B",
120 | widget: "select",
121 | name: "selectB",
122 | description: "我的选项依赖于【下拉选框A】",
123 | dict: {
124 | "selectA==选项1": [
125 | {
126 | value: "选项1",
127 | label: "根据[下拉选框A]的值变化A",
128 | },
129 | {
130 | value: "选项2",
131 | label: "根据[下拉选框A]的值变化B",
132 | },
133 | ],
134 | "selectA == 选项2": "http://localhost:8080/#/form-design",
135 | "input == 123456": [
136 | {
137 | value: "input等于123456",
138 | label: "input等于123456",
139 | },
140 | ],
141 | },
142 | options: [
143 | {
144 | value: "选项1",
145 | label: "黄金糕",
146 | },
147 | {
148 | value: "选项2",
149 | label: "双皮奶",
150 | },
151 | ],
152 | }
153 | ```
154 | 补充说明
155 | 当两个select的选项互相依赖时,箭值为条件,值可以有三种形式,若是url则获取数据,若是数组则直接赋值给options
156 | ```js
157 | dict: "http://localhost:8080/#/form-design", // 获取到的值会直接覆盖options
158 | dict: {
159 | [<字段名name> == 'A']: "https://shandawang.com/dict/province", // 字典,
160 | [<字段名name> == 'B']: [{},{}], // options
161 | [<字段名name> == 'any']: "https://shandawang.com/dict/province", // 若等于any且值是url,<字段名name>的值只要变化,就会带上<字段名name>值到后端过滤获取字典
162 | [<字段名name> == 'any']: {filterKey: "id"}, // 若等于any且值是对象,filterKey字段和options都必须有。<字段名name>的值只要变化,就会带上<字段名name>值到options中过滤。有一种特殊应用,当被依赖的字段值变化了,根据被依赖选项({label,value,other})的某个字段的值到当前options过滤,此时可配beRelyFilterKey如 {filterKey: "id",beRelyFilterKey: "other"}
163 | }
164 | ```
165 | 2、字段隐藏依赖
166 | ```js
167 | {
168 | title: "名称对方",
169 | widget: "input",
170 | name: "input",
171 | type: "textarea",
172 | hideRely: "radioA==单选框B",
173 | }
174 | ```
175 | 补充说明
176 | ```js
177 | hideRely:<字段名称nameA> == 'C', // 可以是单值
178 | hideRely:[ // 也可以是多值,只要满足一个条件,就隐藏,且后面条件不会再校验
179 | <字段名称nameA> == 'C',
180 | <字段名称nameB> == 'D',
181 | ]
182 | ```
183 | 3、更多widgets配置详情
184 | 请见src/pages/richform.vue
185 |
186 | ## 深度编辑
187 | values可能是深度嵌套如下
188 | ```js
189 | {
190 | title: {
191 | text: "ECharts 入门示例",
192 | subtext: "Living Expenses in Shenzhen",
193 | },
194 | legend: {
195 | orient: "horizontal", // vertical/horizontal
196 | left: 0,
197 | // top: 0,
198 | bottom: 0,
199 | },
200 | }
201 | ```
202 | 要编辑这种valuse可开启deepValues: true
203 | ```html
204 |
205 | ```
206 | 此时在定义form的name字段和shema结构,需要与values的结构对应
207 | ```js
208 | layout: [{
209 | title: "标题",
210 | widget: "input",
211 | name: "title.text",
212 | }]
213 | ```
214 | [例子](http://117.73.12.76/demo/richform/#/deep-values )
215 |
--------------------------------------------------------------------------------
/npm/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | module.exports = function localize_zh(errors) {
3 | if (!(errors && errors.length)) return;
4 | for (var i = 0; i < errors.length; i++) {
5 | var e = errors[i];
6 | var out;
7 | switch (e.keyword) {
8 | case '$ref':
9 | out = 'Không thể tìm thấy tài liệu tham khảo' + (e.params.ref);
10 | break;
11 | case 'additionalItems':
12 | out = '';
13 | var n = e.params.limit;
14 | out += 'Không được phép nhiều hơn' + (n) + 'phần tử';
15 | break;
16 | case 'additionalProperties':
17 | out = 'Không cho phép thuộc tính bên ngoài';
18 | break;
19 | case 'anyOf':
20 | out = 'Dữ liệu phải là một trong những dữ liệu được chỉ định bởi AnyOf';
21 | break;
22 | case 'const':
23 | out = 'Phải bằng hằng số';
24 | break;
25 | case 'contains':
26 | out = 'Nên chứa một mục hợp lệ';
27 | break;
28 | case 'custom':
29 | out = 'Nên thông qua xác minh từ khóa' + (e.keyword);
30 | break;
31 | case 'dependencies':
32 | out = '';
33 | var n = e.params.depsCount;
34 | out += 'Nên có thuộc tính phụ thuộc cho thuộc tính ' + (e.params.property) + ":" + (e.params.deps);
35 | break;
36 | case 'enum':
37 | out = 'Phải là một trong những giá trị liệt kê mặc định';
38 | break;
39 | case 'exclusiveMaximum':
40 | out = '';
41 | var cond = e.params.comparison + " " + e.params.limit;
42 | out += 'Nên là ' + (cond);
43 | break;
44 | case 'exclusiveMinimum':
45 | out = '';
46 | var cond = e.params.comparison + " " + e.params.limit;
47 | out += 'Nên là ' + (cond);
48 | break;
49 | case 'false schema':
50 | out = 'Lỗi mẫu Boolean';
51 | break;
52 | case 'format':
53 | out = 'Phải phù hợp với định dạng "' + (e.params.format) + '"';
54 | break;
55 | case 'formatExclusiveMaximum':
56 | out = 'formatExclusiveMaximum Phải là giá trị Boolean';
57 | break;
58 | case 'formatExclusiveMinimum':
59 | out = 'formatExclusiveMinimum Phải là giá trị Boolean';
60 | break;
61 | case 'formatMaximum':
62 | out = '';
63 | var cond = e.params.comparison + " " + e.params.limit;
64 | out += 'Nên là ' + (cond);
65 | break;
66 | case 'formatMinimum':
67 | out = '';
68 | var cond = e.params.comparison + " " + e.params.limit;
69 | out += 'Nên là ' + (cond);
70 | break;
71 | case 'if':
72 | out = 'nên phù hợp với mẫu "' + (e.params.failingKeyword) + '" ';
73 | break;
74 | case 'maximum':
75 | out = '';
76 | var cond = e.params.comparison + " " + e.params.limit;
77 | out += 'Nên là ' + (cond);
78 | break;
79 | case 'maxItems':
80 | out = '';
81 | var n = e.params.limit;
82 | out += 'Không nên có nhiều hơn ' + (n) + ' mục';
83 | break;
84 | case 'maxLength':
85 | out = '';
86 | var n = e.params.limit;
87 | out += 'Không được nhiều hơn ' + (n) + ' ký tự';
88 | break;
89 | case 'maxProperties':
90 | out = '';
91 | var n = e.params.limit;
92 | out += 'Không được có nhiều hơn ' + (n) + ' thuộc tính';
93 | break;
94 | case 'minimum':
95 | out = '';
96 | var cond = e.params.comparison + " " + e.params.limit;
97 | out += 'Nên là ' + (cond);
98 | break;
99 | case 'minItems':
100 | out = '';
101 | var n = e.params.limit;
102 | out += 'Không được ít hơn ' + (n) + ' mục';
103 | break;
104 | case 'minLength':
105 | out = '';
106 | var n = e.params.limit;
107 | out += 'Không được ít hơn ' + (n) + ' ký tự';
108 | break;
109 | case 'minProperties':
110 | out = '';
111 | var n = e.params.limit;
112 | out += 'Không được có ít hơn ' + (n) + ' thuộc tính';
113 | break;
114 | case 'multipleOf':
115 | out = 'Phải là bội số nguyên của ' + (e.params.multipleOf);
116 | break;
117 | case 'not':
118 | out = 'không nên phù hợp "not" schema';
119 | break;
120 | case 'oneOf':
121 | out = 'Chỉ có thể khớp với một trong "oneOf"';
122 | break;
123 | case 'pattern':
124 | out = 'nên phù hợp với mẫu "' + (e.params.pattern) + '"';
125 | break;
126 | case 'patternRequired':
127 | out = 'Cần có mẫu khớp thuộc tính ' + (e.params.missingPattern);
128 | break;
129 | case 'propertyNames':
130 | out = 'Tên thuộc tính không hợp lệ \'' + (e.params.propertyName);
131 | break;
132 | case 'required':
133 | out = 'Nên có thuộc tính bắt buộc ' + (e.params.missingProperty);
134 | break;
135 | case 'switch':
136 | out = 'không thông qua hiệu nghiệm "switch" vì' + (e.params.caseIndex) + ' thất bại ';
137 | break;
138 | case 'type':
139 | out = 'Nên thuộc loại ' + (e.params.type);
140 | break;
141 | case 'uniqueItems':
142 | out = 'Không được trùng lặp (mục (' + (e.params.j) + ') và (' + (e.params.i) + ') là trùng lặp)';
143 | break;
144 | default:
145 | continue;
146 | }
147 | e.message = out;
148 | }
149 | };
150 |
--------------------------------------------------------------------------------
/npm/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "richform",
3 | "version": "0.11.50",
4 | "private": false,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "build:prod": "vue-cli-service build --target lib --name richform src/components/index.js",
9 | "lint": "vue-cli-service lint"
10 | },
11 | "main": "lib/richform.umd.min.js",
12 | "module": "lib/richform.umd.min.js",
13 | "dependencies": {
14 | "ajv": "^6.12.6",
15 | "ajv-errors": "^1.0.1",
16 | "axios": "^0.21.1",
17 | "core-js": "^3.6.5",
18 | "element-resize-detector": "^1.2.4",
19 | "element-ui": "^2.15.6",
20 | "jquery": "^3.6.0",
21 | "ramda": "^0.27.1",
22 | "vue-baidu-map": "^0.21.22",
23 | "vue-i18n": "^8.28.2",
24 | "vue-scrollto": "^2.20.0",
25 | "vue2-perfect-scrollbar": "^1.5.0",
26 | "vuedraggable": "^2.24.3",
27 | "vxe-table": "^3.4.15",
28 | "xe-utils": "^3.5.4"
29 | },
30 | "devDependencies": {
31 | "@vue/babel-preset-app": "^5.0.8",
32 | "@vue/cli-plugin-babel": "~4.5.0",
33 | "@vue/cli-plugin-eslint": "~4.5.0",
34 | "@vue/cli-service": "~4.5.0",
35 | "babel-eslint": "^10.1.0",
36 | "babel-polyfill": "^6.26.0",
37 | "es6-promise": "^4.2.8",
38 | "eslint": "^6.7.2",
39 | "eslint-plugin-vue": "^6.2.2",
40 | "node-sass": "^6.0.1",
41 | "sass-loader": "^10.3.1",
42 | "vue-template-compiler": "^2.6.11"
43 | },
44 | "eslintConfig": {
45 | "root": true,
46 | "env": {
47 | "node": true
48 | },
49 | "extends": [
50 | "plugin:vue/essential",
51 | "eslint:recommended"
52 | ],
53 | "parserOptions": {
54 | "parser": "babel-eslint"
55 | },
56 | "rules": {
57 | "generator-star-spacing": "off",
58 | "no-tabs": "off",
59 | "no-unused-vars": "off",
60 | "no-console": "off",
61 | "no-irregular-whitespace": "off",
62 | "no-debugger": "off"
63 | }
64 | },
65 | "files": [
66 | "dist",
67 | "package.json",
68 | "README.md",
69 | "src/i18n/lang"
70 | ],
71 | "browserslist": [
72 | "> 1%",
73 | "last 2 versions"
74 | ],
75 | "author": "ljy",
76 | "license": "ISC",
77 | "repository": {
78 | "type": "git",
79 | "url": "git+https://github.com/jingyuLin1999/echarts-designer"
80 | }
81 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "richform",
3 | "version": "0.11.50",
4 | "private": false,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "build:prod": "vue-cli-service build --target lib --name richform src/components/index.js",
9 | "lint": "vue-cli-service lint"
10 | },
11 | "main": "dist/richform.umd.min.js",
12 | "module": "dist/richform.umd.min.js",
13 | "dependencies": {
14 | "ajv": "^6.12.6",
15 | "ajv-errors": "^1.0.1",
16 | "ajv-i18n": "^3.3.0",
17 | "axios": "^0.21.4",
18 | "core-js": "^3.6.5",
19 | "element-resize-detector": "^1.2.4",
20 | "element-ui": "^2.15.6",
21 | "jquery": "^3.6.0",
22 | "ramda": "^0.27.1",
23 | "vue": "^2.6.11",
24 | "vue-baidu-map": "^0.21.22",
25 | "vue-i18n": "^8.28.2",
26 | "vue-router": "^3.5.2",
27 | "vue-scrollto": "^2.20.0",
28 | "vue2-perfect-scrollbar": "^1.5.0",
29 | "vuedraggable": "^2.24.3",
30 | "vxe-table": "^3.4.15",
31 | "xe-utils": "^3.5.4"
32 | },
33 | "devDependencies": {
34 | "@vue/babel-preset-app": "^5.0.8",
35 | "@vue/cli-plugin-babel": "~4.5.0",
36 | "@vue/cli-plugin-eslint": "~4.5.0",
37 | "@vue/cli-service": "~4.5.0",
38 | "babel-eslint": "^10.1.0",
39 | "babel-polyfill": "^6.26.0",
40 | "es6-promise": "^4.2.8",
41 | "eslint": "^6.7.2",
42 | "eslint-plugin-vue": "^6.2.2",
43 | "node-sass": "^6.0.1",
44 | "sass-loader": "^10.3.1",
45 | "vue-template-compiler": "^2.6.11"
46 | },
47 | "eslintConfig": {
48 | "root": true,
49 | "env": {
50 | "node": true
51 | },
52 | "extends": [
53 | "plugin:vue/essential",
54 | "eslint:recommended"
55 | ],
56 | "parserOptions": {
57 | "parser": "babel-eslint"
58 | },
59 | "rules": {
60 | "generator-star-spacing": "off",
61 | "no-tabs": "off",
62 | "no-unused-vars": "off",
63 | "no-console": "off",
64 | "no-irregular-whitespace": "off",
65 | "no-debugger": "off"
66 | }
67 | },
68 | "files": [
69 | "dist",
70 | "package.json",
71 | "README.md",
72 | "src/i18n/lang"
73 | ],
74 | "browserslist": [
75 | "> 1%",
76 | "last 2 versions"
77 | ],
78 | "author": "ljy",
79 | "license": "ISC",
80 | "repository": {
81 | "type": "git",
82 | "url": "git+https://github.com/jingyuLin1999/richform"
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingyuLin1999/richform/46d4f2445f27aa81c072207b44eed535efdea23e/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | <%= htmlWebpackPlugin.options.title %>
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
14 |
15 |
29 |
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingyuLin1999/richform/46d4f2445f27aa81c072207b44eed535efdea23e/src/assets/logo.png
--------------------------------------------------------------------------------
/src/components/Formdesign/iconfont/iconfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingyuLin1999/richform/46d4f2445f27aa81c072207b44eed535efdea23e/src/components/Formdesign/iconfont/iconfont.ttf
--------------------------------------------------------------------------------
/src/components/Formdesign/iconfont/iconfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingyuLin1999/richform/46d4f2445f27aa81c072207b44eed535efdea23e/src/components/Formdesign/iconfont/iconfont.woff
--------------------------------------------------------------------------------
/src/components/Formdesign/iconfont/iconfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jingyuLin1999/richform/46d4f2445f27aa81c072207b44eed535efdea23e/src/components/Formdesign/iconfont/iconfont.woff2
--------------------------------------------------------------------------------
/src/components/Formdesign/meta/base.js:
--------------------------------------------------------------------------------
1 | export const baseForm = {
2 | border: false, // 显示边框
3 | grid: false, // 表单内部栅栏
4 | labelSuffix: ":", // 字段标题后缀内容,默认' : '
5 | labelWidth: "100px", // 标签宽度,默认50px
6 | validator: "input", // submit
7 | labelAlign: "right", // 标签对齐, 默认右对齐, 可选左对齐left
8 | labelInline: true, // 字段标题显示位置, 默认true左侧left,false显示在top上方
9 | colors: {
10 | btnBgColor: ""
11 | }
12 | }
13 |
14 | export const baseValues = {
15 | title: "",
16 | }
17 |
18 | export const baseLayout = [
19 | {
20 | title: "名称",
21 | name: "name",
22 | size: "small",
23 | widget: "select",
24 | filterable: true,
25 | allowCreate: true,
26 | description: "对应数据库字段",
27 | options: [],
28 | },
29 | {
30 | title: "标题",
31 | name: "title",
32 | size: "small",
33 | widget: "input"
34 | },
35 | {
36 | title: "隐藏",
37 | name: "hideRely",
38 | size: "small",
39 | widget: "draggablelist",
40 | // description: "隐藏依赖设置",
41 | template: "",
42 | default: [],
43 | strAttr: {
44 | widget: "expression",
45 | key: {
46 | title: "字段",
47 | show: true,
48 | order: 1,
49 | options: [],
50 | },
51 | val: {
52 | title: "值",
53 | show: true,
54 | order: 3,
55 | options: [],
56 | },
57 | }
58 | }
59 | ]
60 |
61 | export const baseRules = {
62 | ...baseForm,
63 | layout: [
64 | {
65 | title: "类型",
66 | widget: "select",
67 | name: "type",
68 | size: "small",
69 | options: [
70 | { value: "string", label: "字符串" },
71 | ],
72 | },
73 | ]
74 | }
--------------------------------------------------------------------------------
/src/components/Formdesign/meta/canvas.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | type: "text", // text,textarea
4 | placeholder: "请输入内容",
5 | disabled: false, // 禁用状态
6 | clearable: true, //
7 | showPassword: false, // 密码框
8 | prefixIcon: "", // 当type等于text有效。前置图标 el-icon-search
9 | suffixIcon: "", // 当type等于text有效。后置图标 el-icon-date
10 | rows: 4, // 当type等于textarea有效
11 | autosize: false, // 当type等于textarea有效。根据内容自动设置高度,也可接受一个对象 { minRows: 2, maxRows: 4}
12 | prepend: "", // 当type等于text有效。
13 | append: "", // 当type等于text有效。
14 | size: "", // large、small 和 mini
15 | maxLength: null,
16 | minLength: null,
17 | *
18 | */
19 | import { baseForm, baseLayout } from "./base"
20 | export const attribute = {
21 | schema: {
22 |
23 | },
24 | values: {
25 |
26 | },
27 | form: {
28 | ...baseForm,
29 | layout: [
30 | {
31 | title: "表边框",
32 | widget: "select",
33 | name: "border",
34 | size: "small",
35 | options: [
36 | {
37 | value: true,
38 | label: "是",
39 | },
40 | {
41 | value: false,
42 | label: "否",
43 | },
44 | ],
45 | },
46 | {
47 | title: "表栅栏",
48 | widget: "select",
49 | name: "grid",
50 | size: "small",
51 | options: [
52 | {
53 | value: true,
54 | label: "是",
55 | },
56 | {
57 | value: false,
58 | label: "否",
59 | },
60 | ],
61 | },
62 | {
63 | title: "对齐方式",
64 | widget: "select",
65 | name: "labelAlign",
66 | size: "small",
67 | options: [
68 | {
69 | value: "right",
70 | label: "靠右",
71 | },
72 | {
73 | value: "left",
74 | label: "靠左",
75 | }
76 | ],
77 | },
78 | {
79 | title: "标签后缀",
80 | widget: "input",
81 | name: "labelSuffix",
82 | size: "small",
83 | },
84 | {
85 | title: "标签宽度",
86 | widget: "input",
87 | name: "labelWidth",
88 | size: "small",
89 | },
90 | {
91 | title: "行显示",
92 | widget: "select",
93 | name: "labelInline",
94 | size: "small",
95 | options: [
96 | { value: true, label: "是" },
97 | { value: false, label: "否" }
98 | ],
99 | },
100 | {
101 | widget: "grid",
102 | title: "颜色设置",
103 | showTitle: false,
104 | isClicked: false,
105 | fields: [
106 | [
107 | {
108 | title: "主题",
109 | widget: "colorpicker",
110 | name: "colors.theme",
111 | },
112 | {
113 | title: "按钮字体",
114 | widget: "colorpicker",
115 | name: "colors.btnColor",
116 | },
117 | {
118 | title: "激活字体",
119 | widget: "colorpicker",
120 | name: "colors.activeColor",
121 | },
122 | {
123 | title: "多选选项背景",
124 | widget: "colorpicker",
125 | name: "colors.multiOptionBgColor",
126 | },
127 | ],
128 | [
129 | {
130 | title: "字体",
131 | widget: "colorpicker",
132 | name: "colors.fontColor",
133 | },
134 | {
135 | title: "按钮背景",
136 | widget: "colorpicker",
137 | name: "colors.btnBgColor",
138 | },
139 | {
140 | title: "日期范围背景",
141 | widget: "colorpicker",
142 | name: "colors.dateRangeBgColor",
143 | },
144 | ]
145 | ]
146 | },
147 | // {
148 | // title: "恢复主题",
149 | // widget: "button",
150 | // name: "resetTheme",
151 | // size: "small",
152 | // type: "primary"
153 | // },
154 | ],
155 | }
156 | }
157 |
158 | export const rules = {
159 | schema: {},
160 | values: {
161 | },
162 | form: {
163 | ...baseForm,
164 | layout: []
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/src/components/Formdesign/meta/cascader.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | disabled: false,
4 | placeholder: "",
5 | filterable: true, // 搜索功能
6 | clearable: true,
7 | separator: "/", // 分隔符
8 | showAllLevels: true, // 结果显示所以级别如:a/b/c
9 | propValue: "value",
10 | propLabel: "label",
11 | expandTrigger: "hover", // click / hover
12 | checkStrictly: false, // 父子节点不互相关联
13 | multiple: false, // 可通过 props.multiple = true 来开启多选模
14 | *
15 | */
16 | import { baseForm, baseLayout } from "./base"
17 | export const attribute = {
18 | schema: {
19 |
20 | },
21 | values: {
22 |
23 | },
24 | form: {
25 | ...baseForm,
26 | layout: [
27 | ...baseLayout,
28 | {
29 | title: "触发方式",
30 | widget: "select",
31 | name: "expandTrigger",
32 | size: "small",
33 | options: [
34 | {
35 | value: "hover",
36 | label: "悬停",
37 | },
38 | {
39 | value: "click ",
40 | label: "点击",
41 | },
42 | ],
43 | },
44 | {
45 | title: "标签键值",
46 | widget: "input",
47 | name: "propLabel",
48 | size: "small"
49 | },
50 | {
51 | title: "值键值",
52 | widget: "input",
53 | name: "propValue",
54 | size: "small"
55 | },
56 | {
57 | widget: "grid",
58 | title: "栅格布局",
59 | showTitle: false,
60 | isClicked: false,
61 | fields: [
62 | [
63 | {
64 | name: "clearable",
65 | title: "可清空",
66 | widget: "switch",
67 | width: 40, // 宽度
68 | activeColor: "#13ce66", // 激活背景颜色
69 | inactiveColor: "#ccc", // 取消背景颜色
70 | activeValue: true, // 打开的值,支持Boolean, String或Number
71 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
72 | },
73 | {
74 | name: "filterable",
75 | title: "过滤",
76 | widget: "switch",
77 | width: 40, // 宽度
78 | activeColor: "#13ce66", // 激活背景颜色
79 | inactiveColor: "#ccc", // 取消背景颜色
80 | activeValue: true, // 打开的值,支持Boolean, String或Number
81 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
82 | },
83 | {
84 | name: "multiple",
85 | title: "多选",
86 | widget: "switch",
87 | width: 40, // 宽度
88 | activeColor: "#13ce66", // 激活背景颜色
89 | inactiveColor: "#ccc", // 取消背景颜色
90 | activeValue: true, // 打开的值,支持Boolean, String或Number
91 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
92 | }
93 | ], [
94 | {
95 | name: "disabled",
96 | title: "禁用",
97 | widget: "switch",
98 | width: 40, // 宽度
99 | activeColor: "#13ce66", // 激活背景颜色
100 | inactiveColor: "#ccc", // 取消背景颜色
101 | activeValue: true, // 打开的值,支持Boolean, String或Number
102 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
103 | },
104 | {
105 | name: "showAllLevels",
106 | title: "所有级别",
107 | widget: "switch",
108 | width: 40, // 宽度
109 | activeColor: "#13ce66", // 激活背景颜色
110 | inactiveColor: "#ccc", // 取消背景颜色
111 | activeValue: true, // 打开的值,支持Boolean, String或Number
112 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
113 | },
114 | {
115 | name: "checkStrictly",
116 | title: "严格模式",
117 | widget: "switch",
118 | width: 40, // 宽度
119 | activeColor: "#13ce66", // 激活背景颜色
120 | inactiveColor: "#ccc", // 取消背景颜色
121 | activeValue: true, // 打开的值,支持Boolean, String或Number
122 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
123 | },
124 | ]
125 | ]
126 | },
127 | {
128 | title: "分隔符",
129 | widget: "input",
130 | name: "separator",
131 | size: "small",
132 | hideRely: "showAllLevels==false",
133 | },
134 | {
135 | title: "数据配置",
136 | widget: "tree",
137 | name: "options",
138 | addSibling: true,
139 | editable: true,
140 | deletable: true,
141 | addable: true,
142 | draggable: true, // 开启拖拽
143 | isShowIcon: false,
144 | showAddTemplate: true,
145 | },
146 | ],
147 | }
148 | }
149 |
150 | export const rules = {
151 | schema: {},
152 | values: {},
153 | form: {
154 | ...baseForm,
155 | layout: []
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/src/components/Formdesign/meta/checkbox.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | isGroup: false, // 为true时,options有效即多选框组生效,value必须为array
4 | isButton: false, // 功能:指明多选框组为按钮形式
5 | max: 10000, // 生效:多选框组 功能:规定可以选择的范围
6 | min: 0, // 生效:多选框组 功能:规定可以选择的范围
7 | disabled: false, // 生效:多选框组或单个 说明:优先级高于子checkbox
8 | border: false,
9 | size: "", // medium / small / mini 说明:仅对按钮形式或带有边框的Checkbox有效
10 | textColor: "#ffffff", // 按钮有效
11 | fill: "#409EFF", // 按钮有效
12 | chooseAll: false,
13 | *
14 | */
15 | import { baseForm, baseLayout } from "./base"
16 | export const attribute = {
17 | schema: {
18 |
19 | },
20 | values: {
21 |
22 | },
23 | form: {
24 | ...baseForm,
25 | layout: [
26 | ...baseLayout,
27 | {
28 | title: "尺寸",
29 | widget: "select",
30 | name: "size",
31 | size: "small",
32 | options: [
33 | {
34 | value: "medium",
35 | label: "大",
36 | },
37 | {
38 | value: "small ",
39 | label: "中",
40 | },
41 | {
42 | value: "mini",
43 | label: "小",
44 | },
45 | ],
46 | },
47 | {
48 | title: "选项",
49 | widget: "draggablelist",
50 | name: "options",
51 | template: { title: "", name: "" },
52 | attribute: {
53 | title: { widget: "input", placeholder: "", editable: true },
54 | name: { widget: "input", placeholder: "", editable: true },
55 | },
56 | default: []
57 | },
58 | {
59 | widget: "grid",
60 | title: "栅格布局",
61 | showTitle: false,
62 | isClicked: false,
63 | fields: [
64 | [
65 | {
66 | name: "isGroup",
67 | title: "多选框组",
68 | widget: "switch",
69 | width: 40, // 宽度
70 | activeColor: "#13ce66", // 激活背景颜色
71 | inactiveColor: "#ccc", // 取消背景颜色
72 | activeValue: true, // 打开的值,支持Boolean, String或Number
73 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
74 | },
75 | {
76 | name: "disabled",
77 | title: "禁用",
78 | widget: "switch",
79 | width: 40, // 宽度
80 | activeColor: "#13ce66", // 激活背景颜色
81 | inactiveColor: "#ccc", // 取消背景颜色
82 | activeValue: true, // 打开的值,支持Boolean, String或Number
83 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
84 | },
85 | {
86 | title: "字体颜色",
87 | widget: "colorpicker",
88 | name: "textColor",
89 | hideRely: "isButton==false",
90 | },
91 | ], [
92 | {
93 | name: "isButton",
94 | title: "按钮",
95 | widget: "switch",
96 | width: 40, // 宽度
97 | activeColor: "#13ce66", // 激活背景颜色
98 | inactiveColor: "#ccc", // 取消背景颜色
99 | activeValue: true, // 打开的值,支持Boolean, String或Number
100 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
101 | },
102 | {
103 | name: "border",
104 | title: "边界",
105 | widget: "switch",
106 | width: 40, // 宽度
107 | activeColor: "#13ce66", // 激活背景颜色
108 | inactiveColor: "#ccc", // 取消背景颜色
109 | activeValue: true, // 打开的值,支持Boolean, String或Number
110 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
111 | },
112 | {
113 | title: "填充颜色",
114 | widget: "colorpicker",
115 | name: "fill",
116 | hideRely: "isButton==false",
117 | },
118 | ]
119 | ]
120 | },
121 | ],
122 | }
123 | }
124 |
125 | export const rules = {
126 | schema: {},
127 | values: {
128 |
129 | },
130 | form: {
131 | ...baseForm,
132 | layout: [
133 |
134 | ]
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/src/components/Formdesign/meta/collapse.js:
--------------------------------------------------------------------------------
1 | import { baseForm, baseLayout } from "./base"
2 | export const attribute = {
3 | schema: {
4 |
5 | },
6 | values: {
7 |
8 | },
9 | form: {
10 | ...baseForm,
11 | layout: [
12 | {
13 | title: "标题",
14 | name: "title",
15 | size: "small",
16 | widget: "input"
17 | },
18 | ],
19 | }
20 | }
21 |
22 | export const rules = {
23 | schema: {},
24 | values: {},
25 | form: {
26 | ...baseForm
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/components/Formdesign/meta/colorpicker.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | predefineColors: ["#409EFF", "#f00"], // 预定义颜色
4 | disabled: false,
5 | size: "small", // 选项: medium / small / mini
6 | showAlpha: false,
7 | popperClass: "",
8 | colorFormat: "", //单位选项:hsl / hsv / hex / rgb 说明:写入 v-model 的颜色的格式
9 | defaultColor: "#1278F6",
10 | *
11 | */
12 | import { baseForm, baseLayout } from "./base"
13 | export const attribute = {
14 | schema: {
15 |
16 | },
17 | values: {
18 |
19 | },
20 | form: {
21 | ...baseForm,
22 | layout: [
23 | ...baseLayout,
24 | {
25 | title: "单位", // 优先级小于shema中定义的title
26 | widget: "select",
27 | name: "selectMultiple",
28 | filterable: true,
29 | size: "small",
30 | options: [
31 | {
32 | value: "hsl",
33 | label: "hsl",
34 | },
35 | {
36 | value: "hsv",
37 | label: "hsv",
38 | },
39 | {
40 | value: "hex",
41 | label: "hex",
42 | },
43 | {
44 | value: "rgb",
45 | label: "rgb",
46 | },
47 | ],
48 | },
49 | {
50 | title: "默认颜色",
51 | widget: "colorpicker",
52 | name: "default",
53 | default: "#f00"
54 | },
55 | {
56 | widget: "grid",
57 | title: "栅格布局",
58 | showTitle: false,
59 | isClicked: false,
60 | fields: [
61 | [
62 | {
63 | name: "disabled",
64 | title: "禁用",
65 | widget: "switch",
66 | width: 40, // 宽度
67 | activeColor: "#13ce66", // 激活背景颜色
68 | inactiveColor: "#ccc", // 取消背景颜色
69 | activeValue: true, // 打开的值,支持Boolean, String或Number
70 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
71 | }
72 | ], [
73 | {
74 | name: "showAlpha",
75 | title: "透明度",
76 | widget: "switch",
77 | width: 40, // 宽度
78 | activeColor: "#13ce66", // 激活背景颜色
79 | inactiveColor: "#ccc", // 取消背景颜色
80 | activeValue: true, // 打开的值,支持Boolean, String或Number
81 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
82 | }
83 | ]
84 | ]
85 | },
86 | ],
87 | }
88 | }
89 |
90 | export const rules = {
91 | schema: {},
92 | values: {
93 | type: "string",
94 | },
95 | form: {
96 | ...baseForm,
97 | layout: [
98 |
99 | ]
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/src/components/Formdesign/meta/datetimepicker.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | title: "日期选择器",
4 | type: "daterange", // year/month/date/dates/ week/datetime/datetimerange/daterange/monthrange
5 | readOnly: false,
6 | disabled: false,
7 | clearable: true, // 是否显示清除按钮
8 | size: "", // medium / small / mini
9 | editable: false, // 文本框可输入
10 | placeholder: "请选择", // 单个
11 | format: "", // 显示的格式,注意和type配套
12 | valueFormat: "yyyy-MM-dd", // yyyy-MM-dd/timestamp 指定值的格式
13 | arrowControl: true,
14 | rangeSeparator: "至", // 选择范围时的分隔符
15 | startPlaceholder: "开始时间",
16 | endPlaceholder: "结束时间",
17 | pickerOptions: {},
18 | *
19 | */
20 | import { baseForm, baseLayout } from "./base"
21 | export const attribute = {
22 | schema: {
23 |
24 | },
25 | values: {
26 |
27 | },
28 | form: {
29 | ...baseForm,
30 | layout: [
31 | ...baseLayout,
32 | {
33 | title: "类型",
34 | widget: "select",
35 | name: "type",
36 | size: "small",
37 | options: [
38 | {
39 | value: "year",
40 | label: "年",
41 | },
42 | {
43 | value: "month",
44 | label: "月",
45 | },
46 | {
47 | value: "date",
48 | label: "日期",
49 | },
50 | {
51 | value: "dates",
52 | label: "多个日期",
53 | },
54 | {
55 | value: "week",
56 | label: "星期",
57 | },
58 | {
59 | value: "datetime",
60 | label: "日期时间",
61 | },
62 | {
63 | value: "datetimerange",
64 | label: "日期时间范围",
65 | },
66 | {
67 | value: "daterange",
68 | label: "日期范围",
69 | },
70 | {
71 | value: "monthrange",
72 | label: "月份范围",
73 | },
74 | ],
75 | },
76 | {
77 | title: "尺寸",
78 | widget: "select",
79 | name: "size",
80 | size: "small",
81 | options: [
82 | {
83 | value: "medium",
84 | label: "大",
85 | },
86 | {
87 | value: "small ",
88 | label: "中",
89 | },
90 | {
91 | value: "mini",
92 | label: "小",
93 | },
94 | ],
95 | },
96 | {
97 | title: "占位符",
98 | name: "placeholder",
99 | size: "small",
100 | widget: "input"
101 | },
102 | {
103 | widget: "input",
104 | title: "开始占位符",
105 | name: "startPlaceholder",
106 | size: "small"
107 | },
108 | {
109 | widget: "input",
110 | title: "结束占位符",
111 | name: "endPlaceholder",
112 | size: "small"
113 | },
114 | {
115 | widget: "input",
116 | title: "分隔符",
117 | name: "rangeSeparator",
118 | size: "small"
119 | },
120 | {
121 | widget: "grid",
122 | title: "栅格布局",
123 | showTitle: false,
124 | isClicked: false,
125 | fields: [
126 | [
127 | {
128 | name: "readOnly",
129 | title: "只读",
130 | widget: "switch",
131 | width: 40, // 宽度
132 | activeColor: "#13ce66", // 激活背景颜色
133 | inactiveColor: "#ccc", // 取消背景颜色
134 | activeValue: true, // 打开的值,支持Boolean, String或Number
135 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
136 | hideRely: "type==textarea",
137 | },
138 | {
139 | name: "clearable",
140 | title: "可清除",
141 | widget: "switch",
142 | width: 40, // 宽度
143 | activeColor: "#13ce66", // 激活背景颜色
144 | inactiveColor: "#ccc", // 取消背景颜色
145 | activeValue: true, // 打开的值,支持Boolean, String或Number
146 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
147 | hideRely: "type==textarea",
148 | }
149 | ], [
150 | {
151 | name: "disabled",
152 | title: "禁用",
153 | widget: "switch",
154 | width: 40, // 宽度
155 | activeColor: "#13ce66", // 激活背景颜色
156 | inactiveColor: "#ccc", // 取消背景颜色
157 | activeValue: true, // 打开的值,支持Boolean, String或Number
158 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
159 | hideRely: "type==textarea",
160 | },
161 | {
162 | name: "arrowControl",
163 | title: "箭头",
164 | widget: "switch",
165 | width: 40, // 宽度
166 | activeColor: "#13ce66", // 激活背景颜色
167 | inactiveColor: "#ccc", // 取消背景颜色
168 | activeValue: true, // 打开的值,支持Boolean, String或Number
169 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
170 | hideRely: "type==textarea",
171 | }
172 | ]
173 | ]
174 | },
175 | ],
176 | }
177 | }
178 |
179 | export const rules = {
180 | schema: {},
181 | values: {
182 | },
183 | form: {
184 | ...baseForm,
185 | layout: []
186 | }
187 | }
188 |
--------------------------------------------------------------------------------
/src/components/Formdesign/meta/grid.js:
--------------------------------------------------------------------------------
1 | import { baseForm, baseLayout } from "./base"
2 | export const attribute = {
3 | schema: {
4 |
5 | },
6 | values: {
7 |
8 | },
9 | form: {
10 | ...baseForm,
11 | layout: [
12 | ...baseLayout,
13 | {
14 | title: "比例",
15 | name: "ratio",
16 | widget: "input",
17 | description: "和列数对应,中间用英文字符:隔开",
18 | size: "small",
19 | placeholder: "如: 1:1"
20 | },
21 | {
22 | title: "列数",
23 | name: "fields",
24 | widget: "draggablelist",
25 | template: []
26 | },
27 | ],
28 | }
29 | }
30 |
31 | export const rules = {
32 | schema: {},
33 | values: {
34 |
35 | },
36 | form: {
37 | ...baseForm,
38 | layout: [
39 |
40 | ]
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/components/Formdesign/meta/icon.js:
--------------------------------------------------------------------------------
1 | import { baseForm, baseLayout } from "./base"
2 | export const attribute = {
3 | schema: {
4 |
5 | },
6 | values: {},
7 | form: {
8 | ...baseForm,
9 | layout: [
10 | ...baseLayout,
11 | {
12 | title: "尺寸",
13 | widget: "select",
14 | name: "size",
15 | size: "small",
16 | options: [
17 | {
18 | value: "medium",
19 | label: "大",
20 | },
21 | {
22 | value: "small ",
23 | label: "中",
24 | },
25 | {
26 | value: "mini",
27 | label: "小",
28 | },
29 | ],
30 | },
31 | {
32 | title: "禁用",
33 | widget: "select",
34 | name: "disabled",
35 | size: "small",
36 | options: [
37 | {
38 | value: true,
39 | label: "是",
40 | },
41 | {
42 | value: false,
43 | label: "否",
44 | }
45 | ],
46 | },
47 | {
48 | title: "字体大小",
49 | widget: "input",
50 | name: "fontSize",
51 | size: "small"
52 | },
53 | ],
54 | }
55 | }
56 |
57 | export const rules = {
58 | schema: {},
59 | values: {},
60 | form: {
61 | ...baseForm,
62 | layout: []
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/components/Formdesign/meta/input.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | type: "text", // text,textarea
4 | placeholder: "请输入内容",
5 | disabled: false, // 禁用状态
6 | clearable: true, //
7 | showPassword: false, // 密码框
8 | prefixIcon: "", // 当type等于text有效。前置图标 el-icon-search
9 | suffixIcon: "", // 当type等于text有效。后置图标 el-icon-date
10 | rows: 4, // 当type等于textarea有效
11 | autosize: false, // 当type等于textarea有效。根据内容自动设置高度,也可接受一个对象 { minRows: 2, maxRows: 4}
12 | prepend: "", // 当type等于text有效。
13 | append: "", // 当type等于text有效。
14 | size: "", // large、small 和 mini
15 | maxLength: null,
16 | minLength: null,
17 | *
18 | */
19 | import { baseForm, baseLayout } from "./base"
20 | export const attribute = {
21 | schema: {
22 |
23 | },
24 | values: {
25 |
26 | },
27 | form: {
28 | ...baseForm,
29 | layout: [
30 | ...baseLayout,
31 | {
32 | title: "占位符",
33 | name: "placeholder",
34 | size: "small",
35 | widget: "input"
36 | },
37 | {
38 | title: "类型",
39 | widget: "select",
40 | name: "type",
41 | size: "small",
42 | options: [
43 | {
44 | value: "text",
45 | label: "文本",
46 | },
47 | {
48 | value: "textarea",
49 | label: "多行文本框",
50 | },
51 | ],
52 | },
53 | {
54 | title: "尺寸",
55 | widget: "select",
56 | name: "size",
57 | size: "small",
58 | options: [
59 | {
60 | value: "medium",
61 | label: "大",
62 | },
63 | {
64 | value: "small ",
65 | label: "中",
66 | },
67 | {
68 | value: "mini",
69 | label: "小",
70 | },
71 | ],
72 | },
73 | {
74 | title: "禁用",
75 | widget: "select",
76 | name: "disabled",
77 | size: "small",
78 | options: [
79 | {
80 | value: true,
81 | label: "是",
82 | },
83 | {
84 | value: false,
85 | label: "否",
86 | }
87 | ],
88 | },
89 | {
90 | widget: "grid",
91 | title: "栅格布局",
92 | showTitle: false,
93 | isClicked: false,
94 | fields: [
95 | [
96 | {
97 | name: "clearable",
98 | title: "可清空",
99 | widget: "switch",
100 | width: 40, // 宽度
101 | activeColor: "#13ce66", // 激活背景颜色
102 | inactiveColor: "#ccc", // 取消背景颜色
103 | activeValue: true, // 打开的值,支持Boolean, String或Number
104 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
105 | hideRely: "type==textarea",
106 | }
107 | ], [
108 | {
109 | name: "showPassword",
110 | title: "密码框",
111 | widget: "switch",
112 | width: 40, // 宽度
113 | activeColor: "#13ce66", // 激活背景颜色
114 | inactiveColor: "#ccc", // 取消背景颜色
115 | activeValue: true, // 打开的值,支持Boolean, String或Number
116 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
117 | hideRely: "type==textarea",
118 | }
119 | ]
120 | ]
121 | },
122 | ],
123 | }
124 | }
125 |
126 | export const rules = {
127 | schema: {},
128 | values: {
129 | type: "string",
130 | },
131 | form: {
132 | ...baseForm,
133 | layout: [
134 | {
135 | title: "类型",
136 | widget: "select",
137 | name: "type",
138 | size: "small",
139 | options: [
140 | {
141 | value: "string",
142 | label: "字符串",
143 | },
144 | {
145 | value: "number",
146 | label: "数字",
147 | },
148 | ],
149 | },
150 | {
151 | title: "最小值",
152 | name: "minimum",
153 | widget: "inputnumber",
154 | step: 1, // 步数
155 | min: 0,
156 | default: 0,
157 | stepStrictly: false, // 严格步数,只能输入 step 的倍数
158 | precision: undefined, // 精度,设置计数器最小值
159 | controlsPosition: "", // 按钮位置。计数器增减按钮的位置, 默认"", 可设置为 "right"
160 | size: "mini",
161 | hideRely: "type==string",
162 | },
163 | {
164 | title: "最大值",
165 | name: "maximum",
166 | widget: "inputnumber",
167 | step: 1, // 步数
168 | min: 0,
169 | default: 255,
170 | stepStrictly: false, // 严格步数,只能输入 step 的倍数
171 | precision: undefined, // 精度,设置计数器最小值
172 | controlsPosition: "", // 按钮位置。计数器增减按钮的位置, 默认"", 可设置为 "right"
173 | size: "mini",
174 | hideRely: "type==string",
175 | },
176 | {
177 | title: "最小长度",
178 | name: "minLength",
179 | widget: "inputnumber",
180 | step: 1, // 步数
181 | min: 0,
182 | max: 255,
183 | default: 0,
184 | stepStrictly: false, // 严格步数,只能输入 step 的倍数
185 | precision: undefined, // 精度,设置计数器最小值
186 | controlsPosition: "", // 按钮位置。计数器增减按钮的位置, 默认"", 可设置为 "right"
187 | size: "mini",
188 | hideRely: "type==number",
189 | },
190 | {
191 | title: "最大长度",
192 | name: "maxLength",
193 | widget: "inputnumber",
194 | step: 1, // 步数
195 | min: 0,
196 | max: 255,
197 | default: 255,
198 | stepStrictly: false, // 严格步数,只能输入 step 的倍数
199 | precision: undefined, // 精度,设置计数器最小值
200 | controlsPosition: "", // 按钮位置。计数器增减按钮的位置, 默认"", 可设置为 "right"
201 | size: "mini",
202 | hideRely: "type==number",
203 | },
204 |
205 | ]
206 | }
207 | }
208 |
--------------------------------------------------------------------------------
/src/components/Formdesign/meta/inputnumber.js:
--------------------------------------------------------------------------------
1 | /**
2 | disabled: false,
3 | step: 1, // 步数
4 | min: undefined,
5 | max: undefined,
6 | stepStrictly: false, // 严格步数,只能输入 step 的倍数
7 | precision: undefined, // 精度,设置计数器最小值
8 | controlsPosition: "", // 按钮位置。计数器增减按钮的位置, 默认"", 可设置为 "right"
9 | size: "",
10 | */
11 |
12 | import { baseForm, baseLayout } from "./base";
13 |
14 | export const attribute = {
15 | values: {
16 | step: 1,
17 | min: 0,
18 | max: 256,
19 | disabled: false,
20 | },
21 | form: {
22 | ...baseForm,
23 | layout: [
24 | ...baseLayout,
25 | {
26 | title: "尺寸",
27 | widget: "select",
28 | name: "size",
29 | size: "small",
30 | options: [
31 | {
32 | value: "medium",
33 | label: "大",
34 | },
35 | {
36 | value: "small ",
37 | label: "中",
38 | },
39 | {
40 | value: "mini",
41 | label: "小",
42 | },
43 | ],
44 | },
45 | {
46 | title: "按钮位置",
47 | widget: "select",
48 | name: "controlsPosition",
49 | size: "small",
50 | options: [
51 | {
52 | value: "",
53 | label: "默认",
54 | },
55 | {
56 | value: "right",
57 | label: "右边",
58 | },
59 | ],
60 | },
61 | {
62 | title: "禁用",
63 | widget: "select",
64 | name: "disabled",
65 | size: "small",
66 | options: [
67 | {
68 | value: true,
69 | label: "是",
70 | },
71 | {
72 | value: false,
73 | label: "否",
74 | },
75 | ],
76 | },
77 | {
78 | name: "step",
79 | title: "步经",
80 | widget: "inputnumber",
81 | step: 1,
82 | controlsPosition: "",
83 | size: "small",
84 | },
85 | {
86 | name: "min",
87 | title: "最小",
88 | widget: "inputnumber",
89 | step: 1,
90 | controlsPosition: "",
91 | size: "small",
92 | },
93 | {
94 | name: "max",
95 | title: "最大",
96 | widget: "inputnumber",
97 | step: 1,
98 | controlsPosition: "",
99 | size: "small",
100 | },
101 | // {
102 | // name: "stepStrictly",
103 | // title: "严格步经",
104 | // widget: "switch",
105 | // description: "只能输入 步经 的倍数"
106 | // },
107 | ],
108 | }
109 | }
110 |
111 | export const rules = {
112 | schema: {},
113 | values: {},
114 | form: {
115 | ...baseForm,
116 | layout: [
117 | {
118 | title: "最小值",
119 | name: "minimum",
120 | widget: "inputnumber",
121 | step: 1, // 步数
122 | min: 0,
123 | default: 0,
124 | stepStrictly: false, // 严格步数,只能输入 step 的倍数
125 | precision: undefined, // 精度,设置计数器最小值
126 | controlsPosition: "", // 按钮位置。计数器增减按钮的位置, 默认"", 可设置为 "right"
127 | size: "mini",
128 | },
129 | {
130 | title: "最大值",
131 | name: "maximum",
132 | widget: "inputnumber",
133 | step: 1, // 步数
134 | min: 0,
135 | default: 255,
136 | stepStrictly: false, // 严格步数,只能输入 step 的倍数
137 | precision: undefined, // 精度,设置计数器最小值
138 | controlsPosition: "", // 按钮位置。计数器增减按钮的位置, 默认"", 可设置为 "right"
139 | size: "mini",
140 | },
141 | ]
142 | }
143 | }
--------------------------------------------------------------------------------
/src/components/Formdesign/meta/ipinput.js:
--------------------------------------------------------------------------------
1 | import { baseForm, baseLayout } from "./base"
2 | export const attribute = {
3 | schema: {
4 |
5 | },
6 | values: {
7 |
8 | },
9 | form: {
10 | ...baseForm,
11 | layout: [
12 | ...baseLayout,
13 | // {
14 | // title: "前置内容",
15 | // name: "prepend",
16 | // size: "small",
17 | // widget: "input"
18 | // },
19 | // {
20 | // title: "后置内容",
21 | // name: "append",
22 | // size: "small",
23 | // widget: "input"
24 | // },
25 | ],
26 | }
27 | }
28 |
29 | export const rules = {
30 | schema: {},
31 | values: {},
32 | form: {
33 | ...baseForm,
34 | layout: []
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/components/Formdesign/meta/radio.js:
--------------------------------------------------------------------------------
1 | /**
2 | isGroup: true,
3 | isButton: false,
4 | disabled: true,
5 | border: false,
6 | size: "", // medium / small / mini
7 | textColor: "", // 当isButton为true时有效
8 | fill: "", // 当isButton为true时有效
9 | */
10 |
11 | import { baseForm, baseLayout } from "./base";
12 |
13 | export const attribute = {
14 | values: {},
15 | form: {
16 | ...baseForm,
17 | layout: [
18 | ...baseLayout,
19 | {
20 | title: "尺寸",
21 | widget: "select",
22 | name: "size",
23 | size: "small",
24 | options: [
25 | {
26 | value: "medium",
27 | label: "大",
28 | },
29 | {
30 | value: "small ",
31 | label: "中",
32 | },
33 | {
34 | value: "mini",
35 | label: "小",
36 | },
37 | ],
38 | },
39 | {
40 | title: "选项",
41 | widget: "draggablelist",
42 | name: "options",
43 | template: { title: "", name: "" },
44 | attribute: {
45 | title: { widget: "input", placeholder: "", editable: true },
46 | name: { widget: "input", placeholder: "", editable: true },
47 | },
48 | },
49 | {
50 | widget: "grid",
51 | showTitle: false,
52 | isClicked: false,
53 | fields: [
54 | [
55 | {
56 | name: "isButton",
57 | title: "按钮",
58 | widget: "switch",
59 | width: 40, // 宽度
60 | activeColor: "#13ce66", // 激活背景颜色
61 | inactiveColor: "#ccc", // 取消背景颜色
62 | activeValue: true, // 打开的值,支持Boolean, String或Number
63 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
64 | },
65 | {
66 | name: "border",
67 | title: "边框",
68 | widget: "switch",
69 | width: 40, // 宽度
70 | activeColor: "#13ce66", // 激活背景颜色
71 | inactiveColor: "#ccc", // 取消背景颜色
72 | activeValue: true, // 打开的值,支持Boolean, String或Number
73 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
74 | }
75 | ],
76 | [
77 | {
78 | name: "isGroup",
79 | title: "分组",
80 | widget: "switch",
81 | width: 40, // 宽度
82 | activeColor: "#13ce66", // 激活背景颜色
83 | inactiveColor: "#ccc", // 取消背景颜色
84 | activeValue: true, // 打开的值,支持Boolean, String或Number
85 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
86 | },
87 | {
88 | name: "disabled",
89 | title: "禁用",
90 | widget: "switch",
91 | width: 40, // 宽度
92 | activeColor: "#13ce66", // 激活背景颜色
93 | inactiveColor: "#ccc", // 取消背景颜色
94 | activeValue: true, // 打开的值,支持Boolean, String或Number
95 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
96 | }
97 | ],
98 | ]
99 | }
100 | ],
101 | }
102 | }
103 |
104 | export const rules = {
105 | schema: {},
106 | values: {},
107 | form: {
108 | ...baseForm,
109 | layout: [
110 | {
111 | title: "类型",
112 | widget: "select",
113 | name: "type",
114 | size: "small",
115 | default: "string",
116 | options: [
117 | {
118 | value: "string",
119 | label: "字符串",
120 | },
121 | {
122 | value: "number",
123 | label: "数字",
124 | },
125 | ],
126 | },
127 | ]
128 | }
129 | }
--------------------------------------------------------------------------------
/src/components/Formdesign/meta/rate.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | disabled: false,
4 | colors: ["#99A9BF", "#F7BA2A", "#FF9900"], // 等同于 { 2: '#99A9BF', 4: { value: '#F7BA2A', excluded: true }, 5: '#FF9900' }
5 | showText: false,
6 | texts: ["极差", "失望", "一般", "满意", "惊喜"], // 1、showText为true有效 2、数组长度要和max对应
7 | showScore: false, // texts优先级大于texts
8 | textColor: "#ff9900", // 字体颜色
9 | max: 5, // 最大分值,即有几个星星
10 | allowHalf: false, // 是否允许半选
11 | scoreTemplate: `${this.value}`, // 显示模板,优先级大于value,默认等于value
12 | lowThreshold: 2,
13 | highThreshold: 4,
14 | *
15 | */
16 | import { baseForm, baseLayout } from "./base"
17 | export const attribute = {
18 | schema: {
19 |
20 | },
21 | values: {
22 |
23 | },
24 | form: {
25 | ...baseForm,
26 | layout: [
27 | ...baseLayout,
28 | {
29 | name: "max",
30 | title: "最大分值",
31 | widget: "inputnumber",
32 | },
33 | {
34 | name: "showText",
35 | title: "显示文本",
36 | widget: "switch",
37 | width: 40, // 宽度
38 | activeColor: "#13ce66", // 激活背景颜色
39 | inactiveColor: "#ccc", // 取消背景颜色
40 | activeValue: true, // 打开的值,支持Boolean, String或Number
41 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
42 | },
43 | {
44 | title: "选项",
45 | widget: "draggablelist",
46 | name: "texts",
47 | template: "",
48 | default: [],
49 | hideRely: "showText==false",
50 | description: "个数和最大分值对应"
51 | },
52 | {
53 | widget: "grid",
54 | title: "栅格布局",
55 | showTitle: false,
56 | isClicked: false,
57 | fields: [
58 | [
59 | {
60 | name: "allowHalf",
61 | title: "半选",
62 | widget: "switch",
63 | width: 40, // 宽度
64 | activeColor: "#13ce66", // 激活背景颜色
65 | inactiveColor: "#ccc", // 取消背景颜色
66 | activeValue: true, // 打开的值,支持Boolean, String或Number
67 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
68 | },
69 | ], [
70 | {
71 | name: "disabled",
72 | title: "禁用",
73 | widget: "switch",
74 | width: 40, // 宽度
75 | activeColor: "#13ce66", // 激活背景颜色
76 | inactiveColor: "#ccc", // 取消背景颜色
77 | activeValue: true, // 打开的值,支持Boolean, String或Number
78 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
79 | },
80 | ]
81 | ]
82 | },
83 | ],
84 | }
85 | }
86 |
87 | export const rules = {
88 | schema: {},
89 | values: {
90 |
91 | },
92 | form: {
93 | ...baseForm,
94 | layout: [
95 |
96 | ]
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/components/Formdesign/meta/select.js:
--------------------------------------------------------------------------------
1 | /**
2 |
3 | isGroup: false, // 是否分组
4 | placeholder: "请选择",
5 | size: "",
6 | disabled: false, // 说明:当该属性在字典中,则禁用对应的选项。若在field.disable则禁用整个选择器
7 | clearable: false, // 说明:可清空选项 注意:仅单选有效
8 | multiple: false, // 说明:是否支持多选
9 | collapseTags: false, // 多选用tags显示
10 | filterable: false, // 说明:搜索label
11 | allowCreate: false, // 说明:是否允许创建条目,谨慎使用 注意:filterable为true时有效
12 | */
13 |
14 | import { baseForm, baseLayout } from "./base";
15 |
16 | export const attribute = {
17 | schema: {},
18 | values: {
19 | // type: "string"
20 | },
21 | form: {
22 | ...baseForm,
23 | layout: [
24 | ...baseLayout,
25 | {
26 | title: "占位符",
27 | name: "placeholder",
28 | size: "small",
29 | widget: "input"
30 | },
31 | {
32 | title: "尺寸",
33 | widget: "select",
34 | name: "size",
35 | size: "small",
36 | options: [
37 | {
38 | value: "medium",
39 | label: "大",
40 | },
41 | {
42 | value: "small ",
43 | label: "中",
44 | },
45 | {
46 | value: "mini",
47 | label: "小",
48 | },
49 | ],
50 | },
51 | {
52 | title: "选项",
53 | widget: "draggablelist",
54 | name: "options",
55 | default: []
56 | },
57 | {
58 | widget: "grid",
59 | showTitle: false,
60 | isClicked: false,
61 | fields: [
62 | [
63 | {
64 | name: "isGroup",
65 | title: "分组",
66 | widget: "switch",
67 | width: 40, // 宽度
68 | activeColor: "#13ce66", // 激活背景颜色
69 | inactiveColor: "#ccc", // 取消背景颜色
70 | activeValue: true, // 打开的值,支持Boolean, String或Number
71 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
72 | description: "分组option结构特殊,具体请见element"
73 | }
74 | ], [
75 | {
76 | name: "disabled",
77 | title: "禁用",
78 | widget: "switch",
79 | width: 40, // 宽度
80 | activeColor: "#13ce66", // 激活背景颜色
81 | inactiveColor: "#ccc", // 取消背景颜色
82 | activeValue: true, // 打开的值,支持Boolean, String或Number
83 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
84 | }
85 | ]
86 | ]
87 | },
88 | {
89 | widget: "grid",
90 | showTitle: false,
91 | isClicked: false,
92 | fields: [
93 | [
94 | {
95 | name: "clearable",
96 | title: "可清空",
97 | widget: "switch",
98 | width: 40, // 宽度
99 | activeColor: "#13ce66", // 激活背景颜色
100 | inactiveColor: "#ccc", // 取消背景颜色
101 | activeValue: true, // 打开的值,支持Boolean, String或Number
102 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
103 | }
104 | ], [
105 | {
106 | name: "multiple",
107 | title: "多选",
108 | widget: "switch",
109 | width: 40, // 宽度
110 | activeColor: "#13ce66", // 激活背景颜色
111 | inactiveColor: "#ccc", // 取消背景颜色
112 | activeValue: true, // 打开的值,支持Boolean, String或Number
113 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
114 | hideRely: "type==string"
115 | }
116 | ]
117 | ]
118 | },
119 | ],
120 | }
121 | }
122 |
123 | export const rules = {
124 | schema: {},
125 | values: {
126 | type: "string"
127 | },
128 | form: {
129 | ...baseForm,
130 | layout: [
131 | {
132 | title: "类型",
133 | widget: "select",
134 | name: "type",
135 | size: "small",
136 | options: [
137 | {
138 | value: "string",
139 | label: "字符串",
140 | },
141 | {
142 | value: "array",
143 | label: "数组",
144 | },
145 | ],
146 | },
147 | {
148 | title: "最小长度",
149 | name: "minLength",
150 | widget: "inputnumber",
151 | step: 1, // 步数
152 | min: undefined,
153 | max: undefined,
154 | stepStrictly: false, // 严格步数,只能输入 step 的倍数
155 | precision: undefined, // 精度,设置计数器最小值
156 | controlsPosition: "", // 按钮位置。计数器增减按钮的位置, 默认"", 可设置为 "right"
157 | size: "mini",
158 | }
159 | ]
160 | }
161 | }
--------------------------------------------------------------------------------
/src/components/Formdesign/meta/slider.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | disabled: false,
4 | showTooltip: true,
5 | step: 1, // 步长
6 | minimum: 1, // 最小值
7 | maximum: 10, // 最大值
8 | showStop: false, // 显示间断点
9 | showInput: false, // 是否显示输入框,仅在非范围选择时有效
10 | inputSize: "", // large / medium / small / mini
11 | showInputControls: false, // 在显示输入框的情况下,是否显示输入框的控制按钮
12 | showRange: false, // 是否为范围选择,此时value必须为 [2,58]
13 | vertical: false,
14 | marks: {},
15 | height: "200px", // vertical 为true时,必须设置高度
16 | *
17 | */
18 | import { baseForm, baseLayout } from "./base"
19 | export const attribute = {
20 | schema: {
21 |
22 | },
23 | values: {
24 |
25 | },
26 | form: {
27 | ...baseForm,
28 | layout: [
29 | ...baseLayout,
30 | {
31 | title: "步长",
32 | widget: "inputnumber",
33 | name: "step",
34 | step: 1,
35 | default: 1,
36 | },
37 | {
38 | title: "最小值",
39 | widget: "inputnumber",
40 | name: "minimum",
41 | step: 1,
42 | },
43 | {
44 | title: "最大值",
45 | widget: "inputnumber",
46 | name: "maximum",
47 | step: 1,
48 | },
49 | {
50 | widget: "grid",
51 | title: "栅格布局",
52 | showTitle: false,
53 | isClicked: false,
54 | fields: [
55 | [
56 | {
57 | name: "disabled",
58 | title: "禁用",
59 | widget: "switch",
60 | width: 40, // 宽度
61 | activeColor: "#13ce66", // 激活背景颜色
62 | inactiveColor: "#ccc", // 取消背景颜色
63 | activeValue: true, // 打开的值,支持Boolean, String或Number
64 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
65 | }
66 | ], [
67 | {
68 | name: "showStop",
69 | title: "间断点",
70 | widget: "switch",
71 | width: 40, // 宽度
72 | activeColor: "#13ce66", // 激活背景颜色
73 | inactiveColor: "#ccc", // 取消背景颜色
74 | activeValue: true, // 打开的值,支持Boolean, String或Number
75 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
76 | }
77 | ]
78 | ]
79 | },
80 | {
81 | widget: "grid",
82 | title: "栅格布局",
83 | showTitle: false,
84 | isClicked: false,
85 | fields: [
86 | [
87 | {
88 | name: "showInput",
89 | title: "显示输入框",
90 | widget: "switch",
91 | width: 40, // 宽度
92 | activeColor: "#13ce66", // 激活背景颜色
93 | inactiveColor: "#ccc", // 取消背景颜色
94 | activeValue: true, // 打开的值,支持Boolean, String或Number
95 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
96 | }
97 | ], [
98 | {
99 | name: "showInputControls",
100 | title: "控制按钮",
101 | widget: "switch",
102 | width: 40, // 宽度
103 | activeColor: "#13ce66", // 激活背景颜色
104 | inactiveColor: "#ccc", // 取消背景颜色
105 | activeValue: true, // 打开的值,支持Boolean, String或Number
106 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
107 | hideRely: "showInput == false",
108 | }
109 | ]
110 | ]
111 | },
112 | {
113 | widget: "grid",
114 | title: "栅格布局",
115 | showTitle: false,
116 | isClicked: false,
117 | fields: [
118 | [
119 | {
120 | name: "vertical",
121 | title: "竖排列",
122 | widget: "switch",
123 | width: 40, // 宽度
124 | activeColor: "#13ce66", // 激活背景颜色
125 | inactiveColor: "#ccc", // 取消背景颜色
126 | activeValue: true, // 打开的值,支持Boolean, String或Number
127 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
128 | }
129 | ], [
130 | {
131 | name: "height",
132 | title: "高度",
133 | widget: "input",
134 | size: "small",
135 | hideRely: "vertical == false",
136 | }
137 | ]
138 | ]
139 | },
140 | {
141 | title: "尺寸",
142 | widget: "select",
143 | name: "inputSize",
144 | size: "small",
145 | hideRely: "showInput == false",
146 | options: [
147 | {
148 | value: "large",
149 | label: "超大",
150 | },
151 | {
152 | value: "medium",
153 | label: "大",
154 | },
155 | {
156 | value: "small",
157 | label: "中",
158 | },
159 | {
160 | value: "mini",
161 | label: "小",
162 | },
163 | ],
164 | },
165 | ],
166 | }
167 | }
168 |
169 | export const rules = {
170 | schema: {},
171 | values: {
172 |
173 | },
174 | form: {
175 | ...baseForm,
176 | layout: [
177 |
178 | ]
179 | }
180 | }
181 |
--------------------------------------------------------------------------------
/src/components/Formdesign/meta/slot.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | html
4 | *
5 | */
6 | import { baseForm, baseLayout } from "./base"
7 | export const attribute = {
8 | schema: {
9 |
10 | },
11 | values: {
12 |
13 | },
14 | form: {
15 | ...baseForm,
16 | layout: [
17 | ...baseLayout,
18 | {
19 | title: "文本",
20 | name: "html",
21 | widget: "input",
22 | type: "textarea"
23 | },
24 | ]
25 | }
26 | }
27 |
28 | export const rules = {
29 | schema: {},
30 | values: {},
31 | form: {
32 | ...baseForm,
33 | layout: []
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/components/Formdesign/meta/switch.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | disabled: false,
4 | width: 40, // 宽度
5 | activeColor: "#13ce66", // 激活背景颜色
6 | inactiveColor: "#ff4949", // 取消背景颜色
7 | activeText: "", // 激活文本
8 | inactiveText: "", // 取消文本
9 | activeValue: true, // 打开的值,支持Boolean, String或Number
10 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
11 | activeIconClass: "",
12 | inactiveIconClass: "",
13 | *
14 | */
15 | import { baseForm, baseLayout } from "./base"
16 | export const attribute = {
17 | schema: {
18 |
19 | },
20 | values: {
21 |
22 | },
23 | form: {
24 | ...baseForm,
25 | layout: [
26 | ...baseLayout,
27 | {
28 | title: "开值",
29 | widget: "input",
30 | size: "small",
31 | name: "activeValue"
32 | },
33 | {
34 | title: "关值",
35 | widget: "input",
36 | size: "small",
37 | name: "inactiveValue",
38 | },
39 | {
40 | title: "激活文本",
41 | widget: "input",
42 | size: "small",
43 | name: "activeText",
44 | },
45 | {
46 | title: "取消文本",
47 | widget: "input",
48 | size: "small",
49 | name: "inactiveText",
50 | },
51 | {
52 | title: "禁用",
53 | widget: "switch",
54 | name: "disabled",
55 | },
56 | {
57 | title: "宽度",
58 | widget: "inputnumber",
59 | size: "small",
60 | name: "width",
61 | },
62 | ],
63 | }
64 | }
65 |
66 | export const rules = {
67 | schema: {},
68 | values: {
69 |
70 | },
71 | form: {
72 | ...baseForm,
73 | layout: [
74 | {
75 | title: "类型",
76 | widget: "select",
77 | name: "type",
78 | size: "small",
79 | default: "number",
80 | options: [
81 | {
82 | value: "string",
83 | label: "字符串",
84 | },
85 | {
86 | value: "number",
87 | label: "数字",
88 | },
89 | {
90 | value: "boolean",
91 | label: "布尔",
92 | },
93 | ],
94 | },
95 | ]
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/src/components/Formdesign/meta/tabs.js:
--------------------------------------------------------------------------------
1 | import { baseForm, baseLayout } from "./base"
2 | export const attribute = {
3 | schema: {
4 | $schema: "http://json-schema.org/draft-07/schema#",
5 | title: "设备属性",
6 | description: "A product from Acme's catalog",
7 | type: "object",
8 | properties: {
9 | tabs: {
10 | type: "array"
11 | }
12 | }
13 | },
14 | values: {
15 |
16 | },
17 | form: {
18 | ...baseForm,
19 | layout: [
20 | {
21 | idKey: "name",
22 | title: "标签",
23 | name: "tabs",
24 | widget: "draggablelist",
25 | template: { label: "标签页一", fields: [] },
26 | attribute: {
27 | label: { widget: "input", placeholder: "", editable: true },
28 | name: { widget: "input", placeholder: "", editable: true },
29 | value: { widget: "", placeholder: "", editable: false },
30 | },
31 | },
32 | ],
33 | }
34 | }
35 |
36 | export const rules = {
37 | schema: {},
38 | values: {},
39 | form: {
40 | ...baseForm
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/components/Formdesign/meta/timepicker.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | isPicker: true, // 是否为 timepicker 时间任意。timeselect固定时间,由pickerOptions设定
4 | readOnly: false,
5 | disabled: false,
6 | clearable: true, // 是否显示清除按钮
7 | size: "", // medium / small / mini
8 | editable: false, // 文本框可输入
9 | placeholder: "请选择", // 单个
10 | valueFormat: "HH:mm:ss",
11 | isRange: false, // isRange下面三个有效
12 | arrowControl: true,
13 | rangeSeparator: "至", // 选择范围时的分隔符
14 | startPlaceholder: "开始时间",
15 | endPlaceholder: "结束时间",
16 | pickerOptions: {
17 | // timeselect 有效
18 | start: "08:30",
19 | step: "00:15",
20 | end: "18:30",
21 | },
22 | *
23 | */
24 | import { baseForm, baseLayout } from "./base"
25 | export const attribute = {
26 | schema: {
27 | $schema: "http://json-schema.org/draft-07/schema#",
28 | title: "设备属性",
29 | description: "A product from Acme's catalog",
30 | type: "object",
31 | properties: {
32 | isRange: {
33 | require: true,
34 | description: "该字段选择后不可更改,否则会因为字段类型错误而报错",
35 | }
36 | }
37 | },
38 | values: {},
39 | form: {
40 | ...baseForm,
41 | layout: [
42 | ...baseLayout,
43 | {
44 | title: "范围选择",
45 | widget: "select",
46 | name: "isRange",
47 | size: "small",
48 | options: [
49 | {
50 | value: true,
51 | label: "是",
52 | },
53 | {
54 | value: false,
55 | label: "否",
56 | }
57 | ],
58 | },
59 | {
60 | title: "尺寸",
61 | widget: "select",
62 | name: "size",
63 | size: "small",
64 | options: [
65 | {
66 | value: "medium",
67 | label: "大",
68 | },
69 | {
70 | value: "small",
71 | label: "中",
72 | },
73 | {
74 | value: "mini",
75 | label: "小",
76 | },
77 | ],
78 | },
79 | {
80 | widget: "input",
81 | title: "开始占位符",
82 | name: "startPlaceholder",
83 | hideRely: "isRange==false",
84 | size: "small"
85 | },
86 | {
87 | widget: "input",
88 | title: "结束占位符",
89 | name: "endPlaceholder",
90 | hideRely: "isRange==false",
91 | size: "small"
92 | },
93 | {
94 | widget: "input",
95 | title: "分隔符",
96 | name: "rangeSeparator",
97 | hideRely: "isRange==false",
98 | size: "small"
99 | },
100 | {
101 | widget: "grid",
102 | title: "栅格布局",
103 | showTitle: false,
104 | isClicked: false,
105 | fields: [
106 | [
107 | {
108 | name: "readOnly",
109 | title: "只看",
110 | widget: "switch",
111 | width: 40, // 宽度
112 | activeColor: "#13ce66", // 激活背景颜色
113 | inactiveColor: "#ccc", // 取消背景颜色
114 | activeValue: true, // 打开的值,支持Boolean, String或Number
115 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
116 | },
117 | {
118 | name: "clearable",
119 | title: "清除按钮",
120 | widget: "switch",
121 | width: 40, // 宽度
122 | activeColor: "#13ce66", // 激活背景颜色
123 | inactiveColor: "#ccc", // 取消背景颜色
124 | activeValue: true, // 打开的值,支持Boolean, String或Number
125 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
126 | }
127 | ], [
128 | {
129 | name: "disabled",
130 | title: "禁用",
131 | widget: "switch",
132 | width: 40, // 宽度
133 | activeColor: "#13ce66", // 激活背景颜色
134 | inactiveColor: "#ccc", // 取消背景颜色
135 | activeValue: true, // 打开的值,支持Boolean, String或Number
136 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
137 | },
138 | {
139 | name: "arrowControl",
140 | title: "可控",
141 | widget: "switch",
142 | width: 40, // 宽度
143 | activeColor: "#13ce66", // 激活背景颜色
144 | inactiveColor: "#ccc", // 取消背景颜色
145 | activeValue: true, // 打开的值,支持Boolean, String或Number
146 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
147 | },
148 | ]
149 | ]
150 | },
151 | ],
152 | }
153 | }
154 |
155 | export const rules = {
156 | schema: {},
157 | values: {
158 |
159 | },
160 | form: {
161 | ...baseForm,
162 | layout: [
163 | // {
164 | // title: "类型",
165 | // widget: "select",
166 | // name: "type",
167 | // size: "small",
168 | // options: [
169 | // {
170 | // value: "string",
171 | // label: "字符串",
172 | // },
173 | // {
174 | // value: "number",
175 | // label: "数字",
176 | // },
177 | // ],
178 | // },
179 | ]
180 | }
181 | }
182 |
--------------------------------------------------------------------------------
/src/components/Formdesign/meta/transfer.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | placeholder: "",
4 | filterable: false, // 是否过滤
5 | titles: ["Source1", "Target"], // 标题
6 | buttonTexts: [], // "到左边", "到右边"
7 | *
8 | */
9 | import { baseForm, baseLayout } from "./base"
10 | export const attribute = {
11 | schema: {
12 |
13 | },
14 | values: {
15 |
16 | },
17 | form: {
18 | ...baseForm,
19 | layout: [
20 | ...baseLayout,
21 | {
22 | name: "filterable",
23 | title: "过滤",
24 | widget: "switch",
25 | width: 40, // 宽度
26 | activeColor: "#13ce66", // 激活背景颜色
27 | inactiveColor: "#ccc", // 取消背景颜色
28 | activeValue: true, // 打开的值,支持Boolean, String或Number
29 | inactiveValue: false, // 关闭的值,支持Boolean, String或Number
30 | },
31 | {
32 | title: "标题",
33 | widget: "draggablelist",
34 | name: "titles",
35 | template: "",
36 | default: [],
37 | },
38 | {
39 | title: "选项",
40 | widget: "draggablelist",
41 | name: "options",
42 | template: { label: "", key: "" },
43 | attribute: {
44 | label: { widget: "input", placeholder: "", editable: true },
45 | key: { widget: "input", placeholder: "", editable: true },
46 | value: { widget: "", placeholder: "", editable: false },
47 | },
48 | default: [],
49 | },
50 | {
51 | title: "按钮",
52 | widget: "draggablelist",
53 | name: "buttonTexts",
54 | template: "",
55 | default: [],
56 | },
57 | ],
58 | }
59 | }
60 |
61 | export const rules = {
62 | schema: {},
63 | values: {
64 |
65 | },
66 | form: {
67 | ...baseForm,
68 | layout: [
69 |
70 | ]
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/components/Formdesign/meta/upload.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | title: "上传",
4 | name: "imageFile",
5 | tips: "", // 提示
6 | listType: "picture-card", // 可选 text/picture/picture-card
7 | actions: "http://127.0.0.1:8080/manage/minio/upload.do", // 上传路径
8 | deleteUrl: "http://127.0.0.1:8080/manage/minio/removeFile.do", // 删除路径
9 | draggable: true, // 是否可拖拽
10 | multiple: true, // 多选
11 | autoUpload: true, // 是否在选取文件后立即进行上传
12 | limit: 3, // 上传限制
13 | disabled: false,
14 | showFileList: true, // 是否显示已上传文件列表
15 | *
16 | */
17 | import { baseForm, baseLayout } from "./base"
18 | export const attribute = {
19 | schema: {
20 |
21 | },
22 | values: {
23 |
24 | },
25 | form: {
26 | ...baseForm,
27 | layout: [
28 | ...baseLayout,
29 | {
30 | title: "提示语",
31 | name: "tips",
32 | size: "small",
33 | widget: "input"
34 | },
35 | {
36 | title: "类型",
37 | widget: "select",
38 | name: "listType",
39 | size: "small",
40 | options: [
41 | {
42 | value: "text",
43 | label: "拖拽上传",
44 | },
45 | {
46 | value: "picture",
47 | label: "图片列表",
48 | },
49 | {
50 | value: "picture-card",
51 | label: "照片墙",
52 | },
53 | ],
54 | },
55 | {
56 | title: "上传URL",
57 | name: "actions",
58 | size: "small",
59 | widget: "input",
60 | },
61 | {
62 | title: "删除URL",
63 | name: "deleteUrl",
64 | size: "small",
65 | widget: "input"
66 | },
67 | {
68 | title: "可拖拽",
69 | widget: "select",
70 | name: "draggable",
71 | size: "small",
72 | options: [
73 | { value: true, label: "是" },
74 | { value: false, label: "否" },
75 | ],
76 | },
77 | {
78 | title: "多选",
79 | widget: "select",
80 | name: "multiple",
81 | size: "small",
82 | options: [
83 | { value: true, label: "是" },
84 | { value: false, label: "否" },
85 | ],
86 | },
87 | {
88 | title: "立即上传",
89 | widget: "select",
90 | name: "autoUpload",
91 | size: "small",
92 | options: [
93 | { value: true, label: "是" },
94 | { value: false, label: "否" },
95 | ],
96 | },
97 | {
98 | title: "禁用",
99 | widget: "select",
100 | name: "disabled",
101 | size: "small",
102 | options: [
103 | { value: true, label: "是" },
104 | { value: false, label: "否" },
105 | ],
106 | },
107 |
108 | {
109 | title: "显示上传列表",
110 | widget: "select",
111 | name: "showFileList",
112 | size: "small",
113 | options: [
114 | { value: true, label: "是" },
115 | { value: false, label: "否" },
116 | ],
117 | }
118 | ],
119 | }
120 | }
121 |
122 | export const rules = {
123 | schema: {},
124 | values: {},
125 | form: {
126 | ...baseForm,
127 | layout: []
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/src/components/Richform/actions.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
18 |
19 |
20 |
32 |
33 |
34 |
35 |
36 |
37 |
70 |
71 |
80 |
--------------------------------------------------------------------------------
/src/components/Richform/autoLayout.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
13 |
14 |
--------------------------------------------------------------------------------
/src/components/Richform/group/collapse.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
12 |
13 | {{
14 | collapse.title
15 | }}
16 |
17 |
18 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
78 |
79 |
--------------------------------------------------------------------------------
/src/components/Richform/group/default.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
25 |
26 |
--------------------------------------------------------------------------------
/src/components/Richform/group/grid.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
9 | {{ gridItem.title }}
10 |
11 |
12 |
13 |
14 |
20 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
73 |
74 |
--------------------------------------------------------------------------------
/src/components/Richform/group/tabs.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
59 |
60 |
--------------------------------------------------------------------------------
/src/components/Richform/layout.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
46 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
93 |
94 |
--------------------------------------------------------------------------------
/src/components/Richform/utils/defaultData.js:
--------------------------------------------------------------------------------
1 | export const defaultForm = {
2 | border: false, // 显示边框
3 | grid: false, // 表单内部栅栏
4 | labelSuffix: ":", // 字段标题后缀内容,默认' : '
5 | labelWidth: "100px", // 标签宽度,默认50px
6 | validator: "input", // submit
7 | labelAlign: "right", // 标签对齐, 默认右对齐, 可选左对齐left
8 | labelInline: true, // 字段标题显示位置, 默认true左侧left,false显示在top上方
9 | colors: { // 主题颜色
10 | theme: "", // #121B2C
11 | fontColor: "", // #F8F4F4
12 | btnColor: "", // #F8F4F4
13 | btnBgColor: "", // #040C19
14 | activeColor: "", // #4F9FFE
15 | dateRangeBgColor: "", // #999
16 | multiOptionBgColor: "" // #ddd
17 | },
18 | }
19 |
20 | export const defaultSchema = {
21 | $schema: "http://json-schema.org/draft-07/schema#",
22 | title: "richform attribute",
23 | description: "",
24 | type: "object",
25 | properties: {},
26 | errorMessage: {},
27 | if: {},
28 | then: {},
29 | else: {},
30 | allOf: [],
31 | anyOf: [],
32 | oneOf: [],
33 | required: [],
34 | }
35 |
--------------------------------------------------------------------------------
/src/components/Richform/utils/design.scss:
--------------------------------------------------------------------------------
1 | .richform {
2 | // 操作
3 | .design-draggable,
4 | .design-delete,
5 | .design-copy {
6 | display: inline-block;
7 | position: absolute;
8 | width: 22px;
9 | height: 26px;
10 | line-height: 26px;
11 | color: #fff;
12 | background: #409eff;
13 | text-align: center;
14 | cursor: pointer;
15 | z-index: 99999;
16 | }
17 | .design-draggable {
18 | left: 0;
19 | top: 0;
20 | z-index: 99;
21 | cursor: move;
22 | }
23 | .design-copy {
24 | right: 27px;
25 | bottom: 0;
26 | z-index: 99;
27 | }
28 | .design-delete {
29 | right: 3px;
30 | bottom: 0;
31 | z-index: 99;
32 | }
33 | // 拖拽过程配置
34 | .design-draggable-ghost {
35 | border-top: 5px solid #f56c6c;
36 | }
37 | // https://github.com/SortableJS/Vue.Draggable/issues/1008#issuecomment-782545024
38 | .base-component-item {
39 | width: 100%;
40 | display: inline-block;
41 | text-indent: -9999px;
42 | }
43 | .design-sortable-drag {
44 | background: #f4dec9;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/components/Richform/utils/designMixin.js:
--------------------------------------------------------------------------------
1 | import eventbus from "./eventbus";
2 | export default {
3 | props: {
4 | schema: { type: Object, default: () => ({}) },
5 | values: { type: Object, default: () => ({}) },
6 | form: { type: Object, default: () => ({}) },
7 | isDesign: { type: Boolean, default: false },
8 | fieldErrors: { type: Object, default: () => ({}) },
9 | hideFields: { type: Object, default: () => ({}) },
10 | colors: { type: Object, default: () => ({}) },
11 | isDark: { type: Boolean, default: false },
12 | isFriendValue: { type: Boolean, default: true },
13 | },
14 | inject: ["formId"],
15 | data() {
16 | return {
17 | designValid: true,
18 | }
19 | },
20 | created() {
21 | this.$nextTick(() => {
22 | // this.onScrollToBottom();
23 | })
24 | },
25 | methods: {
26 | emit() {
27 | if (arguments.length > 0) {
28 | arguments[0] = `${this.formId}:${arguments[0]}`;
29 | eventbus.$emit(...arguments);
30 | }
31 | },
32 | // 监听事件,滚动条滑动到最底部
33 | onScrollToBottom() {
34 | const ele = document.getElementById("form-design-center").parentNode;
35 | let scrollToBottomInterval;
36 | ele.onmouseenter = () => {
37 | scrollToBottomInterval = setInterval(function () {
38 | //设置滚动条到最底部
39 | if (ele.scrollHeight > ele.clientHeight) {
40 | ele.scrollTop = ele.scrollHeight;
41 | }
42 | }, 20);
43 | };
44 | ele.onmouseout = () => {
45 | clearInterval(scrollToBottomInterval);
46 | }
47 | window.addEventListener("mousewheel", () => {
48 | clearInterval(scrollToBottomInterval);
49 | }, false);
50 | },
51 | // 项目点击事件
52 | onClickedItem(item) {
53 | if (!this.isDesign) return;
54 | this.emit("design:clicked", item);
55 | },
56 | // 项目删除动作
57 | onDeleteItem(form, field) {
58 | if (!this.isDesign) return;
59 | this.iterationFind(form.layout, field)
60 | },
61 | // 递归查找并删除
62 | iterationFind(obj, target) {
63 | for (let key in obj) {
64 | if (typeof obj[key] === "object" && obj[key] !== null) {
65 | if (JSON.stringify(obj[key]) == JSON.stringify(target)) {
66 | this.$delete(obj, key);
67 | }
68 | this.iterationFind(obj[key], target)
69 | }
70 | }
71 | },
72 | // 复制
73 | onCopyItem(item) {
74 | if (!this.isDesign) return;
75 | this.emit("design:copyItem", item);
76 | },
77 | // 拖拽参数配置
78 | getDragOptions() {
79 | return {
80 | group: "formdesign", // 两个draggable要相互拖拽必须相同
81 | sort: true, // 是否允许排序
82 | disabled: false,
83 | animation: 0, // 过度
84 | easing: "cubic-bezier(1, 0, 0, 1)", // 动画效果
85 | handle: ".design-handle-move", // 可拖拽类,用于限定区域
86 | dragClass: "design-sortable-drag", // 排序背景显示
87 | ghostClass: "design-draggable-ghost",
88 | emptyInsertThreshold: 6, // 首个拖进来占位,该值不能太大,否则会发生抖动情况
89 | invertSwap: false,
90 | // direction: 'vertical',
91 | swapThreshold: 0.5,
92 | }
93 | }
94 | }
95 | }
--------------------------------------------------------------------------------
/src/components/Richform/utils/eventbus.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 |
3 | let eventbus= new Vue()
4 |
5 | export default eventbus
6 |
7 |
--------------------------------------------------------------------------------
/src/components/Richform/utils/http.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | import { Message } from 'element-ui'
3 |
4 | // create an axios instance
5 | const service = axios.create({
6 | timeout: 5000 // request timeout
7 | })
8 |
9 | // request interceptor
10 | service.interceptors.request.use(
11 | config => {
12 | const authKey = sessionStorage.getItem("richform-key");
13 | const authValue = sessionStorage.getItem("richform-value");
14 | if (authKey == "" || authValue == "") console.warn("未定义token信息")
15 | else config.headers[authKey] = authValue
16 | return config;
17 | },
18 | error => {
19 | // do something with request error
20 | console.log(error) // for debug
21 | return Promise.reject(error)
22 | }
23 | )
24 |
25 | // response interceptor
26 | service.interceptors.response.use(
27 | response => {
28 | const { data, status } = response
29 | if (status != 200) {
30 | Message({ message: res.msg || 'Error', type: 'error', duration: 5 * 1000 })
31 | return Promise.reject(new Error(res.msg || 'Error'))
32 | }
33 | return data
34 | },
35 | error => {
36 | console.log('err' + error) // for debug
37 | return Promise.reject(error)
38 | }
39 | )
40 |
41 | export default service
42 |
--------------------------------------------------------------------------------
/src/components/Richform/utils/index.js:
--------------------------------------------------------------------------------
1 | import request from "./http"
2 |
3 | export function isUrl(url) {
4 | let Exp = /^(https?:\/\/)([0-9a-z.]+)(:[0-9]+)?([/0-9a-z.]+)?(\?[0-9a-z&=]+)?(#[0-9-a-z]+)?/i;
5 | return Exp.test(url);
6 | }
7 |
8 | export function loadDict(url, data, method) {
9 | return request({
10 | url,
11 | method: method,
12 | [method == "post" ? "data" : "params"]: data
13 | })
14 | }
15 |
16 | // 将字符串转成对象,若转失败则直接返回源字符串
17 | export function strToObj(str) {
18 | try {
19 | return /^{.*}$/.test(str) || /^\[.*\]$/.test(str) ? JSON.parse(str) : str;
20 | } catch {
21 | return str
22 | }
23 | }
24 |
25 | export function deleteIteration(obj = {}, keys = []) {
26 | if (keys.length == 1) {
27 | delete obj[keys[0]];
28 | return;
29 | }
30 | obj = obj[keys[0]];
31 | keys.shift();
32 | return deleteIteration(obj, keys);
33 | }
34 |
35 | export function debounce(delay, callback) {
36 | let lastTime
37 |
38 | return function () {
39 | clearTimeout(lastTime)
40 |
41 | const [that, args] = [this, arguments]
42 |
43 | lastTime = setTimeout(() => {
44 | callback.apply(that, args)
45 | }, delay)
46 | }
47 | }
48 |
49 | export function observerDomResize(dom, callback) {
50 | const MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver
51 |
52 | const observer = new MutationObserver(callback)
53 |
54 | observer.observe(dom, { attributes: true, attributeFilter: ['style'], attributeOldValue: true, subtree: true, })
55 |
56 | return observer
57 | }
58 |
59 | /**
60 | * @description Get the rgb value of the hex color
61 | * @param {String} color Hex color
62 | * @return {Array} Rgb value of the color
63 | */
64 | export function getRgbValueFromHex(color) {
65 | color = color.replace('#', '');
66 | if (color.length === 3) color = Array.from(color).map(function (hexNum) {
67 | return hexNum + hexNum;
68 | }).join('');
69 | color = color.split('');
70 | return new Array(3).fill(0).map(function (t, i) {
71 | return parseInt("0x".concat(color[i * 2]).concat(color[i * 2 + 1]));
72 | });
73 | }
--------------------------------------------------------------------------------
/src/components/Richform/utils/themeMixin.js:
--------------------------------------------------------------------------------
1 | const ORIGINAL_THEME = '#409EFF' // default color
2 |
3 | export default {
4 | data() {
5 | return {
6 | originalColors: ['#409EFF', "#303133", "#606266", "#DCDFE6", "#E4E7ED", "#EBEEF5", "#F2F6FC", "#f4f4f5", "#fff", "#fff", "#fff", "#F5F7FA", "#303133"],
7 | }
8 | },
9 | watch: {
10 | "form.colors": {
11 | handler(newVal) {
12 | // 将新的颜色派发保存以便下一轮替换
13 | if (typeof newVal != "object") return;
14 | this.pickColors();
15 | },
16 | deep: true,
17 | immediate: true,
18 | }
19 | },
20 | methods: {
21 | pickColors() {
22 | this.$nextTick(() => {
23 | const oldVal = ORIGINAL_THEME
24 | let styles = [].slice.call(document.querySelectorAll('style')).filter(style => {
25 | const text = style.innerText
26 | return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text)
27 | })
28 | styles.forEach((style) => {
29 | const { innerText } = style
30 | if (typeof innerText !== 'string') return
31 | style.innerText = this.replaceStyle(innerText);
32 | })
33 | if (styles) this.updateOriginalColors();
34 | })
35 | },
36 | updateOriginalColors() {
37 | let { theme, fontColor, btnColor, activeColor, btnBgColor, dateRangeBgColor, multiOptionBgColor } = this.friendForm.colors;
38 | if (activeColor) this.originalColors[0] = activeColor;
39 | if (fontColor) {
40 | this.originalColors[1] = fontColor;
41 | this.originalColors[2] = fontColor;
42 | this.originalColors[3] = fontColor;
43 | this.originalColors[4] = fontColor;
44 | this.originalColors[5] = fontColor;
45 | this.originalColors[12] = theme;
46 | }
47 | if (dateRangeBgColor) this.originalColors[6] = dateRangeBgColor;
48 | if (multiOptionBgColor) this.originalColors[7] = multiOptionBgColor;
49 | if (theme) {
50 | this.originalColors[8] = theme;
51 | this.originalColors[9] = theme;
52 | }
53 | if (btnColor) this.originalColors[10] = btnColor;
54 | if (btnBgColor) this.originalColors[11] = btnBgColor;
55 |
56 | },
57 | replaceStyle(style) {
58 | let newStyle = style;
59 | let { originalColors } = this;
60 | let { activeColor, theme, fontColor, btnColor, btnBgColor, dateRangeBgColor, multiOptionBgColor } = this.friendForm.colors;
61 | if (activeColor.length > 0) // brand color
62 | // brand color
63 | newStyle = newStyle.replace(new RegExp(originalColors[0], 'ig'), activeColor) // 复选框,tab,选中的背景颜色
64 | if (fontColor.length > 0) {
65 | newStyle = newStyle.replace(new RegExp(`background:${originalColors[12]}`, 'ig'), 'background:' + theme) // tooltip背景颜色
66 | // font color
67 | newStyle = newStyle.replace(new RegExp(originalColors[1], 'ig'), fontColor) // 未被选中的状态,字体颜色
68 | newStyle = newStyle.replace(new RegExp(originalColors[2], 'ig'), fontColor) // 未被选中字体颜色,即字体颜色,非button ---白色
69 | // border color
70 | newStyle = newStyle.replace(new RegExp(originalColors[3], 'ig'), fontColor) // border 默认颜色
71 | newStyle = newStyle.replace(new RegExp(originalColors[4], 'ig'), fontColor) // border颜色 聚焦后的颜色
72 | newStyle = newStyle.replace(new RegExp(originalColors[5], 'ig'), fontColor) // 穿梭框边颜色
73 | }
74 | if (dateRangeBgColor.length > 0)
75 | newStyle = newStyle.replace(new RegExp(originalColors[6], 'ig'), dateRangeBgColor) // 日期范围背景
76 | if (multiOptionBgColor.length > 0)
77 | newStyle = newStyle.replace(new RegExp(originalColors[7], 'ig'), multiOptionBgColor) // 下拉框,多选的选项颜色
78 | if (theme.length > 0) {
79 | // background color
80 | newStyle = newStyle.replace(new RegExp(`background:${originalColors[8]}`, 'ig'), 'background:' + theme) // 下同
81 | newStyle = newStyle.replace(new RegExp(`background-color:${originalColors[9]}`, 'ig'), 'background-color:' + theme)
82 | }
83 | if (btnColor.length > 0)
84 | newStyle = newStyle.replace(new RegExp(`color:${originalColors[10]}`, 'ig'), 'color:' + btnColor) // 按钮和滑块的字体颜色
85 | if (btnBgColor.length > 0)
86 | newStyle = newStyle.replace(new RegExp(originalColors[11], 'ig'), btnBgColor) // 穿梭框头部和inputnumber两边的颜色,下拉hover的背景颜色
87 |
88 | return newStyle
89 | },
90 | }
91 | }
--------------------------------------------------------------------------------
/src/components/Richform/utils/validator.js:
--------------------------------------------------------------------------------
1 | const Ajv = require("ajv")
2 | const ajvI18n = require("ajv-i18n")
3 |
4 | // https://ajv.js.org/api.html
5 | const ajv = new Ajv({
6 | removeAdditional: true,
7 | useDefaults: true, // 校验时会自动填入缺省值
8 | coerceTypes: false, // 强制类型转换,如type="boolean",而value="其他类型",会被转换为boolean,
9 | allErrors: true, // 是否显示所有的错误,否则则显示单条数据
10 | jsonPointers: true,
11 | strict: false, // 严格模式,若开启,则schema中不能自定义字段
12 | })
13 | require("ajv-errors")(ajv, { singleError: false }); // 自定义错误信息
14 |
15 | // 将语言名称统一处理
16 | const langMap = {
17 | 'zh-cn': 'zh',
18 | 'en': 'en'
19 | }
20 |
21 | export const localize = function (errors, lang = "zh-cn") {
22 | let curLang = lang.toLowerCase()
23 | if (curLang in langMap) curLang = langMap[curLang] // 更名
24 | try {
25 | return ajvI18n[curLang](errors)
26 | } catch (e) {
27 | return ajvI18n.en(errors)
28 | }
29 | }
30 | ajv.localize = localize
31 |
32 |
33 | export default ajv
--------------------------------------------------------------------------------
/src/components/Richform/vars.scss:
--------------------------------------------------------------------------------
1 | $form-font-size: 13px;
2 | $field-font-color: #303133;
3 | $form-border-color: #ddd;
4 | $color: #409eff;
5 | $active-border-color: #4F9FFE;
6 |
--------------------------------------------------------------------------------
/src/components/Richform/widgets/button.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
20 |
21 |
22 |
39 |
40 |
41 |
42 |
43 |
73 |
74 |
--------------------------------------------------------------------------------
/src/components/Richform/widgets/cascader.vue:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
18 |
167 |
168 |
--------------------------------------------------------------------------------
/src/components/Richform/widgets/checkbox.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
13 |
21 |
22 |
33 |
34 |
35 |
43 |
44 |
45 |
46 |
56 |
57 |
58 |
59 |
60 |
61 |
111 |
112 |
121 |
--------------------------------------------------------------------------------
/src/components/Richform/widgets/colorpicker.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/components/Richform/widgets/components/Input/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
38 |
39 |
41 |
--------------------------------------------------------------------------------
/src/components/Richform/widgets/datetimepicker.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
118 |
119 |
129 |
--------------------------------------------------------------------------------
/src/components/Richform/widgets/input.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
24 | {{
25 | field.append
26 | }}
27 | {{
28 | field.prepend
29 | }}
30 |
31 |
32 |
33 |
79 |
80 |
--------------------------------------------------------------------------------
/src/components/Richform/widgets/inputnumber.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
15 |
16 |
17 |
18 |
40 |
45 |
--------------------------------------------------------------------------------
/src/components/Richform/widgets/ipinput.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 | {{ field.prepend }}
11 | {{ field.append }}
12 |
13 |
14 |
15 |
42 |
43 |
58 |
59 |
--------------------------------------------------------------------------------
/src/components/Richform/widgets/map.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
19 |
27 |
38 |
43 |
44 |
54 |
55 |
56 |
57 |
58 |
59 |
156 |
157 |
--------------------------------------------------------------------------------
/src/components/Richform/widgets/multiexp.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
--------------------------------------------------------------------------------
/src/components/Richform/widgets/radio.vue:
--------------------------------------------------------------------------------
1 |
2 |
48 |
49 |
50 |
88 |
89 |
--------------------------------------------------------------------------------
/src/components/Richform/widgets/rate.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/components/Richform/widgets/select.vue:
--------------------------------------------------------------------------------
1 |
2 |
34 |
35 |
36 |
174 |
175 |
--------------------------------------------------------------------------------
/src/components/Richform/widgets/slider.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
19 |
20 |
21 |
22 |
49 |
50 |
--------------------------------------------------------------------------------
/src/components/Richform/widgets/slot.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
23 |
24 |
--------------------------------------------------------------------------------
/src/components/Richform/widgets/switch.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
17 |
18 |
19 |
20 |
44 |
45 |
--------------------------------------------------------------------------------
/src/components/Richform/widgets/text.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
20 |
21 |
--------------------------------------------------------------------------------
/src/components/Richform/widgets/transfer.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
17 |
18 |
19 |
38 |
39 |
41 |
--------------------------------------------------------------------------------
/src/components/SplitLayout/mixin.scss:
--------------------------------------------------------------------------------
1 | @mixin clearfix {
2 | &:after {
3 | content: "";
4 | display: table;
5 | clear: both;
6 | }
7 | }
8 |
9 | @mixin scrollBar {
10 | &::-webkit-scrollbar-track-piece {
11 | background: #d3dce6;
12 | }
13 |
14 | &::-webkit-scrollbar {
15 | width: 6px;
16 | }
17 |
18 | &::-webkit-scrollbar-thumb {
19 | background: #99a9bf;
20 | border-radius: 20px;
21 | }
22 | }
23 |
24 | @mixin relative {
25 | position: relative;
26 | width: 100%;
27 | height: 100%;
28 | }
29 |
30 | @mixin pct($pct) {
31 | width: #{$pct};
32 | position: relative;
33 | margin: 0 auto;
34 | }
35 |
36 | @mixin triangle($width, $height, $color, $direction) {
37 | $width: $width/2;
38 | $color-border-style: $height solid $color;
39 | $transparent-border-style: $width solid transparent;
40 | height: 0;
41 | width: 0;
42 |
43 | @if $direction==up {
44 | border-bottom: $color-border-style;
45 | border-left: $transparent-border-style;
46 | border-right: $transparent-border-style;
47 | }
48 |
49 | @else if $direction==right {
50 | border-left: $color-border-style;
51 | border-top: $transparent-border-style;
52 | border-bottom: $transparent-border-style;
53 | }
54 |
55 | @else if $direction==down {
56 | border-top: $color-border-style;
57 | border-left: $transparent-border-style;
58 | border-right: $transparent-border-style;
59 | }
60 |
61 | @else if $direction==left {
62 | border-right: $color-border-style;
63 | border-top: $transparent-border-style;
64 | border-bottom: $transparent-border-style;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/components/Teleport/index.vue:
--------------------------------------------------------------------------------
1 |
30 |
--------------------------------------------------------------------------------
/src/components/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 |
3 | import RichForm from "./Richform/index.vue"
4 | Vue.component("RichForm", RichForm)
5 |
6 | import FormDesign, { FormMetas } from "./Formdesign/index.vue"
7 | Vue.component("FormDesign", FormDesign)
8 |
9 | import SplitLayout from "./SplitLayout/index.vue"
10 | Vue.component("SplitLayout", SplitLayout)
11 |
12 | export { RichForm, FormDesign, FormMetas, SplitLayout }
--------------------------------------------------------------------------------
/src/i18n/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import VueI18n from 'vue-i18n'
3 | Vue.use(VueI18n)
4 |
5 | const langFiles = require.context('./lang', true, /\.js$/)
6 |
7 | const langs = langFiles.keys().reduce((modules, modulePath) => {
8 | const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
9 | const value = langFiles(modulePath)
10 | modules[moduleName] = value.default;
11 | return modules
12 | }, {})
13 |
14 | const i18n = new VueI18n({
15 | warnHtmlMessage: false,
16 | locale: localStorage.getItem("lang") || "zh-CN",
17 | globalInjection: true,
18 | legacy: false,
19 | messages: langs
20 | })
21 |
22 | export default i18n
--------------------------------------------------------------------------------
/src/i18n/lang/en.js:
--------------------------------------------------------------------------------
1 | import elementEn from 'element-ui/lib/locale/lang/en'
2 | export default {
3 | // ...elementEn,
4 | lang: "english",
5 |
6 | }
--------------------------------------------------------------------------------
/src/i18n/lang/vi.js:
--------------------------------------------------------------------------------
1 | import elementVi from 'element-ui/lib/locale/lang/vi'
2 | export default {
3 | // ...elementVi,
4 | lang: "vi",
5 |
6 | }
--------------------------------------------------------------------------------
/src/i18n/lang/zh-CN.js:
--------------------------------------------------------------------------------
1 | import elementZhCn from 'element-ui/lib/locale/lang/zh-CN'
2 | export default {
3 | // ...elementZhCn,
4 | lang: "简体中文", // 这个写对应国语言
5 | }
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import i18n from '@/i18n'
3 | import App from './App.vue'
4 | import 'babel-polyfill'
5 | import Es6Promise from 'es6-promise'
6 | require('es6-promise').polyfill()
7 | Es6Promise.polyfill()
8 |
9 | Vue.config.productionTip = false
10 | import router from './router'
11 |
12 | new Vue({
13 | router,
14 | i18n,
15 | render: h => h(App),
16 | }).$mount('#app')
17 |
--------------------------------------------------------------------------------
/src/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "ajv-i18n": "^4.0.0"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/src/pages/deep-values.vue:
--------------------------------------------------------------------------------
1 |
2 |
22 |
23 |
24 | 所有值:{{ values }}
25 | 脏值:{{ hooks.dirtyValues }}
26 |
27 |
28 |
31 |
34 |
35 |
36 |
44 |
45 |
46 |
47 |
212 |
213 |
219 |
220 |
--------------------------------------------------------------------------------
/src/pages/form-design.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
26 |
27 |
--------------------------------------------------------------------------------
/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 |
4 | Vue.use(Router)
5 |
6 | const constRouter = [
7 | {
8 | path: '/form-design',
9 | name: 'richform',
10 | component: () => import('@/pages/richform')
11 | },
12 | {
13 | path: '/',
14 | name: 'form-design',
15 | component: () => import('@/pages/form-design')
16 | },
17 | {
18 | path: '/deep-values',
19 | name: 'deep-values',
20 | component: () => import('@/pages/deep-values')
21 | }
22 | ]
23 |
24 | const router = new Router({
25 | // mode: 'history',
26 | routes: constRouter
27 | })
28 |
29 | export default router
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | const webpack = require('webpack');
2 | const path = require('path');
3 | const isBuild = process.argv.includes("build")
4 |
5 | function resolve(dir) {
6 | return path.join(__dirname, dir);
7 | }
8 |
9 | module.exports = {
10 | publicPath: '',
11 | outputDir: 'dist/lib',
12 | assetsDir: 'static',
13 | productionSourceMap: false,
14 | css: { extract: false },
15 | configureWebpack: {
16 | // provide the app's title in webpack's name field, so that
17 | // it can be accessed in index.html to inject the correct title.
18 | name: 'richform',
19 | resolve: {
20 | alias: {
21 | '@': resolve('src')
22 | }
23 | },
24 | //警告 webpack 的性能提示
25 | performance: {
26 | hints: 'warning',
27 | //入口起点的最大体积
28 | maxEntrypointSize: 100000,
29 | //生成文件的最大体积
30 | maxAssetSize: 600000,
31 | },
32 | plugins: [],
33 | externals: isBuild ? {
34 | "ajv": "ajv",
35 | "ajv-errors": "ajv-errors",
36 | // "ajv-i18n": "ajv-i18n",
37 | "axios": "axios",
38 | "element-resize-detector": "element-resize-detector",
39 | "core-js": "core-js",
40 | "element-ui": "element-ui",
41 | "jquery": "jquery",
42 | "ramda": "ramda",
43 | "vue": "vue",
44 | "vue-baidu-map": "vue-baidu-map",
45 | "vue-i18n": "vue-i18n",
46 | "vue-router": "vue-router",
47 | "vue-scrollto": "vue-scrollto",
48 | "vue2-perfect-scrollbar": "vue2-perfect-scrollbar",
49 | "vuedraggable": "vuedraggable",
50 | "vxe-table": "vxe-table",
51 | "xe-utils": "xe-utils"
52 | } : {}
53 | },
54 | // to handle element icon error in build.
55 | chainWebpack: config => {
56 | config.module.rule('compile')
57 | .test(/\.js$/)
58 | .include
59 | .add(resolve('src'))
60 | .add(resolve('test'))
61 | .add(resolve('node_modules/webpack-dev-server/client'))
62 | .add(resolve('node_modules'))
63 | .end()
64 | .use('babel')
65 | .loader('babel-loader')
66 | .options({
67 | presets: [
68 | ['@babel/preset-env', {
69 | modules: false
70 | }]
71 | ]
72 | })
73 | config.module
74 | .rule("fonts")
75 | .test(/.(ttf|otf|eot|woff|woff2)$/)
76 | .use("url-loader")
77 | .loader("url-loader")
78 | .tap(options => {
79 | options = {
80 | // limit: 10000,
81 | name: '/static/fonts/[name].[ext]',
82 | }
83 | return options
84 | })
85 | .end()
86 | }
87 | }
--------------------------------------------------------------------------------