cl-form 添加 children 参数

This commit is contained in:
icssoa 2023-06-13 02:14:01 +08:00
parent 02dad133a8
commit 520fd74d2b
12 changed files with 221 additions and 134 deletions

View File

@ -58,6 +58,11 @@
" app.refresh();", " app.refresh();",
" }", " }",
");", ");",
"",
"// 刷新",
"function refresh(params?: any) {",
" Crud.value?.refresh(params);",
"}",
"</script>", "</script>",
"" ""
], ],

View File

@ -1,6 +1,6 @@
{ {
"name": "front-next", "name": "front-next",
"version": "6.3.1", "version": "6.3.2",
"scripts": { "scripts": {
"dev": "vite --host", "dev": "vite --host",
"build": "vite build", "build": "vite build",

View File

@ -429,6 +429,18 @@ declare namespace ClForm {
size?: "medium" | "default" | "small"; size?: "medium" | "default" | "small";
[key: string]: any; [key: string]: any;
}; };
col?: {
span: number;
offset: number;
push: number;
pull: number;
xs: any;
sm: any;
md: any;
lg: any;
xl: any;
tag: string;
};
hook?: Hook.Form; hook?: Hook.Form;
group?: string; group?: string;
collapse?: boolean; collapse?: boolean;
@ -443,6 +455,7 @@ declare namespace ClForm {
append?: Render.Component; append?: Render.Component;
rules?: Rule | Rule[]; rules?: Rule | Rule[];
required?: boolean; required?: boolean;
children?: Item[];
[key: string]: any; [key: string]: any;
} }

View File

@ -138,7 +138,7 @@ export function useTabs({ config, Form }: { config: Config; Form: Form }) {
} }
// 切换 // 切换
function change(value: any, isValid: boolean = true) { function change(value: any, isValid = true) {
return new Promise((resolve: Function, reject: Function) => { return new Promise((resolve: Function, reject: Function) => {
function next() { function next() {
active.value = value; active.value = value;
@ -146,7 +146,7 @@ export function useTabs({ config, Form }: { config: Config; Form: Form }) {
} }
if (isValid) { if (isValid) {
let isError: boolean = false; let isError = false;
const arr = config.items const arr = config.items
.filter((e: any) => e.group == active.value && !e._hidden && e.prop) .filter((e: any) => e.group == active.value && !e._hidden && e.prop)

View File

@ -274,35 +274,44 @@ export default defineComponent({
// 设置表单数据 // 设置表单数据
config.items.map((e) => { config.items.map((e) => {
if (e.prop) { function deep(e: ClForm.Item) {
// 解析 prop if (e.prop) {
if (e.prop.includes(".")) { // 解析 prop
e.prop = e.prop.replace(/\./g, "-"); if (e.prop.includes(".")) {
e.prop = e.prop.replace(/\./g, "-");
}
// prop 合并
Tabs.mergeProp(e);
// 绑定值
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}不能为空`
};
}
// 子集
if (e.children) {
e.children.forEach(deep);
}
} }
// prop 合并 // 设置 tabs 默认值
Tabs.mergeProp(e); if (e.type == "tabs") {
Tabs.set(e.value);
// 绑定值
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}不能为空`
};
} }
} }
// 设置 tabs 默认值 deep(e);
if (e.type == "tabs") {
Tabs.set(e.value);
}
}); });
// 设置默认值 // 设置默认值
@ -337,113 +346,131 @@ export default defineComponent({
Object.assign(form, data); Object.assign(form, data);
} }
// 渲染表单及表单 // 渲染表单
function renderForm() { function renderFormItem(e: ClForm.Item) {
const { isDisabled } = config._data; const { isDisabled } = config._data;
// 表单项列表 if (e.type == "tabs") {
const children = config.items.map((e) => { return <cl-form-tabs v-model={Tabs.active.value} {...e.props} />;
if (e.type == "tabs") { }
return <cl-form-tabs v-model={Tabs.active.value} {...e.props} />;
}
// 是否隐藏 // 是否隐藏
e._hidden = parseFormHidden(e.hidden, { e._hidden = parseFormHidden(e.hidden, {
scope: form scope: form
}); });
// 分组显示 // 分组显示
const inGroup = const inGroup =
isEmpty(Tabs.active.value) || isEmpty(e.group) isEmpty(Tabs.active.value) || isEmpty(e.group)
? true ? true
: e.group === Tabs.active.value; : e.group === Tabs.active.value;
// 表单项
const FormItem = e.component
? h(
<el-form-item
class={{
"no-label": !(e.renderLabel || e.label),
"has-children": !!e.children
}}
label-width={props.inline ? "auto" : ""}
label={e.label}
prop={e.prop}
rules={isDisabled ? null : e.rules}
v-show={inGroup}
/>,
e.props,
{
label() {
return e.renderLabel
? renderNode(e.renderLabel, {
scope: form,
render: "slot",
slots
})
: e.label;
},
default() {
return (
<div>
<div class="cl-form-item">
{["prepend", "component", "append"]
.filter((k) => e[k])
.map((name) => {
const children = e.children && (
<div class="cl-form-item__children">
<el-row gutter={10}>
{e.children.map(renderFormItem)}
</el-row>
</div>
);
const Item = renderNode(e[name], {
item: e,
prop: e.prop,
scope: form,
slots,
children,
_data: {
isDisabled
}
});
// 表单项
const FormItem = e.component
? h(
<el-form-item
label-width={props.inline ? "auto" : ""}
label={e.label}
prop={e.prop}
rules={isDisabled ? null : e.rules}
v-show={inGroup}
/>,
e.props,
{
label() {
return e.renderLabel
? renderNode(e.renderLabel, {
scope: form,
render: "slot",
slots
})
: e.label;
},
default() {
return (
<div>
<div class="cl-form-item">
{["prepend", "component", "append"].map((name) => {
return ( return (
e[name] && ( <div
<div v-show={!e.collapse}
v-show={!e.collapse} class={[
class={[ `cl-form-item__${name}`,
`cl-form-item__${name}`, {
{ flex1: e.flex !== false
flex1: e.flex !== false }
} ]}
]} style={e[name].style}>
style={e[name].style}> {Item}
{renderNode(e[name], { </div>
item: e,
prop: e.prop,
scope: form,
slots,
_data: {
isDisabled
}
})}
</div>
)
); );
})} })}
</div>
{isBoolean(e.collapse) && (
<div
class="cl-form-item__collapse"
onClick={() => {
Action.collapseItem(e);
}}>
<el-divider content-position="center">
{e.collapse ? "查看更多" : "隐藏内容"}
</el-divider>
</div>
)}
</div> </div>
);
} {isBoolean(e.collapse) && (
<div
class="cl-form-item__collapse"
onClick={() => {
Action.collapseItem(e);
}}>
<el-divider content-position="center">
{e.collapse ? "查看更多" : "隐藏内容"}
</el-divider>
</div>
)}
</div>
);
} }
) }
: null; )
: null;
// 隐藏 // 隐藏
if (e._hidden) { if (e._hidden) {
return null; return null;
} }
// 行内 // 行内
if (props.inline) { if (props.inline) {
return FormItem; return FormItem;
} }
return ( return (
<el-col span={24} key={e.prop} {...e}> <el-col key={e.prop} span={e.span || 24} {...e.col}>
{FormItem} {FormItem}
</el-col> </el-col>
); );
}); }
// 渲染表单
function renderForm() {
// 表单项列表
const children = config.items.map(renderFormItem);
return ( return (
<div class="cl-form__container"> <div class="cl-form__container">

View File

@ -6,6 +6,7 @@ import AdvSearch from "./adv/search";
import Flex from "./flex1"; import Flex from "./flex1";
import Form from "./form"; import Form from "./form";
import FormTabs from "./form-tabs"; import FormTabs from "./form-tabs";
import FormCard from "./form-card";
import MultiDeleteBtn from "./multi-delete-btn"; import MultiDeleteBtn from "./multi-delete-btn";
import Pagination from "./pagination"; import Pagination from "./pagination";
import Query from "./query"; import Query from "./query";
@ -27,6 +28,7 @@ export const components: { [key: string]: any } = {
Flex, Flex,
Form, Form,
FormTabs, FormTabs,
FormCard,
MultiDeleteBtn, MultiDeleteBtn,
Pagination, Pagination,
Query, Query,

View File

@ -6,8 +6,6 @@ import { mergeConfig } from "../../utils";
export default defineComponent({ export default defineComponent({
name: "cl-table", name: "cl-table",
emits: ["selection-change", "sort-change"],
props: { props: {
// 列配置 // 列配置
columns: { columns: {
@ -39,6 +37,8 @@ export default defineComponent({
} }
}, },
emits: ["selection-change", "sort-change"],
setup(props, { emit, expose }) { setup(props, { emit, expose }) {
const { crud } = useCore(); const { crud } = useCore();
const { getValue, style } = useTools(); const { getValue, style } = useTools();

View File

@ -7,8 +7,6 @@ import { mergeConfig } from "../../utils";
export default defineComponent({ export default defineComponent({
name: "cl-upsert", name: "cl-upsert",
emits: ["opened", "closed"],
props: { props: {
// 表单项 // 表单项
items: { items: {
@ -37,6 +35,8 @@ export default defineComponent({
onSubmit: Function onSubmit: Function
}, },
emits: ["opened", "closed"],
setup(props, { slots, expose }) { setup(props, { slots, expose }) {
const { crud } = useCore(); const { crud } = useCore();

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="c"> <div class="c">
<!-- <el-button @click="submit">submit</el-button> --> <!-- <el-button @click="submit">submit</el-button> -->
{{ Form?.form.t2.name }} - {{ disabled }} {{ form?.t2.name }} - {{ disabled }}
<el-input v-model="val" @input="onChange"></el-input> <el-input v-model="val" @input="onChange"></el-input>
<el-button @click="add">a</el-button> <el-button @click="add">a</el-button>
<el-button @click="remove">b</el-button> <el-button @click="remove">b</el-button>
@ -9,10 +9,10 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { computed, onMounted, ref } from "vue"; import { computed, ref } from "vue";
import { useForm, useUpsert } from "../hooks"; import { useForm, useUpsert } from "../hooks";
const props = defineProps({ defineProps({
modelValue: Object, modelValue: Object,
title: String, title: String,
scope: null, scope: null,
@ -27,7 +27,7 @@ const Form = useForm();
const form = computed(() => Upsert.value?.form); const form = computed(() => Upsert.value?.form);
const val = ref<string>(""); const val = ref("");
function onChange(val: string) { function onChange(val: string) {
emit("update:modelValue", val); emit("update:modelValue", val);

View File

@ -21,7 +21,7 @@ export default defineComponent({
const Form = useForm(); const Form = useForm();
const Crud = useCrud(); const Crud = useCrud();
const Upsert = useUpsert({ useUpsert({
onOpened(data) { onOpened(data) {
console.log(data); console.log(data);
} }

View File

@ -17,10 +17,49 @@ const { refs, setRefs } = useRefs();
const Upsert = useUpsert({ const Upsert = useUpsert({
items: [ items: [
{
prop: "user",
component: {
name: "cl-form-card",
props: {
label: "用户信息"
}
},
children: [
{
label: "账号",
prop: "account",
span: 12,
required: true,
component: {
name: "el-input"
}
},
{
label: "密码",
prop: "password",
span: 12,
required: true,
component: {
name: "el-input",
props: {
type: "password"
}
}
},
{
label: "手机号",
prop: "phone",
component: {
name: "el-input"
}
}
]
},
{ {
label: "姓名", label: "姓名",
renderLabel: () => { renderLabel: () => {
return <p>1</p>; return <p style="color: green">姓名</p>;
}, },
prop: "name", prop: "name",
required: true, required: true,

View File

@ -14,6 +14,8 @@ interface Options {
item?: any; item?: any;
// 插槽 // 插槽
slots?: any; slots?: any;
// 子集
children?: any[] & any;
// 自定义 // 自定义
custom?: (vnode: any) => any; custom?: (vnode: any) => any;
// 渲染方式 // 渲染方式
@ -105,7 +107,7 @@ export function parseNode(vnode: any, options: Options): VNode {
// 渲染节点 // 渲染节点
export function renderNode(vnode: any, options: Options) { export function renderNode(vnode: any, options: Options) {
const { item, scope, _data, render } = options || {}; const { item, scope, children, _data, render } = options || {};
if (!vnode) { if (!vnode) {
return null; return null;
@ -174,8 +176,7 @@ export function renderNode(vnode: any, options: Options) {
// jsx 模式 // jsx 模式
if (isObject(vnode)) { if (isObject(vnode)) {
if (vnode.name) { if (vnode.name) {
const { children } = parseExtensionComponent(vnode); return parseNode(vnode, { ...options, children, ...parseExtensionComponent(vnode) });
return parseNode(vnode, { ...options, children });
} else { } else {
if (options.custom) { if (options.custom) {
return options.custom(vnode); return options.custom(vnode);