import { defineComponent, h, nextTick } from "vue";
import { cloneDeep, isBoolean } from "lodash-es";
import { useAction, useForm, usePlugins, useTabs } from "./helper";
import { useBrowser, useConfig, useElApi, useRefs } from "../../hooks";
import { getValue, merge } from "../../utils";
import formHook from "../../utils/form-hook";
import { renderNode } from "../../utils/vnode";
import { parseFormHidden } from "../../utils/parse";
export default defineComponent({
name: "cl-form",
props: {
inner: Boolean,
inline: Boolean
},
setup(props, { expose, slots }) {
const { refs, setRefs } = useRefs();
const { style, dict } = useConfig();
const browser = useBrowser();
const { Form, config, form, visible, saving, loading, disabled } = useForm();
// 关闭的操作类型
let closeAction: ClForm.CloseAction = "close";
// 旧表单数据
let defForm: obj | undefined;
// 选项卡
const Tabs = useTabs({ config, Form });
// 操作
const Action = useAction({ config, form, Form });
// 方法
const ElFormApi = useElApi(
["validate", "validateField", "resetFields", "scrollToField", "clearValidate"],
Form
);
// 插件
const plugin = usePlugins({ visible });
// 显示加载中
function showLoading() {
loading.value = true;
}
// 隐藏加载
function hideLoading() {
loading.value = false;
}
// 设置是否禁用
function setDisabled(val: boolean = true) {
disabled.value = val;
}
// 请求表单保存状态
function done() {
saving.value = false;
}
// 关闭表单
function close(action?: ClForm.CloseAction) {
if (action) {
closeAction = action;
}
beforeClose(() => {
visible.value = false;
done();
});
}
// 关闭前
function beforeClose(done: fn) {
if (config.on?.close) {
config.on.close(closeAction, done);
} else {
done();
}
}
// 关闭后
function onClosed() {
Tabs.clear();
Form.value?.clearValidate();
}
// 清空表单验证
function clear() {
for (const i in form) {
delete form[i];
}
setTimeout(() => {
Form.value?.clearValidate();
}, 0);
}
// 重置
function reset() {
if (defForm) {
for (const i in defForm) {
form[i] = cloneDeep(defForm[i]);
}
}
}
// 表单提交
function submit(callback?: fn) {
// 验证表单
Form.value.validate(async (valid: boolean, error: any) => {
if (valid) {
saving.value = true;
// 拷贝表单值
const d = cloneDeep(form);
config.items.forEach((e) => {
function deep(e: ClForm.Item) {
if (e.prop) {
// 过滤隐藏的表单项
if (e._hidden) {
if (e.prop) {
delete d[e.prop];
}
}
// hook 提交处理
if (e.hook) {
formHook.submit({
...e,
value: e.prop ? d[e.prop] : undefined,
form: d
});
}
}
if (e.children) {
e.children.forEach(deep);
}
}
deep(e);
});
// 处理 "-" 多层级
for (const i in d) {
if (i.includes("-")) {
// 结构参数
const [a, ...arr] = i.split("-");
// 关键值的key
const k: string = arr.pop() || "";
if (!d[a]) {
d[a] = {};
}
let f: any = d[a];
// 设置默认值
arr.forEach((e) => {
if (!f[e]) {
f[e] = {};
}
f = f[e];
});
// 设置关键值
f[k] = d[i];
delete d[i];
}
}
const submit = callback || config.on?.submit;
// 提交事件
if (submit) {
submit(await plugin.submit(d), {
close() {
close("save");
},
done
});
} else {
done();
}
} else {
// 切换到对应的选项卡
Tabs.toGroup({
refs,
config,
prop: Object.keys(error)[0]
});
}
});
}
// 打开表单
function open(options?: ClForm.Options, plugins?: ClForm.Plugin[]) {
if (!options) {
return console.error("Options is not null");
}
// 清空
if (options.isReset !== false) {
clear();
}
// 显示对话框
visible.value = true;
// 默认关闭方式
closeAction = "close";
// 合并配置
for (const i in config) {
switch (i) {
// 表单项
case "items":
function deep(arr: any[]): any[] {
return arr.map((e) => {
const d = getValue(e);
return {
...d,
children: d?.children ? deep(d.children) : undefined
};
});
}
config.items = deep(options.items || []);
break;
// 事件、参数、操作
case "on":
case "op":
case "props":
case "dialog":
case "_data":
merge(config[i], options[i] || {});
break;
// 其他
default:
config[i] = options[i];
break;
}
}
// 预设表单值
if (options?.form) {
for (const i in options.form) {
form[i] = options.form[i];
}
}
// 设置表单数据
config.items.forEach((e) => {
function deep(e: ClForm.Item) {
if (e.prop) {
// 解析 prop
if (e.prop.includes(".")) {
e.prop = e.prop.replace(/\./g, "-");
}
// prop 合并
Tabs.mergeProp(e);
// hook 绑定值
formHook.bind({
...e,
value: form[e.prop] !== undefined ? form[e.prop] : cloneDeep(e.value),
form
});
// 表单验证
if (e.required) {
e.rules = {
required: true,
message: `${e.label}${dict.label.nonEmpty}`
};
}
}
// 设置 tabs 默认值
if (e.type == "tabs") {
Tabs.set(e.value);
}
// 子集
if (e.children) {
e.children.forEach(deep);
}
}
deep(e);
});
// 设置默认值
if (!defForm) {
defForm = cloneDeep(form);
}
// 创建插件
plugin.create(plugins);
// 打开回调
nextTick(() => {
setTimeout(() => {
// 打开事件
if (config.on?.open) {
config.on.open(form);
}
}, 10);
});
}
// 绑定表单数据
function bindForm(data: any) {
config.items.forEach((e) => {
function deep(e: ClForm.Item) {
formHook.bind({
...e,
value: e.prop ? data[e.prop] : undefined,
form: data
});
if (e.children) {
e.children.forEach(deep);
}
}
deep(e);
});
Object.assign(form, data);
}
// 渲染表单项
function renderFormItem(e: ClForm.Item) {
const { isDisabled } = config._data;
if (e.type == "tabs") {
return (