form-tdesigner
Version:
好用的Vue低代码可视化表单设计器,可以通过拖拽的方式快速创建表单,提高开发者对表单的开发效率。
433 lines (389 loc) • 10.9 kB
JavaScript
import is, { hasProperty } from '@form-create/utils/lib/type';
import { parseFn } from '@form-create/utils/lib/json';
import toCase from '@form-create/utils/lib/tocase';
import { computed, isRef, ref, unref } from 'vue';
import ZhCn from '../locale/zh-cn';
import { message } from './message';
export { formTemplate, formTemplateV3, htmlTemplate } from './template';
export function makeRequiredRule() {
return {
type: 'Required',
field: 'formCreate$required',
title: '是否必填',
};
}
export function addAutoKeyMap(cm) {}
export function makeTreeOptions(pre, config, level, data = []) {
if (!config.id) {
config.id = 1;
}
level && level--;
for (let i = 0; i < 3; i++) {
const item = {
[config.label]: pre + level * 10 + (i + 1),
[config.value]: '' + config.id++,
};
if (level) {
makeTreeOptions(pre, config, level, (item.children = []));
}
data.push(item);
}
return data;
}
export function makeOptionsRule(t, to) {
const options = [
{ label: t('fetch.optionsType.struct'), value: 2 },
{ label: t('fetch.optionsType.fetch'), value: 1 },
];
const control = [
{
value: 1,
rule: [
{
type: 'FetchConfig',
field: 'formCreateEffect>fetch',
props: {
to,
},
},
],
},
{
value: 2,
rule: [
{
type: 'TableOptions',
field: 'formCreate' + upper(to).replace('.', '>'),
props: {
column: [
{ label: t('props.key'), key: 'label' },
{ value: true, label: t('props.value'), key: 'value' },
],
keyValue: 'label',
},
},
],
},
];
return {
type: 'radio',
title: t('props.options'),
field: '_optionType',
value: 2,
options,
props: {
type: 'button',
},
control,
};
}
export function makeTreeOptionsRule(t, to, label, value) {
const options = [
{ label: t('fetch.optionsType.struct'), value: 2 },
{ label: t('fetch.optionsType.fetch'), value: 1 },
];
const control = [
{
value: 1,
rule: [
{
type: 'FetchConfig',
field: 'formCreateEffect>fetch',
props: {
to,
},
},
],
},
{
value: 2,
rule: [
{
type: 'TreeOptions',
field: 'formCreate' + upper(to).replace('.', '>'),
props: {
columns: {
label,
value,
},
keyValue: label,
},
},
],
},
];
return {
type: 'radio',
title: t('props.options'),
field: '_optionType',
value: 2,
options,
props: {
type: 'button',
},
control,
};
}
export function upper(str) {
return str.replace(str[0], str[0].toLocaleUpperCase());
}
export const toJSON = function (val) {
const type = /object ([a-zA-Z]*)/.exec(Object.prototype.toString.call(val));
if (type && _toJSON[type[1].toLowerCase()]) {
return _toJSON[type[1].toLowerCase()](val);
} else {
return val;
}
};
const _toJSON = {
object: function (val) {
var json = [];
for (var i in val) {
if (!hasProperty(val, i)) continue;
json.push(toJSON(i) + ': ' + (val[i] != null ? toJSON(val[i]) : 'null'));
}
return '{\n ' + json.join(',\n ') + '\n}';
},
function: function (val) {
val = '' + val;
var exec = /^ *([\w]+) *\(/.exec(val);
if (exec && exec[1] !== 'function') {
return 'function ' + val;
}
return val;
},
array: function (val) {
for (var i = 0, json = []; i < val.length; i++)
json[i] = val[i] != null ? toJSON(val[i]) : 'null';
return '[' + json.join(', ') + ']';
},
string: function (val) {
var tmp = val.split('');
for (var i = 0; i < tmp.length; i++) {
var c = tmp[i];
c >= ' '
? c === '\\'
? (tmp[i] = '\\\\')
: c === '"'
? (tmp[i] = '\\"')
: 0
: (tmp[i] =
c === '\n'
? '\\n'
: c === '\r'
? '\\r'
: c === '\t'
? '\\t'
: c === '\b'
? '\\b'
: c === '\f'
? '\\f'
: ((c = c.charCodeAt()),
'\\u00' + (c > 15 ? 1 : 0) + (c % 16)));
}
return '"' + tmp.join('') + '"';
},
};
export const deepParseFn = function (target) {
if (target && typeof target === 'object') {
for (let key in target) {
if (Object.prototype.hasOwnProperty.call(target, key)) {
let data = target[key];
if (Array.isArray(data) || is.Object(data)) {
deepParseFn(data);
}
if (is.String(data)) {
target[key] = parseFn(data);
}
}
}
}
return target;
};
export function deepGet(object, path, defaultValue) {
path = (path || '').split('.');
let index = 0,
length = path.length;
while (object != null && index < length) {
object = object[path[index++]];
}
return index && index === length
? object !== undefined
? object
: defaultValue
: defaultValue;
}
export const buildTranslator = locale => (path, option) =>
translate(path, option, unref(locale));
export const translate = (path, option, locale) =>
deepGet(locale, path, '').replace(
/\{(\w+)\}/g,
(_, key) => `${option?.[key] ?? `{${key}}`}`,
);
export const buildLocaleContext = locale => {
const lang = computed(() => unref(locale).name);
const name = computed(() => upper(toCase(lang.value || '')));
const localeRef = isRef(locale) ? locale : ref(locale);
return {
lang,
name,
locale: localeRef,
t: buildTranslator(locale),
};
};
export const useLocale = locale => {
return buildLocaleContext(computed(() => locale.value || ZhCn));
};
export const localeOptions = (t, options, prefix) => {
return options.map(opt => {
opt.label =
t((prefix || 'props') + '.' + opt.label || opt.value) || opt.label;
return opt;
});
};
export const localeProps = (t, prefix, rules) => {
return rules.map(rule => {
if (rule.field === 'formCreate$required') {
rule.title = t('validate.required') || rule.title;
} else if (rule.field && rule.field !== '_optionType') {
rule.title = t('com.' + prefix + '.' + rule.field) || rule.title;
}
if (rule.type === 'template' && is.trueArray(rule.children)) {
rule.children = localeProps(t, prefix, rule.children);
}
return rule;
});
};
export const getRuleTree = children => {
const tree = [];
children &&
children.forEach(rule => {
if (rule?._fc_drag_tag) {
const item = {
id: rule.__fc__.id,
rule,
children: getRuleTree(rule.children),
};
if (!item.children.length) {
delete item.children;
}
tree.push(item);
} else {
tree.push(...getRuleTree(rule?.children));
}
});
return tree;
};
export const getFormRuleDescription = tree => {
const getTree = children => {
const tree = [];
children &&
children.forEach(rule => {
if (rule.field) {
rule.children = getTree(rule.children || []);
if (!rule.children.length) {
delete rule.children;
}
tree.push(rule);
} else {
tree.push(...getTree(rule.children || []));
}
});
return tree;
};
return getTree(tree);
};
export const getRuleDescription = children => {
const getTree = children => {
const tree = [];
children &&
children.forEach(rule => {
if (typeof rule !== 'object') {
return;
}
if (rule._fc_drag_tag) {
const item = {
_fc_id: rule._fc_id,
type: rule.type,
field: rule.field,
title: rule.title,
name: rule.name,
slot: rule.slot,
props: { ...(rule.props || {}) },
children: getTree(rule.children || []),
};
if (rule.children && typeof rule.children[0] === 'string') {
item.content = rule.children[0];
}
if (!item.children.length) {
delete item.children;
}
tree.push(item);
} else {
tree.push(...getTree(rule.children));
}
});
return tree;
};
return getTree(children);
};
export function getInjectArg(t) {
return {
name: '$inject',
columns: [
{ label: '$inject.api', info: t('event.inject.api'), type: 'Api' },
{ label: '$inject.rule', info: t('event.inject.rule'), type: 'Rule[]' },
{ label: '$inject.self', info: t('event.inject.self'), type: 'Rule' },
{
label: '$inject.option',
info: t('event.inject.option'),
type: 'Object',
},
{ label: '$inject.args', info: t('event.inject.args'), type: 'Array' },
],
};
}
export function isElementInside(x, y, element) {
const rect = element.getBoundingClientRect();
return x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom;
}
export function isNull(v) {
return ['', null, undefined].indexOf(v) !== -1;
}
export function escapeRegExp(str) {
return str.replace(/[\ .*+?^${}()|[\]\\]/g, '\\$&');
}
export function compareVersion(v1, v2) {
const a1 = v1.split('.');
const a2 = v2.split('.');
const minLength = Math.min(a1.length, a2.length);
for (var i = 0; i < minLength; i++) {
var diff = parseInt(a1[i], 10) - parseInt(a2[i], 10);
if (diff > 0) {
return 1;
} else if (diff < 0) {
return -1;
}
}
return a1.length === a2.length ? 0 : a1.length < a2.length ? -1 : 1;
}
export function copyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.style.position = 'fixed';
textArea.style.top = 0;
textArea.style.left = '-9999px';
textArea.value = text;
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
document.execCommand('copy');
} catch (err) {
console.log('Oops, unable to copy');
}
message('已复制!', 'success');
document.body.removeChild(textArea);
}
export function uniqueArray(arr) {
return arr.filter((item, index) => arr.indexOf(item) === index);
}