@form-create/core
Version:
FormCreate低代码表单渲染引擎,可以通过 JSON 生成具有动态渲染、数据收集、验证和提交功能的低代码表单。支持6个UI框架,适配移动端,并且支持生成任何 Vue 组件。
227 lines (213 loc) • 6.73 kB
JavaScript
import {err} from '@form-create/utils/lib/console';
import {byCtx, invoke} from './util';
import is, {hasProperty} from '@form-create/utils/lib/type';
import deepSet from '@form-create/utils/lib/deepset';
import {deepCopy} from '@form-create/utils/lib/deepextend';
import toArray from '@form-create/utils/lib/toarray';
const loadData = function (fc) {
const loadData = {
name: 'loadData',
_fn: [],
created(inject, rule, api) {
this.deleted(inject);
let attrs = toArray(inject.getValue());
const events = [];
attrs.forEach(attr => {
if (attr) {
const on = () => {
if (attr.watch !== false) {
fc.bus.$off('p.loadData.' + attr.attr, on);
fc.bus.$once('p.loadData.' + attr.attr, on);
}
let value = undefined;
if (attr.attr) {
value = fc.loadData[attr.attr] || attr.default;
if (attr.copy !== false) {
value = deepCopy(value)
}
}
deepSet(inject.getProp(), attr.to || 'options', value);
api.sync(rule);
}
events.push(() => fc.bus.$off('p.loadData.' + attr.attr, on));
on();
}
})
this._fn[inject.id] = events;
},
deleted(inject) {
if (this._fn[inject.id]) {
this._fn[inject.id].forEach(un => {
un();
})
delete this._fn[inject.id];
}
inject.clearProp();
},
};
loadData.watch = loadData.created;
return loadData;
}
const componentValidate = {
name: 'componentValidate',
load(attr, rule, api) {
const method = attr.getValue();
if (!method) {
attr.clearProp();
api.clearValidateState([rule.field]);
} else {
attr.getProp().validate = [{
validator(...args) {
const ctx = byCtx(rule);
if (ctx) {
return api.exec(ctx.id, method === true ? 'formCreateValidate' : method, ...args, {
attr,
rule,
api
});
}
}
}];
}
},
watch(...args) {
componentValidate.load(...args);
}
};
const fetch = function (fc) {
function parseOpt(option) {
if (is.String(option)) {
option = {
action: option,
to: 'options'
}
}
return option;
}
function run(inject, rule, api) {
let option = inject.value;
const set = (val) => {
if (val === undefined) {
inject.clearProp();
api.sync(rule);
} else {
deepSet(inject.getProp(), option.to || 'options', val);
}
}
if (is.Function(option)) {
option = option(rule, api);
}
option = parseOpt(option);
if (!option || !option.action) {
set(undefined);
return;
}
option = deepCopy(option);
if (!option.to) {
option.to = 'options';
}
const onError = option.onError;
const check = () => {
if (!inject.getValue()) {
inject.clearProp();
api.sync(rule);
return true;
}
}
const config = {
headers: {},
...option,
onSuccess(body, flag) {
if (check()) return;
let fn = (v) => flag ? v : (hasProperty(v, 'data') ? v.data : v);
if (is.Function(option.parse)) {
fn = option.parse;
} else if (option.parse && is.String(option.parse)) {
fn = (v) => {
option.parse.split('.').forEach(k => {
if (v) {
v = v[k];
}
})
return v;
}
}
set(fn(body, rule, api))
api.sync(rule);
},
onError(e) {
set(undefined)
if (check()) return;
(onError || ((e) => err(e.message || 'fetch fail ' + option.action)))(e, rule, api);
}
};
fc.$handle.beforeFetch(config, {rule, api}).then(() => {
if (is.Function(option.action)) {
option.action(rule, api).then((val) => {
config.onSuccess(val, true);
}).catch((e) => {
config.onError(e);
});
return;
}
invoke(() => fc.create.fetch(config, {inject, rule, api}));
});
}
return {
name: 'fetch',
loaded(...args) {
run(...args);
},
watch(...args) {
run(...args);
},
};
}
const $required = {
name: 'required',
load(inject, rule, api) {
const val = parseVal(inject.getValue());
if (val.required === false) {
inject.clearProp();
api.clearValidateState([rule.field]);
} else {
const validate = {
required: true,
validator(_, v, call) {
is.empty(v) ? call(validate.message) : call();
},
...val,
};
if (!validate.message) {
let title = rule.title || '';
validate.message = ((typeof title === 'object' ? title.title : title) || '') + '不能为空';
}
inject.getProp().validate = [validate];
}
api.sync(rule);
},
watch(...args) {
$required.load(...args);
}
}
function parseVal(val) {
if (is.Boolean(val)) {
return {required: val}
} else if (is.String(val)) {
return {message: val};
} else if (is.Undef(val)) {
return {required: false};
} else if (is.Function(val)) {
return {validator: val};
} else if (!is.Object(val)) {
return {};
} else {
return val;
}
}
export default {
fetch,
loadData,
required: $required,
componentValidate,
};