This commit is contained in:
icssoa 2024-02-21 14:05:56 +08:00
parent 5066bd0691
commit 3a55028265
11 changed files with 300 additions and 82 deletions

View File

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

View File

@ -650,8 +650,10 @@ declare namespace ClAdvSearch {
declare namespace ClSearch { declare namespace ClSearch {
interface Config<T = any> { interface Config<T = any> {
inline?: boolean;
items?: ClForm.Item[]; items?: ClForm.Item[];
data?: T; data?: T;
props?: ElementPlus.FormProps;
resetBtn?: boolean; resetBtn?: boolean;
onLoad?(data: T): void; onLoad?(data: T): void;
onSearch?(data: T, options: { next: ClCrud.Service["api"]["page"] }): void; onSearch?(data: T, options: { next: ClCrud.Service["api"]["page"] }): void;

View File

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

View File

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

View File

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

View File

@ -150,32 +150,26 @@
} }
.el-select { .el-select {
min-width: 100px; min-width: 120px;
} }
} }
.cl-search { .cl-search {
margin-bottom: 0px !important; margin-bottom: 0px !important;
.el-form--inline { .el-form:not(.el-form--label-top) {
.el-form-item { .cl-search__btns {
margin: 0 10px 10px 0; .el-form-item__label {
display: none;
}
}
}
.el-date-editor { .el-form:not(.el-form--inline) {
box-sizing: border-box; .cl-search__btns {
.el-range-input {
&:nth-child(2) {
margin-left: 5px; margin-left: 5px;
} }
} }
}
&:last-child {
margin-right: 0;
}
}
}
} }
.cl-adv-btn { .cl-adv-btn {
@ -254,39 +248,6 @@
min-height: 0; 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 { &-item {
display: flex; display: flex;
@ -329,10 +290,6 @@
} }
} }
.el-form-item {
margin-bottom: 18px;
}
.el-table__header tr { .el-table__header tr {
line-height: normal; line-height: normal;
} }
@ -346,6 +303,78 @@
.cl-crud { .cl-crud {
line-height: normal; 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 { .cl-form-tabs {

View File

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

View File

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

View File

@ -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>

View File

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

View File

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