小改主题

This commit is contained in:
神仙都没用 2024-12-26 17:32:45 +08:00
parent e0b43109bc
commit 69d0f2d756
42 changed files with 753 additions and 404 deletions

View File

@ -12,7 +12,7 @@
"format": "prettier --write src/" "format": "prettier --write src/"
}, },
"dependencies": { "dependencies": {
"@cool-vue/crud": "^7.2.5", "@cool-vue/crud": "^7.2.7",
"@element-plus/icons-vue": "^2.3.1", "@element-plus/icons-vue": "^2.3.1",
"@vueuse/core": "^11.1.0", "@vueuse/core": "^11.1.0",
"@wangeditor/editor": "^5.1.23", "@wangeditor/editor": "^5.1.23",

View File

@ -160,6 +160,8 @@ declare namespace ClCrud {
seeMore: string; seeMore: string;
hideContent: string; hideContent: string;
nonEmpty: string; nonEmpty: string;
collapse: string;
expand: string;
[key: string]: string; [key: string]: string;
} }
@ -669,6 +671,7 @@ declare namespace ClSearch {
data?: T; data?: T;
props?: ElementPlus.FormProps; props?: ElementPlus.FormProps;
resetBtn?: boolean; resetBtn?: boolean;
collapse?: boolean;
Form?: ClForm.Ref; Form?: ClForm.Ref;
onChange?(data: T, prop: string): void; onChange?(data: T, prop: string): void;
onLoad?(data: T): void; onLoad?(data: T): void;

View File

@ -1,6 +1,6 @@
{ {
"name": "@cool-vue/crud", "name": "@cool-vue/crud",
"version": "7.2.5", "version": "7.2.7",
"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",
@ -8,7 +8,7 @@
"dev": "vue-cli-service serve", "dev": "vue-cli-service serve",
"build": "vue-cli-service build", "build": "vue-cli-service build",
"tsc": "tsc --watch", "tsc": "tsc --watch",
"dist": "tsc && yarn build --target lib --name index ./src/index.ts" "dist": "tsc && pnpm build --target lib --name index ./src/index.ts"
}, },
"dependencies": { "dependencies": {
"@element-plus/icons-vue": "^2.3.1", "@element-plus/icons-vue": "^2.3.1",

View File

@ -1,7 +1,7 @@
import { ElMessageBox, ElMessage } from "element-plus"; import { ElMessageBox, ElMessage } from "element-plus";
import { Mitt } from "../../utils/mitt"; import { Mitt } from "../../utils/mitt";
import { ref } from "vue"; import { ref } from "vue";
import { isArray, isFunction } from "lodash-es"; import { assign, isArray, isFunction } from "lodash-es";
import { merge } from "../../utils"; import { merge } from "../../utils";
interface Options { interface Options {
@ -56,7 +56,7 @@ export function useHelper({ config, crud, mitt }: Options) {
return new Promise((success, error) => { return new Promise((success, error) => {
// 合并请求参数 // 合并请求参数
const reqParams = paramsReplace(Object.assign(crud.params, params)); const reqParams = paramsReplace(assign(crud.params, params));
// Loading // Loading
crud.loading = true; crud.loading = true;

View File

@ -1,3 +1,4 @@
import { assign } from "lodash-es";
import { dataset } from "../../../utils"; import { dataset } from "../../../utils";
export function useAction({ export function useAction({
@ -48,7 +49,7 @@ export function useAction({
break; break;
case "props": case "props":
Object.assign(d.component.props, data); assign(d.component.props, data);
break; break;
case "hidden": case "hidden":
@ -60,7 +61,7 @@ export function useAction({
break; break;
default: default:
Object.assign(d, data); assign(d, data);
break; break;
} }
} else { } else {

View File

@ -1,5 +1,5 @@
import { defineComponent, h, nextTick, toRef, watch } from "vue"; import { defineComponent, h, nextTick, toRef, watch } from "vue";
import { cloneDeep, isBoolean } from "lodash-es"; import { assign, cloneDeep, isBoolean, keys } from "lodash-es";
import { useAction, useForm, usePlugins, useTabs } from "./helper"; import { useAction, useForm, usePlugins, useTabs } from "./helper";
import { useBrowser, useConfig, useElApi, useRefs } from "../../hooks"; import { useBrowser, useConfig, useElApi, useRefs } from "../../hooks";
import { getValue, merge } from "../../utils"; import { getValue, merge } from "../../utils";
@ -205,7 +205,7 @@ export default defineComponent({
Tabs.toGroup({ Tabs.toGroup({
refs, refs,
config, config,
prop: Object.keys(error)[0] prop: keys(error)[0]
}); });
} }
}); });
@ -347,7 +347,7 @@ export default defineComponent({
deep(e); deep(e);
}); });
Object.assign(form, data); assign(form, data);
} }
// 渲染表单项 // 渲染表单项
@ -575,9 +575,7 @@ export default defineComponent({
custom() { custom() {
return ( return (
<el-button <el-button
text
type={e.type} type={e.type}
bg
{...e.props} {...e.props}
onClick={() => { onClick={() => {
e.onClick({ scope: form }); e.onClick({ scope: form });

View File

@ -1,5 +1,4 @@
import { useConfig, useCore, useForm } from "../../hooks"; import { useConfig, useCore, useForm, useProxy, useRefs } from "../../hooks";
import { isEmpty, keys } from "lodash-es";
import { import {
onMounted, onMounted,
PropType, PropType,
@ -9,10 +8,12 @@ import {
reactive, reactive,
inject, inject,
mergeProps, mergeProps,
watch, nextTick,
watchEffect onUnmounted
} from "vue"; } from "vue";
import { useApi } from "../form/helper"; import { useApi } from "../form/helper";
import { Search, Refresh, Bottom, Top } from "@element-plus/icons-vue";
import { mitt } from "../../utils/mitt";
export default defineComponent({ export default defineComponent({
name: "cl-search", name: "cl-search",
@ -24,7 +25,7 @@ export default defineComponent({
}, },
props: { props: {
type: Object, type: Object,
default: () => {} default: () => { }
}, },
// 表单值 // 表单值
@ -47,6 +48,9 @@ export default defineComponent({
default: false default: false
}, },
// 是否需要折叠
collapse: Boolean,
// 初始化 // 初始化
onLoad: Function, onLoad: Function,
@ -58,6 +62,7 @@ export default defineComponent({
setup(props, { slots, expose, emit }) { setup(props, { slots, expose, emit }) {
const { crud } = useCore(); const { crud } = useCore();
const { refs, setRefs } = useRefs()
const { style } = useConfig(); const { style } = useConfig();
// 配置 // 配置
@ -71,6 +76,12 @@ export default defineComponent({
// 加载中 // 加载中
const loading = ref(false); const loading = ref(false);
// 展开
const isExpand = ref(!config.collapse);
// 显示展开、收起按钮
const showExpandBtn = ref(false);
// 搜索 // 搜索
function search(params?: any) { function search(params?: any) {
const form = Form.value?.getForm(); const form = Form.value?.getForm();
@ -123,14 +134,43 @@ export default defineComponent({
emit("reset", d); emit("reset", d);
} }
expose({ // 收起、展开
function expand() {
isExpand.value = !isExpand.value;
nextTick(() => {
crud?.["cl-table"].calcMaxHeight()
})
}
// 判断展开状态
function onExpand() {
if (config.collapse) {
const el = refs.form?.querySelector(".cl-form__items");
if (el) {
showExpandBtn.value = el.clientHeight > 84;
}
}
}
function onResize() {
onExpand();
}
const ctx = {
search, search,
reset, reset,
Form, Form,
config,
...useApi({ Form }) ...useApi({ Form })
}); };
useProxy(ctx);
expose(ctx);
onMounted(() => { onMounted(() => {
// 打开表单
Form.value?.open({ Form.value?.open({
op: { op: {
hidden: true hidden: true
@ -141,18 +181,51 @@ export default defineComponent({
on: { on: {
open(data) { open(data) {
config.onLoad?.(data); config.onLoad?.(data);
onExpand();
}, },
change(data, prop) { change(data, prop) {
config.onChange?.(data, prop); config.onChange?.(data, prop);
} }
} }
}); });
mitt.on("resize", onResize);
}); });
onUnmounted(() => {
mitt.off("resize", onResize);
})
return () => { return () => {
const btnEl = (
<el-form-item label=" " class="cl-search__btns">
{/* 重置按钮 */}
{config.resetBtn && (
<el-button size={style.size} icon={Refresh} onClick={reset}>
{crud.dict.label.reset}
</el-button>
)}
{/* 搜索按钮 */}
<el-button
type="primary"
loading={loading.value}
size={style.size}
icon={Search}
onClick={() => {
search();
}}>
{crud.dict.label.search}
</el-button>
{/* 自定义按钮 */}
{slots?.buttons?.(Form.value?.form)}
</el-form-item>
);
return ( return (
isEmpty(config.items) || ( <div class={["cl-search", isExpand.value ? "is-expand" : "is-collapse"]}>
<div class="cl-search"> <div class="cl-search__form" ref={setRefs("form")}>
{h( {h(
<cl-form <cl-form
ref={Form} ref={Form}
@ -163,36 +236,28 @@ export default defineComponent({
{}, {},
{ {
append() { append() {
return ( return config.collapse ? null : btnEl;
<el-form-item label=" " class="cl-search__btns">
{/* 搜索按钮 */}
<el-button
type="primary"
loading={loading.value}
size={style.size}
onClick={() => {
search();
}}>
{crud.dict.label.search}
</el-button>
{/* 重置按钮 */}
{config.resetBtn && (
<el-button size={style.size} onClick={reset}>
{crud.dict.label.reset}
</el-button>
)}
{/* 自定义按钮 */}
{slots?.buttons?.(Form.value?.form)}
</el-form-item>
);
}, },
...slots ...slots
} }
)} )}
</div> </div>
)
{config.collapse && (
<div class="cl-search__more">
{showExpandBtn.value && (
<el-button onClick={expand}>
<span>{isExpand.value ? crud.dict.label.collapse : crud.dict.label.expand}</span>
<el-icon>{isExpand.value ? <Top /> : <Bottom />}</el-icon>
</el-button>
)}
<cl-flex1 />
{btnEl}
</div>
)}
</div>
); );
}; };
} }

View File

@ -1,3 +1,4 @@
import { assign } from "lodash-es";
import { TestService } from "../test/service"; import { TestService } from "../test/service";
import { watch, ref, nextTick, getCurrentInstance, Ref, inject, provide } from "vue"; import { watch, ref, nextTick, getCurrentInstance, Ref, inject, provide } from "vue";
@ -107,7 +108,7 @@ export function useUpsert<T = any>(options?: ClUpsert.Options<T>) {
isChild isChild
}); });
Object.assign(val.config, event); assign(val.config, event);
} }
} }
}, },

View File

@ -28,5 +28,7 @@ export default {
deselect: "Deselect", deselect: "Deselect",
seeMore: "See more", seeMore: "See more",
hideContent: "Hide content", hideContent: "Hide content",
nonEmpty: "Cannot be empty" nonEmpty: "Cannot be empty",
collapse: "Collapse",
expand: "Expand"
}; };

View File

@ -27,5 +27,7 @@ export default {
deselect: "選択解除", deselect: "選択解除",
seeMore: "詳細を表示", seeMore: "詳細を表示",
hideContent: "コンテンツを非表示", hideContent: "コンテンツを非表示",
nonEmpty: "空にできません" nonEmpty: "空にできません",
collapse: "折り畳む",
expand: "展開"
}; };

View File

@ -27,5 +27,7 @@ export default {
deselect: "取消选择", deselect: "取消选择",
seeMore: "查看更多", seeMore: "查看更多",
hideContent: "隐藏内容", hideContent: "隐藏内容",
nonEmpty: "不能为空" nonEmpty: "不能为空",
collapse: "收起",
expand: "展开更多"
}; };

View File

@ -27,5 +27,7 @@ export default {
deselect: "取消選擇", deselect: "取消選擇",
seeMore: "查看更多", seeMore: "查看更多",
hideContent: "隱藏內容", hideContent: "隱藏內容",
nonEmpty: "不能為空" nonEmpty: "不能為空",
collapse: "收起",
expand: "展開"
}; };

View File

@ -170,6 +170,30 @@
margin-left: 5px; margin-left: 5px;
} }
} }
.cl-search__btns {
.el-button + .el-button {
margin-left: 10px;
}
}
&__more {
display: flex;
align-items: center;
justify-content: space-between;
padding: 5px 0;
.el-form-item {
margin-bottom: 0;
}
}
&.is-collapse {
.cl-search__form {
max-height: 84px;
overflow: hidden;
}
}
} }
.cl-adv-btn { .cl-adv-btn {

View File

@ -1,4 +1,4 @@
import { orderBy } from "lodash-es"; import { assign, orderBy } from "lodash-es";
import { uuid } from "../utils"; import { uuid } from "../utils";
const userList = [ const userList = [
@ -160,7 +160,7 @@ class TestService {
const item = userList.find((e) => e.id == params.id); const item = userList.find((e) => e.id == params.id);
if (item) { if (item) {
Object.assign(item, params); assign(item, params);
} }
} }

View File

@ -1,5 +1,5 @@
import { isRef, mergeProps } from "vue"; import { isRef, mergeProps } from "vue";
import { flatMap, isArray, isFunction, isNumber, isString, mergeWith } from "lodash-es"; import { assign, flatMap, isArray, isFunction, isNumber, isString, mergeWith } from "lodash-es";
export function isObject(val: any) { export function isObject(val: any) {
return val !== null && typeof val === "object"; return val !== null && typeof val === "object";
@ -49,7 +49,7 @@ export function dataset(obj: any, key: string, value: any): any {
return d[n]; return d[n];
} else { } else {
if (isObject(value)) { if (isObject(value)) {
Object.assign(d[n], value); assign(d[n], value);
} else { } else {
d[n] = value; d[n] = value;
} }

View File

@ -128,15 +128,12 @@ export function renderNode(vnode: any, options: Options) {
let placeholder = ""; let placeholder = "";
switch (item.component?.name) { switch (item.component?.name) {
case "el-input":
placeholder = config.dict.label.placeholder;
break;
case "el-select": case "el-select":
placeholder = config.dict.label.placeholderSelect; placeholder = config.dict.label.placeholderSelect;
break; break;
default: default:
placeholder = config.dict.label.placeholder;
break; break;
} }

View File

@ -21,6 +21,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
type: BooleanConstructor; type: BooleanConstructor;
default: boolean; default: boolean;
}; };
collapse: BooleanConstructor;
onLoad: FunctionConstructor; onLoad: FunctionConstructor;
onSearch: FunctionConstructor; onSearch: FunctionConstructor;
}>, () => any, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "reset"[], "reset", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{ }>, () => any, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "reset"[], "reset", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
@ -44,6 +45,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
type: BooleanConstructor; type: BooleanConstructor;
default: boolean; default: boolean;
}; };
collapse: BooleanConstructor;
onLoad: FunctionConstructor; onLoad: FunctionConstructor;
onSearch: FunctionConstructor; onSearch: FunctionConstructor;
}>> & Readonly<{ }>> & Readonly<{
@ -54,5 +56,6 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
inline: boolean; inline: boolean;
data: Record<string, any>; data: Record<string, any>;
resetBtn: boolean; resetBtn: boolean;
collapse: boolean;
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>; }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
export default _default; export default _default;

View File

@ -28,5 +28,7 @@ declare const _default: {
seeMore: string; seeMore: string;
hideContent: string; hideContent: string;
nonEmpty: string; nonEmpty: string;
collapse: string;
expand: string;
}; };
export default _default; export default _default;

View File

@ -29,6 +29,8 @@ export declare const locale: {
seeMore: string; seeMore: string;
hideContent: string; hideContent: string;
nonEmpty: string; nonEmpty: string;
collapse: string;
expand: string;
}; };
ja: { ja: {
op: string; op: string;
@ -60,6 +62,8 @@ export declare const locale: {
seeMore: string; seeMore: string;
hideContent: string; hideContent: string;
nonEmpty: string; nonEmpty: string;
collapse: string;
expand: string;
}; };
zhCn: { zhCn: {
op: string; op: string;
@ -91,6 +95,8 @@ export declare const locale: {
seeMore: string; seeMore: string;
hideContent: string; hideContent: string;
nonEmpty: string; nonEmpty: string;
collapse: string;
expand: string;
}; };
zhTw: { zhTw: {
op: string; op: string;
@ -122,5 +128,7 @@ export declare const locale: {
seeMore: string; seeMore: string;
hideContent: string; hideContent: string;
nonEmpty: string; nonEmpty: string;
collapse: string;
expand: string;
}; };
}; };

View File

@ -28,5 +28,7 @@ declare const _default: {
seeMore: string; seeMore: string;
hideContent: string; hideContent: string;
nonEmpty: string; nonEmpty: string;
collapse: string;
expand: string;
}; };
export default _default; export default _default;

View File

@ -28,5 +28,7 @@ declare const _default: {
seeMore: string; seeMore: string;
hideContent: string; hideContent: string;
nonEmpty: string; nonEmpty: string;
collapse: string;
expand: string;
}; };
export default _default; export default _default;

View File

@ -28,5 +28,7 @@ declare const _default: {
seeMore: string; seeMore: string;
hideContent: string; hideContent: string;
nonEmpty: string; nonEmpty: string;
collapse: string;
expand: string;
}; };
export default _default; export default _default;

609
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
import { defineComponent, h, resolveComponent, ref, reactive, watch } from 'vue'; import { defineComponent, h, resolveComponent, ref, reactive, watch } from 'vue';
import { isComponent } from '/@/cool/utils'; import { isComponent } from '/@/cool/utils';
import { assign } from 'lodash-es';
export default defineComponent({ export default defineComponent({
name: 'cl-editor', name: 'cl-editor',
@ -17,7 +18,7 @@ export default defineComponent({
watch(Editor, v => { watch(Editor, v => {
if (v) { if (v) {
Object.assign(ex, v); assign(ex, v);
} }
}); });

View File

@ -16,7 +16,6 @@
:options="data" :options="data"
clearable clearable
filterable filterable
allow-create
@change="onPathChange" @change="onPathChange"
/> />

View File

@ -111,9 +111,10 @@ watch(
.a-menu { .a-menu {
padding: 5px 0 0 15px; padding: 5px 0 0 15px;
background-color: var(--view-bg-color); background-color: var(--view-bg-color);
height: 36px;
.el-menu { .el-menu {
height: 36px; height: 100%;
background-color: transparent; background-color: transparent;
border: 0; border: 0;

View File

@ -32,6 +32,13 @@
</div> </div>
</el-scrollbar> </el-scrollbar>
</div> </div>
<ul class="app-process__op">
<li class="item" @click="toFull">
<cl-svg name="screen-normal" v-if="app.isFull" />
<cl-svg name="screen-full" v-else />
</li>
</ul>
</div> </div>
</template> </template>
@ -44,7 +51,7 @@ import { ContextMenu } from '@cool-vue/crud';
import { useBase, type Process } from '/$/base'; import { useBase, type Process } from '/$/base';
const { refs, setRefs, route, router, mitt } = useCool(); const { refs, setRefs, route, router, mitt } = useCool();
const { process } = useBase(); const { process, app } = useBase();
// //
function toRefresh() { function toRefresh() {
@ -61,6 +68,11 @@ function toBack() {
router.back(); router.back();
} }
//
function toFull() {
app.setFull(!app.isFull);
}
// //
function toPath() { function toPath() {
const d = process.list.find(e => e.active); const d = process.list.find(e => e.active);
@ -173,7 +185,6 @@ onMounted(() => {
&__op { &__op {
list-style: none; list-style: none;
margin-right: 5px;
.item { .item {
display: inline-flex; display: inline-flex;
@ -201,6 +212,7 @@ onMounted(() => {
flex: 1; flex: 1;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
margin: 0 5px;
} }
&__scroller { &__scroller {

View File

@ -58,6 +58,7 @@ const lastName = computed(() => last(list.value)?.meta?.label);
<style lang="scss" scoped> <style lang="scss" scoped>
.route-nav { .route-nav {
white-space: nowrap; white-space: nowrap;
user-select: none;
:deep(.el-breadcrumb) { :deep(.el-breadcrumb) {
margin: 0 10px; margin: 0 10px;

View File

@ -135,6 +135,8 @@ onMounted(() => {
padding: 0 10px; padding: 0 10px;
background-color: var(--el-bg-color); background-color: var(--el-bg-color);
border-bottom: 1px solid var(--el-border-color-extra-light); border-bottom: 1px solid var(--el-border-color-extra-light);
box-sizing: border-box;
transition: height 0.2s ease-in-out;
&__collapse { &__collapse {
display: flex; display: flex;
@ -181,7 +183,7 @@ onMounted(() => {
.name { .name {
white-space: nowrap; white-space: nowrap;
margin-right: 15px; margin-right: 10px;
} }
} }
} }

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="app-layout" :class="{ collapse: app.isFold }"> <div class="app-layout" :class="{ collapse: app.isFold, full: app.isFull }">
<div class="app-layout__mask" @click="app.fold(true)"></div> <div class="app-layout__mask" @click="app.fold(true)"></div>
<div class="app-layout__left"> <div class="app-layout__left">
@ -101,5 +101,22 @@ const { app } = useBase();
} }
} }
} }
&.full {
.app-layout__left {
width: 0;
}
.app-layout__right {
width: 100%;
:deep(.a-menu),
:deep(.app-topbar) {
padding: 0;
height: 0;
overflow: hidden;
}
}
}
} }
</style> </style>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg
t="1735182661616"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="1065"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="256"
height="256"
>
<path
d="M938.666667 42.666667a42.666667 42.666667 0 0 1 42.368 37.674666L981.333333 85.333333v213.333334a42.666667 42.666667 0 0 1-85.034666 4.992L896 298.666667V128h-170.666667a42.666667 42.666667 0 0 1-42.368-37.674667L682.666667 85.333333a42.666667 42.666667 0 0 1 37.674666-42.368L725.333333 42.666667h213.333334z m0 640a42.666667 42.666667 0 0 1 42.368 37.674666L981.333333 725.333333v213.333334a42.666667 42.666667 0 0 1-37.674666 42.368L938.666667 981.333333h-213.333334a42.666667 42.666667 0 0 1-4.992-85.034666L725.333333 896h170.666667v-170.666667a42.666667 42.666667 0 0 1 37.674667-42.368L938.666667 682.666667zM85.333333 682.666667a42.666667 42.666667 0 0 1 42.368 37.674666L128 725.333333v170.666667h170.666667a42.666667 42.666667 0 0 1 42.368 37.674667L341.333333 938.666667a42.666667 42.666667 0 0 1-37.674666 42.368L298.666667 981.333333H85.333333a42.666667 42.666667 0 0 1-42.368-37.674666L42.666667 938.666667v-213.333334a42.666667 42.666667 0 0 1 42.666666-42.666666zM298.666667 42.666667a42.666667 42.666667 0 0 1 4.992 85.034666L298.666667 128H128v170.666667a42.666667 42.666667 0 0 1-37.674667 42.368L85.333333 341.333333a42.666667 42.666667 0 0 1-42.368-37.674666L42.666667 298.666667V85.333333a42.666667 42.666667 0 0 1 37.674666-42.368L85.333333 42.666667h213.333334zM725.333333 256H298.666667a42.666667 42.666667 0 0 0-42.666667 42.666667v426.666666a42.666667 42.666667 0 0 0 42.666667 42.666667h426.666666a42.666667 42.666667 0 0 0 42.666667-42.666667V298.666667a42.666667 42.666667 0 0 0-42.666667-42.666667z m-42.666666 85.333333v341.333334H341.333333V341.333333h341.333334z"
p-id="1066"
></path>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,17 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg
t="1735182665079"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="1226"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="256"
height="256"
>
<path
d="M224 768a42.666667 42.666667 0 0 1 42.368 37.674667L266.666667 810.666667v138.666666a42.666667 42.666667 0 0 1-85.034667 4.992l-0.298667-4.992V853.333333H85.333333a42.666667 42.666667 0 0 1-42.368-37.674666L42.666667 810.666667a42.666667 42.666667 0 0 1 37.674666-42.368L85.333333 768h138.666667z m725.333333 0a42.666667 42.666667 0 0 1 4.992 85.034667L949.333333 853.333333H853.333333v96a42.666667 42.666667 0 0 1-37.674666 42.368L810.666667 992a42.666667 42.666667 0 0 1-42.368-37.674667L768 949.333333V810.666667a42.666667 42.666667 0 0 1 37.674667-42.368L810.666667 768h138.666666zM725.333333 256a42.666667 42.666667 0 0 1 42.666667 42.666667v426.666666a42.666667 42.666667 0 0 1-42.666667 42.666667H298.666667a42.666667 42.666667 0 0 1-42.666667-42.666667V298.666667a42.666667 42.666667 0 0 1 42.666667-42.666667z m-42.666666 85.333333H341.333333v341.333334h341.333334V341.333333zM224 42.666667a42.666667 42.666667 0 0 1 42.368 37.674666L266.666667 85.333333v138.666667a42.666667 42.666667 0 0 1-37.674667 42.368l-4.992 0.298667H85.333333a42.666667 42.666667 0 0 1-4.992-85.034667L85.333333 181.333333h96V85.333333a42.666667 42.666667 0 0 1 37.674667-42.368L224 42.666667zM810.666667 42.666667a42.666667 42.666667 0 0 1 42.368 37.674666L853.333333 85.333333v96h96a42.666667 42.666667 0 0 1 42.368 37.674667l0.298667 4.992a42.666667 42.666667 0 0 1-37.674667 42.368l-4.992 0.298667H810.666667a42.666667 42.666667 0 0 1-42.368-37.674667L768 224V85.333333a42.666667 42.666667 0 0 1 42.666667-42.666666z"
p-id="1227"
></path>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -13,14 +13,15 @@ export const useAppStore = defineStore('app', function () {
...config.app ...config.app
}); });
// 设置基本信息
function set(data: any) {
merge(info, data);
storage.set('__app__', info);
}
// 是否折叠 // 是否折叠
const isFold = ref(false); const isFold = ref(false);
// 事件
const events = reactive<{ [key: string]: any[] }>({
hasToken: []
});
// 折叠 // 折叠
function fold(v?: boolean) { function fold(v?: boolean) {
if (v === undefined) { if (v === undefined) {
@ -30,12 +31,19 @@ export const useAppStore = defineStore('app', function () {
isFold.value = v; isFold.value = v;
} }
// 设置基本信息 // 是否全屏
function set(data: any) { const isFull = ref(false);
merge(info, data);
storage.set('__app__', info); // 设置全屏
function setFull(state: boolean) {
isFull.value = state;
} }
// 事件
const events = reactive<{ [key: string]: any[] }>({
hasToken: []
});
// 添加事件 // 添加事件
function addEvent(name: string, func: any) { function addEvent(name: string, func: any) {
if (func) { if (func) {
@ -52,6 +60,8 @@ export const useAppStore = defineStore('app', function () {
info, info,
isFold, isFold,
fold, fold,
isFull,
setFull,
events, events,
set, set,
addEvent addEvent

View File

@ -3,28 +3,28 @@
<div class="dept-tree__header"> <div class="dept-tree__header">
<el-text>组织架构</el-text> <el-text>组织架构</el-text>
<ul class="dept-tree__op"> <div class="dept-tree__op">
<li @click="refresh()"> <div class="item" @click="refresh()">
<el-tooltip content="刷新"> <el-tooltip content="刷新">
<el-icon> <el-icon>
<refresh-icon /> <refresh-icon />
</el-icon> </el-icon>
</el-tooltip> </el-tooltip>
</li> </div>
<li v-if="drag && !browser.isMini" @click="isDrag = true"> <div class="item" v-if="drag && !browser.isMini" @click="isDrag = true">
<el-tooltip content="拖动排序"> <el-tooltip content="拖动排序">
<el-icon> <el-icon>
<operation /> <operation />
</el-icon> </el-icon>
</el-tooltip> </el-tooltip>
</li> </div>
<li v-show="isDrag" class="no"> <div class="btns" v-show="isDrag">
<el-button size="small" @click="treeOrder(true)">保存</el-button> <el-button type="success" size="small" @click="treeOrder(true)">保存</el-button>
<el-button size="small" @click="treeOrder(false)">取消</el-button> <el-button size="small" @click="treeOrder(false)">取消</el-button>
</li> </div>
</ul> </div>
</div> </div>
<div class="dept-tree__container" @contextmenu.stop.prevent="onContextMenu"> <div class="dept-tree__container" @contextmenu.stop.prevent="onContextMenu">
@ -392,21 +392,32 @@ onMounted(function () {
&__op { &__op {
display: flex; display: flex;
align-items: center;
li { .item {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
list-style: none; list-style: none;
margin-left: 5px; margin-left: 5px;
padding: 5px;
cursor: pointer; cursor: pointer;
border-radius: 4px; border-radius: 4px;
font-size: 16px;
height: 26px;
width: 26px;
&:not(.no):hover { &:hover {
background-color: var(--el-fill-color-light); background-color: var(--el-fill-color-light);
} }
} }
.btns {
margin-left: 10px;
.el-button + .el-button {
margin-left: 10px;
}
}
} }
&__container { &__container {

View File

@ -20,7 +20,7 @@
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="tsx">
import { useForm } from '@cool-vue/crud'; import { useForm } from '@cool-vue/crud';
const Form = useForm(); const Form = useForm();

View File

@ -0,0 +1,120 @@
<template>
<div class="scope">
<div class="h">
<el-tag size="small" effect="dark">collapse</el-tag>
<span>折叠</span>
</div>
<div class="c">
<el-button @click="open">预览</el-button>
<demo-code :files="['search/collapse.vue']" />
<!-- 折叠表格组件 -->
<cl-dialog v-model="visible" title="折叠" width="80%">
<cl-crud ref="Crud">
<!--很重要搜索组件 -->
<div class="search">
<cl-search ref="Search" :reset-btn="true" collapse />
</div>
<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-12-26</span>
</div>
</div>
</template>
<script setup lang="ts">
import { useCrud, useSearch, useTable } from '@cool-vue/crud';
import { ref } from 'vue';
import { useDict } from '/$/dict';
import { range } from 'lodash-es';
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: 170,
sortable: 'desc'
}
]
});
// cl-search
const Search = useSearch({
items: [
...range(20).map(i => {
return {
label: '输入框',
prop: `T${i + 1}`,
component: {
name: 'el-input'
}
};
})
]
});
function refresh(params?: any) {
Crud.value?.refresh(params);
}
const visible = ref(false);
function open() {
visible.value = true;
}
</script>
<style lang="scss" scoped>
.search {
padding: 15px;
background-color: var(--view-bg-color);
border-radius: 8px;
margin-bottom: 10px;
}
</style>

View File

@ -27,6 +27,7 @@
<script lang="ts" setup name="demo-crud"> <script lang="ts" setup name="demo-crud">
import { ref, onActivated } from 'vue'; import { ref, onActivated } from 'vue';
import { useCool } from '/@/cool';
import CrudBase from './components/crud/base.vue'; import CrudBase from './components/crud/base.vue';
import CrudAll from './components/crud/all.vue'; import CrudAll from './components/crud/all.vue';
@ -72,6 +73,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 SearchCollapse from './components/search/collapse.vue';
import SearchLayout from './components/search/layout.vue'; import SearchLayout from './components/search/layout.vue';
import AdvSearchBase from './components/adv-search/base.vue'; import AdvSearchBase from './components/adv-search/base.vue';
@ -79,7 +81,6 @@ import AdvSearchCustom from './components/adv-search/custom.vue';
import OtherTsx from './components/other/tsx'; import OtherTsx from './components/other/tsx';
import OtherTips from './components/other/tips.vue'; import OtherTips from './components/other/tips.vue';
import { useCool } from '/@/cool';
const { route, router } = useCool(); const { route, router } = useCool();
@ -168,7 +169,7 @@ const list = [
children: [ children: [
{ {
label: '基础', label: '基础',
children: [SearchBase, SearchCustom, SearchLayout] children: [SearchBase, SearchCustom, SearchCollapse, SearchLayout]
} }
] ]
}, },

View File

@ -48,8 +48,9 @@
v-if="item.demo && !isEmpty(item.demo)" v-if="item.demo && !isEmpty(item.demo)"
round round
@click="det.open(item)" @click="det.open(item)"
>示例</el-button
> >
示例
</el-button>
</div> </div>
</div> </div>
</el-col> </el-col>
@ -74,7 +75,7 @@
<script lang="ts" setup name="helper-plugins-vue"> <script lang="ts" setup name="helper-plugins-vue">
import { reactive, nextTick, markRaw } from 'vue'; import { reactive, nextTick, markRaw } from 'vue';
import { module, useCool } from '/@/cool'; import { module, useCool } from '/@/cool';
import { isEmpty, isFunction, isString } from 'lodash-es'; import { isEmpty, isFunction, isString, startsWith } from 'lodash-es';
const { router } = useCool(); const { router } = useCool();
@ -117,7 +118,11 @@ const det = reactive({
det.active = 0; det.active = 0;
if (isString(item.demo)) { if (isString(item.demo)) {
router.push(item.demo); if (startsWith(item.demo, 'http')) {
window.open(item.demo);
} else {
router.push(item.demo);
}
} else { } else {
det.visible = true; det.visible = true;
det.title = item.label; det.title = item.label;

View File

@ -0,0 +1,22 @@
import { defineComponent, } from 'vue';
export default defineComponent({
name: 'cl-render',
props: {
modelValue: null,
scope: Object,
prop: String,
disabled: Boolean,
isDisabled: Boolean,
row: Object,
column: Object,
placeholder: String
},
setup(props, { slots, }) {
return () => {
return slots.default?.(props);
};
}
});

View File

@ -5,8 +5,8 @@ import Crud, { locale, setFocus } from '@cool-vue/crud';
import '@cool-vue/crud/dist/index.css'; import '@cool-vue/crud/dist/index.css';
// 调试、自定义crud // 调试、自定义crud
// import Crud, { locale, setFocus } from "/~/crud/src"; // import Crud, { locale, setFocus } from '/~/crud/src';
// import "/~/crud/src/static/index.scss"; // import '/~/crud/src/static/index.scss';
export default (): Merge<ModuleConfig, CrudOptions> => { export default (): Merge<ModuleConfig, CrudOptions> => {
return { return {
@ -14,8 +14,8 @@ export default (): Merge<ModuleConfig, CrudOptions> => {
label: 'CRUD', label: 'CRUD',
description: '快速增删改查及一系列辅助组件', description: '快速增删改查及一系列辅助组件',
author: 'COOL', author: 'COOL',
version: '1.0.7', version: '1.1.0',
updateTime: '2024-05-26', updateTime: '2024-12-26',
demo: '/demo/crud', demo: '/demo/crud',
// 组件全注册 // 组件全注册

View File

@ -9,6 +9,7 @@ export default (): ModuleConfig => {
author: 'COOL', author: 'COOL',
version: '1.0.0', version: '1.0.0',
updateTime: '2024-07-22', updateTime: '2024-07-22',
demo: 'https://echarts.apache.org/examples/zh/index.html',
install(app) { install(app) {
app.component('v-chart', VueECharts); app.component('v-chart', VueECharts);
} }

View File

@ -10,6 +10,7 @@ export default (): ModuleConfig => {
author: 'COOL', author: 'COOL',
version: '1.0.0', version: '1.0.0',
updateTime: '2024-07-22', updateTime: '2024-07-22',
demo: 'https://element-plus.org/zh-CN/component/overview.html',
install(app) { install(app) {
app.use(ElementPlus); app.use(ElementPlus);
} }