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();",
" }",
");",
"",
"// 刷新",
"function refresh(params?: any) {",
" Crud.value?.refresh(params);",
"}",
"</script>",
""
],

View File

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

View File

@ -429,6 +429,18 @@ declare namespace ClForm {
size?: "medium" | "default" | "small";
[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;
group?: string;
collapse?: boolean;
@ -443,6 +455,7 @@ declare namespace ClForm {
append?: Render.Component;
rules?: Rule | Rule[];
required?: boolean;
children?: Item[];
[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) => {
function next() {
active.value = value;
@ -146,7 +146,7 @@ export function useTabs({ config, Form }: { config: Config; Form: Form }) {
}
if (isValid) {
let isError: boolean = false;
let isError = false;
const arr = config.items
.filter((e: any) => e.group == active.value && !e._hidden && e.prop)

View File

@ -274,35 +274,44 @@ export default defineComponent({
// 设置表单数据
config.items.map((e) => {
if (e.prop) {
// 解析 prop
if (e.prop.includes(".")) {
e.prop = e.prop.replace(/\./g, "-");
function deep(e: ClForm.Item) {
if (e.prop) {
// 解析 prop
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.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}不能为空`
};
// 设置 tabs 默认值
if (e.type == "tabs") {
Tabs.set(e.value);
}
}
// 设置 tabs 默认值
if (e.type == "tabs") {
Tabs.set(e.value);
}
deep(e);
});
// 设置默认值
@ -337,113 +346,131 @@ export default defineComponent({
Object.assign(form, data);
}
// 渲染表单及表单
function renderForm() {
// 渲染表单
function renderFormItem(e: ClForm.Item) {
const { isDisabled } = config._data;
// 表单项列表
const children = config.items.map((e) => {
if (e.type == "tabs") {
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, {
scope: form
});
// 是否隐藏
e._hidden = parseFormHidden(e.hidden, {
scope: form
});
// 分组显示
const inGroup =
isEmpty(Tabs.active.value) || isEmpty(e.group)
? true
: e.group === Tabs.active.value;
// 分组显示
const inGroup =
isEmpty(Tabs.active.value) || isEmpty(e.group)
? true
: 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 (
e[name] && (
<div
v-show={!e.collapse}
class={[
`cl-form-item__${name}`,
{
flex1: e.flex !== false
}
]}
style={e[name].style}>
{renderNode(e[name], {
item: e,
prop: e.prop,
scope: form,
slots,
_data: {
isDisabled
}
})}
</div>
)
<div
v-show={!e.collapse}
class={[
`cl-form-item__${name}`,
{
flex1: e.flex !== false
}
]}
style={e[name].style}>
{Item}
</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>
);
}
{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) {
return null;
}
// 隐藏
if (e._hidden) {
return null;
}
// 行内
if (props.inline) {
return FormItem;
}
// 行内
if (props.inline) {
return FormItem;
}
return (
<el-col span={24} key={e.prop} {...e}>
{FormItem}
</el-col>
);
});
return (
<el-col key={e.prop} span={e.span || 24} {...e.col}>
{FormItem}
</el-col>
);
}
// 渲染表单
function renderForm() {
// 表单项列表
const children = config.items.map(renderFormItem);
return (
<div class="cl-form__container">

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -17,10 +17,49 @@ const { refs, setRefs } = useRefs();
const Upsert = useUpsert({
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: "姓名",
renderLabel: () => {
return <p>1</p>;
return <p style="color: green">姓名</p>;
},
prop: "name",
required: true,

View File

@ -14,6 +14,8 @@ interface Options {
item?: any;
// 插槽
slots?: any;
// 子集
children?: 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) {
const { item, scope, _data, render } = options || {};
const { item, scope, children, _data, render } = options || {};
if (!vnode) {
return null;
@ -174,8 +176,7 @@ export function renderNode(vnode: any, options: Options) {
// jsx 模式
if (isObject(vnode)) {
if (vnode.name) {
const { children } = parseExtensionComponent(vnode);
return parseNode(vnode, { ...options, children });
return parseNode(vnode, { ...options, children, ...parseExtensionComponent(vnode) });
} else {
if (options.custom) {
return options.custom(vnode);