mirror of
https://github.com/cool-team-official/cool-admin-vue.git
synced 2025-12-13 14:12:50 +00:00
cl-form 添加 children 参数
This commit is contained in:
parent
02dad133a8
commit
520fd74d2b
5
.vscode/crud.code-snippets
vendored
5
.vscode/crud.code-snippets
vendored
@ -58,6 +58,11 @@
|
|||||||
" app.refresh();",
|
" app.refresh();",
|
||||||
" }",
|
" }",
|
||||||
");",
|
");",
|
||||||
|
"",
|
||||||
|
"// 刷新",
|
||||||
|
"function refresh(params?: any) {",
|
||||||
|
" Crud.value?.refresh(params);",
|
||||||
|
"}",
|
||||||
"</script>",
|
"</script>",
|
||||||
""
|
""
|
||||||
],
|
],
|
||||||
|
|||||||
@ -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",
|
||||||
|
|||||||
13
packages/crud/index.d.ts
vendored
13
packages/crud/index.d.ts
vendored
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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">
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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();
|
||||||
|
|||||||
@ -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();
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user