1 | import getConfig from './config';
|
2 | import mergeProps from '@form-create/utils/lib/mergeprops';
|
3 | import is, {hasProperty} from '@form-create/utils/lib/type';
|
4 | import toString from '@form-create/utils/lib/tostring';
|
5 | import extend from '@form-create/utils/lib/extend';
|
6 |
|
7 | function isTooltip(info) {
|
8 | return info.type === 'tooltip';
|
9 | }
|
10 |
|
11 | const upperCaseReg = /[A-Z]/;
|
12 |
|
13 | export function isAttr(name, value) {
|
14 | return (!upperCaseReg.test(name) && (is.String(value) || is.Number(value)))
|
15 | }
|
16 |
|
17 | function tidy(props, name) {
|
18 | if (!hasProperty(props, name)) return;
|
19 | if (is.String(props[name])) {
|
20 | props[name] = {[name]: props[name], show: true};
|
21 | }
|
22 | }
|
23 |
|
24 | function isFalse(val) {
|
25 | return val === false;
|
26 | }
|
27 |
|
28 | function tidyBool(opt, name) {
|
29 | if (hasProperty(opt, name) && !is.Object(opt[name])) {
|
30 | opt[name] = {show: !!opt[name]};
|
31 | }
|
32 | }
|
33 |
|
34 | export default {
|
35 | validate(call) {
|
36 | this.form().validate(call);
|
37 | },
|
38 | validateField(field, call) {
|
39 | this.form().validateField(field, call);
|
40 | },
|
41 | clearValidateState(ctx) {
|
42 | const fItem = this.vm.$refs[ctx.wrapRef];
|
43 | if (fItem) {
|
44 | fItem.validateMessage = '';
|
45 | fItem.validateState = '';
|
46 | }
|
47 | },
|
48 | tidyOptions(options) {
|
49 | ['submitBtn', 'resetBtn', 'row', 'info', 'wrap', 'col'].forEach(name => {
|
50 | tidyBool(options, name);
|
51 | })
|
52 | return options;
|
53 | },
|
54 | tidyRule({prop}) {
|
55 | tidy(prop, 'title');
|
56 | tidy(prop, 'info');
|
57 | return prop;
|
58 | },
|
59 | mergeProp(ctx) {
|
60 | let props = ctx.prop.props;
|
61 | ctx.prop = mergeProps([{
|
62 | attrs: Object.keys(props).reduce((initial, val) => {
|
63 | if (isAttr(val, props[val]))
|
64 | initial[val] = props[val];
|
65 | return initial;
|
66 | }, {}),
|
67 | info: this.options.info || {},
|
68 | wrap: this.options.wrap || {},
|
69 | col: this.options.col || {},
|
70 | }, ctx.prop], {
|
71 | info: {
|
72 | trigger: 'hover',
|
73 | placement: 'top-start',
|
74 | icon: 'el-icon-warning',
|
75 | },
|
76 | title: {},
|
77 | col: {span: 24},
|
78 | wrap: {},
|
79 | }, {normal: ['title', 'info', 'col', 'wrap']});
|
80 | },
|
81 | getDefaultOptions() {
|
82 | return getConfig();
|
83 | },
|
84 | update() {
|
85 | const form = this.options.form;
|
86 | this.rule = {
|
87 | props: {...form},
|
88 | nativeOn: {
|
89 | submit: (e) => {
|
90 | e.preventDefault();
|
91 | }
|
92 | },
|
93 | class: [form.className, form.class, 'form-create'],
|
94 | style: form.style,
|
95 | type: 'form',
|
96 | };
|
97 | },
|
98 | beforeRender() {
|
99 | const {key, ref, $handle} = this;
|
100 | extend(this.rule, {key, ref});
|
101 | extend(this.rule.props, {
|
102 | model: $handle.formData,
|
103 | rules: $handle.validate(),
|
104 | });
|
105 | },
|
106 | render(children) {
|
107 | if (children.length) {
|
108 | children.push(this.makeFormBtn());
|
109 | }
|
110 | return this.$r(this.rule, isFalse(this.options.row.show) ? children : [this.makeRow(children)]);
|
111 | },
|
112 | makeWrap(ctx, children) {
|
113 | const rule = ctx.prop;
|
114 | const uni = `${this.key}${ctx.key}`;
|
115 | const col = rule.col;
|
116 | const isTitle = this.isTitle(rule);
|
117 | const labelWidth = (!col.labelWidth && !isTitle) ? 0 : col.labelWidth;
|
118 | const {inline, col: _col} = this.rule.props;
|
119 | const item = isFalse(rule.wrap.show) ? children : this.$r(mergeProps([rule.wrap, {
|
120 | props: {
|
121 | labelWidth: labelWidth === void 0 ? labelWidth : toString(labelWidth),
|
122 | ...(rule.wrap || {}),
|
123 | prop: ctx.id,
|
124 | rules: rule.validate,
|
125 | },
|
126 | class: rule.className,
|
127 | key: `${uni}fi`,
|
128 | ref: ctx.wrapRef,
|
129 | type: 'formItem',
|
130 | }]), [children, isTitle ? this.makeInfo(rule, uni) : null]);
|
131 | return (inline === true || isFalse(_col) || isFalse(col.show)) ? item : this.makeCol(rule, uni, [item]);
|
132 | },
|
133 | isTitle(rule) {
|
134 | if(this.options.form.title === false) return false;
|
135 | const title = rule.title;
|
136 | return !((!title.title && !title.native) || isFalse(title.show))
|
137 | },
|
138 | makeInfo(rule, uni) {
|
139 | const titleProp = rule.title;
|
140 | const infoProp = rule.info;
|
141 | const isTip = isTooltip(infoProp);
|
142 | const form = this.options.form;
|
143 | const children = [titleProp.title + (form.labelSuffix || form['label-suffix'] || '')];
|
144 | const titleFn = (pop) => this.$r(mergeProps([titleProp, {
|
145 | props: titleProp,
|
146 | slot: titleProp.slot || (pop ? (isTip ? 'default' : 'reference') : 'label'),
|
147 | key: `${uni}tit`,
|
148 | type: titleProp.type || 'span',
|
149 | }]), children);
|
150 |
|
151 | if (!isFalse(infoProp.show) && (infoProp.info || infoProp.native)) {
|
152 | if (infoProp.icon !== false) {
|
153 | children[infoProp.align !== 'left' ? 'unshift' : 'push'](this.$r({
|
154 | type: 'i',
|
155 | class: infoProp.icon === true ? 'el-icon-warning' : infoProp.icon,
|
156 | key: `${uni}i`
|
157 | }));
|
158 | }
|
159 | const prop = {
|
160 | type: infoProp.type || 'popover',
|
161 | props: {...infoProp},
|
162 | key: `${uni}pop`,
|
163 | slot: 'label'
|
164 | };
|
165 |
|
166 | const field = 'content';
|
167 | if (infoProp.info && !hasProperty(prop.props, field)) {
|
168 | prop.props[field] = infoProp.info;
|
169 | }
|
170 |
|
171 | return this.$r(mergeProps([infoProp, prop]), [
|
172 | titleFn(true)
|
173 | ])
|
174 | }
|
175 | return titleFn();
|
176 | },
|
177 | makeCol(rule, uni, children) {
|
178 | const col = rule.col;
|
179 | return this.$r({
|
180 | class: col.class,
|
181 | type: 'col',
|
182 | props: col || {span: 24},
|
183 | key: `${uni}col`
|
184 | }, children);
|
185 | },
|
186 | makeRow(children) {
|
187 | const row = this.options.row || {};
|
188 | return this.$r({
|
189 | type: 'row',
|
190 | props: row,
|
191 | class: row.class,
|
192 | key: `${this.key}row`
|
193 | }, children)
|
194 | },
|
195 | makeFormBtn() {
|
196 | let vn = [];
|
197 | if (!isFalse(this.options.submitBtn.show)) {
|
198 | vn.push(this.makeSubmitBtn())
|
199 | }
|
200 | if (!isFalse(this.options.resetBtn.show)) {
|
201 | vn.push(this.makeResetBtn())
|
202 | }
|
203 | if (!vn.length) {
|
204 | return;
|
205 | }
|
206 | const item = this.$r({
|
207 | type: 'formItem',
|
208 | key: `${this.key}fb`
|
209 | }, vn);
|
210 |
|
211 | return this.rule.props.inline === true
|
212 | ? item
|
213 | : this.$r({
|
214 | type: 'col',
|
215 | props: {span: 24},
|
216 | key: `${this.key}fc`
|
217 | }, [item]);
|
218 | },
|
219 | makeResetBtn() {
|
220 | const resetBtn = this.options.resetBtn;
|
221 | return this.$r({
|
222 | type: 'button',
|
223 | props: resetBtn,
|
224 | style: {width: resetBtn.width},
|
225 | on: {
|
226 | click: () => {
|
227 | const fApi = this.$handle.api;
|
228 | resetBtn.click
|
229 | ? resetBtn.click(fApi)
|
230 | : fApi.resetFields();
|
231 | }
|
232 | },
|
233 | key: `${this.key}b2`,
|
234 | }, [resetBtn.innerText]);
|
235 | },
|
236 | makeSubmitBtn() {
|
237 | const submitBtn = this.options.submitBtn;
|
238 |
|
239 | return this.$r({
|
240 | type: 'button',
|
241 | props: submitBtn,
|
242 | style: {width: submitBtn.width},
|
243 | on: {
|
244 | click: () => {
|
245 | const fApi = this.$handle.api;
|
246 | submitBtn.click
|
247 | ? submitBtn.click(fApi)
|
248 | : fApi.submit();
|
249 | }
|
250 | },
|
251 | key: `${this.key}b1`,
|
252 | }, [submitBtn.innerText]);
|
253 | }
|
254 | }
|