icssoa 1 gadu atpakaļ
vecāks
revīzija
3a55028265

+ 1 - 1
package.json

@@ -9,7 +9,7 @@
 		"lint:eslint": "eslint \"./src/**/*.{vue,ts,tsx}\" --fix"
 	},
 	"dependencies": {
-		"@cool-vue/crud": "^7.1.12",
+		"@cool-vue/crud": "^7.1.13",
 		"@element-plus/icons-vue": "^2.1.0",
 		"@vueuse/core": "^10.4.0",
 		"@wangeditor/editor": "^5.1.23",

+ 4 - 2
packages/crud/index.d.ts

@@ -40,8 +40,8 @@ declare type obj = {
 declare type DeepPartial<T> = T extends Function
 	? T
 	: T extends object
-	  ? { [P in keyof T]?: DeepPartial<T[P]> }
-	  : T;
+		? { [P in keyof T]?: DeepPartial<T[P]> }
+		: T;
 
 // 合并
 declare type Merge<A, B> = Omit<A, keyof B> & B;
@@ -650,8 +650,10 @@ declare namespace ClAdvSearch {
 
 declare namespace ClSearch {
 	interface Config<T = any> {
+		inline?: boolean;
 		items?: ClForm.Item[];
 		data?: T;
+		props?: ElementPlus.FormProps;
 		resetBtn?: boolean;
 		onLoad?(data: T): void;
 		onSearch?(data: T, options: { next: ClCrud.Service["api"]["page"] }): void;

+ 1 - 1
packages/crud/package.json

@@ -1,6 +1,6 @@
 {
 	"name": "@cool-vue/crud",
-	"version": "7.1.12",
+	"version": "7.1.13",
 	"private": false,
 	"main": "./dist/index.umd.min.js",
 	"typings": "types/index.d.ts",

+ 23 - 17
packages/crud/src/components/form/index.tsx

@@ -451,11 +451,17 @@ export default defineComponent({
 				}
 			);
 
+			let span = e.span || style.form.span;
+
+			if (browser.isMini) {
+				span = 24;
+			}
+
 			// 是否行内
 			const Item = props.inline ? (
 				FormItem
 			) : (
-				<el-col span={e.span || style.form.span} {...e.col} v-show={inGroup && !e._hidden}>
+				<el-col span={span} {...e.col} v-show={inGroup && !e._hidden}>
 					{FormItem}
 				</el-col>
 			);
@@ -468,6 +474,12 @@ export default defineComponent({
 			// 表单项列表
 			const children = config.items.map(renderFormItem);
 
+			// 表单标签位置
+			const labelPosition =
+				browser.isMini && !props.inline
+					? "top"
+					: config.props.labelPosition || style.form.labelPosition;
+
 			return (
 				<div class="cl-form__container" ref={setRefs("form")}>
 					{h(
@@ -486,29 +498,23 @@ export default defineComponent({
 						/>,
 						{
 							...config.props,
-							labelPosition:
-								browser.isMini && !props.inline
-									? "top"
-									: config.props.labelPosition || style.form.labelPosition
+							labelPosition
 						},
 						{
 							default: () => {
-								return (
-									<div class="cl-form__items">
-										{/* 前 */}
-										{slots.prepend && slots.prepend({ scope: form })}
+								const items = [
+									slots.prepend && slots.prepend({ scope: form }),
+									children,
+									slots.append && slots.append({ scope: form })
+								];
 
-										{/* 项 */}
+								return (
+									<div class="cl-form__items" v-loading={loading.value}>
 										{props.inline ? (
-											children
+											items
 										) : (
-											<el-row gutter={10} v-loading={loading.value}>
-												{children}
-											</el-row>
+											<el-row gutter={10}>{items}</el-row>
 										)}
-
-										{/* 后 */}
-										{slots.append && slots.append({ scope: form })}
 									</div>
 								);
 							}

+ 12 - 2
packages/crud/src/components/search/index.tsx

@@ -7,6 +7,15 @@ export default defineComponent({
 	name: "cl-search",
 
 	props: {
+		inline: {
+			type: Boolean,
+			default: true
+		},
+		props: {
+			type: Object,
+			default: () => {}
+		},
+
 		// 表单值
 		data: {
 			type: Object,
@@ -114,6 +123,7 @@ export default defineComponent({
 				op: {
 					hidden: true
 				},
+				props: config.props,
 				items: config.items,
 				form: config.data,
 				on: {
@@ -129,12 +139,12 @@ export default defineComponent({
 				isEmpty(config.items) || (
 					<div class="cl-search">
 						{h(
-							<cl-form ref={Form} inner inline />,
+							<cl-form ref={Form} inner inline={config.inline} />,
 							{},
 							{
 								append() {
 									return (
-										<el-form-item>
+										<el-form-item label=" " class="cl-search__btns">
 											{/* 搜索按钮 */}
 											<el-button
 												type="primary"

+ 82 - 53
packages/crud/src/static/index.scss

@@ -150,30 +150,24 @@
 	}
 
 	.el-select {
-		min-width: 100px;
+		min-width: 120px;
 	}
 }
 
 .cl-search {
 	margin-bottom: 0px !important;
 
-	.el-form--inline {
-		.el-form-item {
-			margin: 0 10px 10px 0;
-
-			.el-date-editor {
-				box-sizing: border-box;
-
-				.el-range-input {
-					&:nth-child(2) {
-						margin-left: 5px;
-					}
-				}
+	.el-form:not(.el-form--label-top) {
+		.cl-search__btns {
+			.el-form-item__label {
+				display: none;
 			}
+		}
+	}
 
-			&:last-child {
-				margin-right: 0;
-			}
+	.el-form:not(.el-form--inline) {
+		.cl-search__btns {
+			margin-left: 5px;
 		}
 	}
 }
@@ -254,39 +248,6 @@
 		min-height: 0;
 	}
 
-	.el-form-item {
-		.el-input-number {
-			&__decrease,
-			&__increase {
-				border: 0;
-				background-color: transparent;
-			}
-		}
-
-		&__label {
-			.el-tooltip {
-				i {
-					margin-left: 5px;
-				}
-			}
-		}
-
-		&__content {
-			min-width: 0px;
-
-			& > div {
-				width: 100%;
-			}
-		}
-
-		&.no-label {
-			& > .el-form-item__label {
-				padding: 0;
-				display: none;
-			}
-		}
-	}
-
 	&-item {
 		display: flex;
 
@@ -329,10 +290,6 @@
 			}
 		}
 
-		.el-form-item {
-			margin-bottom: 18px;
-		}
-
 		.el-table__header tr {
 			line-height: normal;
 		}
@@ -346,6 +303,78 @@
 	.cl-crud {
 		line-height: normal;
 	}
+
+	.el-form-item {
+		margin-bottom: 18px;
+
+		.el-input-number {
+			&__decrease,
+			&__increase {
+				border: 0;
+				background-color: transparent;
+			}
+		}
+
+		&__label {
+			.el-tooltip {
+				i {
+					margin-left: 5px;
+				}
+			}
+		}
+
+		&__content {
+			min-width: 0px;
+
+			& > div {
+				width: 100%;
+			}
+		}
+	}
+
+	&:not(.el-form--label-top) {
+		&.no-label {
+			& > .el-form-item__label {
+				padding: 0;
+				display: none;
+			}
+		}
+	}
+
+	.el-form--label-top {
+		.el-form-item__label {
+			min-height: 22px;
+		}
+	}
+
+	.el-form--inline {
+		.cl-form__items {
+			display: flex;
+			flex-wrap: wrap;
+		}
+
+		.el-form-item {
+			margin: 0 10px 10px 0;
+
+			.el-date-editor {
+				box-sizing: border-box;
+
+				.el-range-input {
+					&:nth-child(2) {
+						margin-left: 5px;
+					}
+				}
+			}
+
+			.el-select {
+				width: 173px;
+			}
+
+			&:last-child {
+				margin-right: 0;
+			}
+		}
+	}
 }
 
 .cl-form-tabs {

+ 1 - 1
packages/crud/types/components/form/index.d.ts

@@ -5,7 +5,7 @@ declare const _default: import("vue").DefineComponent<{
     inner: BooleanConstructor;
     inline: BooleanConstructor;
 }>>, {
-    inner: boolean;
     inline: boolean;
+    inner: boolean;
 }, {}>;
 export default _default;

+ 18 - 0
packages/crud/types/components/search/index.d.ts

@@ -1,6 +1,14 @@
 /// <reference types="../index" />
 import { PropType } from "vue";
 declare const _default: import("vue").DefineComponent<{
+    inline: {
+        type: BooleanConstructor;
+        default: boolean;
+    };
+    props: {
+        type: ObjectConstructor;
+        default: () => void;
+    };
     data: {
         type: ObjectConstructor;
         default: () => {};
@@ -16,6 +24,14 @@ declare const _default: import("vue").DefineComponent<{
     onLoad: FunctionConstructor;
     onSearch: FunctionConstructor;
 }, () => any, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "reset"[], "reset", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
+    inline: {
+        type: BooleanConstructor;
+        default: boolean;
+    };
+    props: {
+        type: ObjectConstructor;
+        default: () => void;
+    };
     data: {
         type: ObjectConstructor;
         default: () => {};
@@ -34,6 +50,8 @@ declare const _default: import("vue").DefineComponent<{
     onReset?: ((...args: any[]) => any) | undefined;
 }, {
     items: ClForm.Item<any>[];
+    props: Record<string, any>;
+    inline: boolean;
     data: Record<string, any>;
     resetBtn: boolean;
 }, {}>;

+ 152 - 0
src/modules/demo/views/crud/components/search/layout.vue

@@ -0,0 +1,152 @@
+<template>
+	<div class="scope">
+		<div class="h">
+			<el-tag size="small" effect="dark">layout</el-tag>
+			<span>布局</span>
+		</div>
+
+		<div class="c">
+			<el-button @click="open">预览</el-button>
+			<demo-code :files="['search/layout.vue']" />
+
+			<!-- 自定义表格组件 -->
+			<cl-dialog v-model="visible" title="布局" width="80%">
+				<cl-crud ref="Crud">
+					<!--【很重要】搜索组件 -->
+					<cl-search ref="Search" :reset-btn="true" />
+
+					<cl-row>
+						<cl-table ref="Table" />
+					</cl-row>
+
+					<cl-row>
+						<cl-flex1 />
+						<cl-pagination />
+					</cl-row>
+				</cl-crud>
+			</cl-dialog>
+		</div>
+
+		<div class="f">
+			<span class="date">2024-01-01</span>
+		</div>
+	</div>
+</template>
+
+<script setup lang="ts">
+import { useCrud, useSearch, useTable } from "@cool-vue/crud";
+import { ref } from "vue";
+import { useDict } from "/$/dict";
+
+const { dict } = useDict();
+
+// cl-crud 配置
+const Crud = useCrud(
+	{
+		service: "test"
+	},
+	(app) => {
+		app.refresh();
+	}
+);
+
+// cl-table 配置
+const Table = useTable({
+	autoHeight: false,
+	contextMenu: ["refresh"],
+
+	columns: [
+		{
+			label: "姓名",
+			prop: "name",
+			minWidth: 140
+		},
+		{
+			label: "手机号",
+			prop: "phone",
+			minWidth: 140
+		},
+		{
+			label: "工作",
+			prop: "occupation",
+			dict: dict.get("occupation"),
+			minWidth: 140
+		},
+		{
+			label: "创建时间",
+			prop: "createTime",
+			minWidth: 160,
+			sortable: "desc"
+		}
+	]
+});
+
+// cl-search 配置
+//【很重要】该组件基于 cl-form 故很多示例都可复用
+const Search = useSearch({
+	// 取消行内表单模式
+	inline: false,
+
+	// 表单参数
+	props: {
+		labelPosition: "top"
+	},
+
+	// 配置如 cl-form 一样
+	items: [
+		{
+			label: "姓名",
+			prop: "name",
+			span: 6,
+			component: {
+				name: "el-input",
+				props: {
+					clearable: true,
+
+					// 值改变的时候刷新列表
+					onChange(val: string) {
+						refresh({
+							name: val,
+							page: 1
+						});
+					}
+				}
+			}
+		},
+		{
+			label: "手机号",
+			prop: "phone",
+			span: 6,
+			component: {
+				name: "el-input",
+				props: {
+					clearable: true
+				}
+			}
+		},
+		{
+			label: "工作",
+			prop: "occupation",
+			span: 6,
+			component: {
+				name: "cl-select",
+				props: {
+					tree: true,
+					checkStrictly: true,
+					options: dict.get("occupation")
+				}
+			}
+		}
+	]
+});
+
+function refresh(params?: any) {
+	Crud.value?.refresh(params);
+}
+
+const visible = ref(false);
+
+function open() {
+	visible.value = true;
+}
+</script>

+ 2 - 1
src/modules/demo/views/crud/index.vue

@@ -71,6 +71,7 @@ import UpsertHook from "./components/upsert/hook/index.vue";
 
 import SearchBase from "./components/search/base.vue";
 import SearchCustom from "./components/search/custom.vue";
+import SearchLayout from "./components/search/layout.vue";
 
 import AdvSearchBase from "./components/adv-search/base.vue";
 import AdvSearchCustom from "./components/adv-search/custom.vue";
@@ -165,7 +166,7 @@ const list = [
 		children: [
 			{
 				label: "基础",
-				children: [SearchBase, SearchCustom]
+				children: [SearchBase, SearchCustom, SearchLayout]
 			}
 		]
 	},

+ 4 - 4
yarn.lock

@@ -282,10 +282,10 @@
     "@babel/helper-validator-identifier" "^7.22.20"
     to-fast-properties "^2.0.0"
 
-"@cool-vue/crud@^7.1.12":
-  version "7.1.12"
-  resolved "https://registry.yarnpkg.com/@cool-vue/crud/-/crud-7.1.12.tgz#e1b703da12f3f4519ffdde73538d1d7a642fdb56"
-  integrity sha512-a5+9uBCQWUnibtpZU+q+gQDyZCAvjx2/bC1aFDM6XQ3+3C/4A0jxeZessBlXh3DaleYbLu8Kp2dBty8mVuy//g==
+"@cool-vue/crud@^7.1.13":
+  version "7.1.13"
+  resolved "https://registry.npmjs.org/@cool-vue/crud/-/crud-7.1.13.tgz#8c150d0f0ccbe466628a1190ac19219054e93cca"
+  integrity sha512-e5Mt5HjYpr89sF+dMqudGHrcSP8KVdzNrn8hHEqgcpc1J7oAxyMtS8Wq2XjJY4XkxSZP7xeBEC6yqNgSQOYKyw==
   dependencies:
     array.prototype.flat "^1.2.4"
     core-js "^3.21.1"