cl-view-group 添加 tree 参数

This commit is contained in:
神仙都没用 2023-11-24 13:35:40 +08:00
parent 2327e1527f
commit 07b07b9ad7
4 changed files with 187 additions and 58 deletions

View File

@ -0,0 +1,40 @@
import { TreeData } from "element-plus/es/components/tree/src/tree.type";
import { ClViewGroup, useViewGroup } from "/$/base";
import { service } from "/@/cool";
import Node from "element-plus/es/components/tree/src/model/node";
import ClAvatar from "../avatar/index";
export function useDeptViewGroup(options: DeepPartial<ClViewGroup.Options>) {
const { ViewGroup } = useViewGroup({
...options,
service: service.base.sys.department,
enableAdd: false,
label: "员工列表",
tree: {
lazy: true,
onLoad(node: Node, resolve: (data: TreeData) => void) {
if (node.data.id) {
service.base.sys.user.list({ departmentId: node.data.id }).then((res) => {
res.forEach((e) => {
e.isLeaf = true;
e.icon = (
<ClAvatar
size={22}
src={e.headImg}
style={{ marginRight: "6px" }}
/>
);
});
res.unshift(...(node.data.children || []));
resolve(res);
});
}
}
}
});
return {
ViewGroup
};
}

View File

@ -1,9 +1,11 @@
import { provide, ref } from "vue";
import { useParent } from "/@/cool";
import { TreeData } from "element-plus/es/components/tree/src/tree.type";
import Node from "element-plus/es/components/tree/src/model/node";
export declare namespace ClViewGroup {
interface Item {
id: string;
id: any;
name: string;
[key: string]: any;
}
@ -24,6 +26,17 @@ export declare namespace ClViewGroup {
data: {
[key: string]: any;
};
tree: {
lazy?: boolean;
props?: {
label?: string | ((node: Node, data: any) => string);
children?: any;
disabled?: string | ((node: Node, data: any) => string);
isLeaf?: string | ((node: Node, data: any) => string);
class?: any;
};
onLoad?(node: Node, resolve: (data: TreeData) => void): void;
};
service: {
_permission: {
[key: string]: boolean;
@ -35,6 +48,7 @@ export declare namespace ClViewGroup {
list: any[];
pagination: { page: number; size: number; total: number };
}>;
list(data?: any): Promise<any[]>;
update(data: any): Promise<any>;
add(data: any): Promise<any>;
delete(data: any): Promise<any>;

View File

@ -24,56 +24,80 @@
</el-tooltip>
</div>
<div class="list" v-loading="loading">
<div class="data" v-loading="loading">
<el-scrollbar>
<ul
v-infinite-scroll="onMore"
:infinite-scroll-immediate="false"
:infinite-scroll-disabled="loaded"
>
<li
v-for="(item, index) in list"
:key="index"
@click="select(item)"
@contextmenu="
(e) => {
onContextMenu(e, item);
}
"
<!-- 树类型 -->
<template v-if="tree.visible">
<el-tree
class="tree"
highlight-current
:lazy="tree.lazy"
:data="list"
:props="tree.props"
:load="tree.onLoad"
:default-expanded-keys="tree.defaultExpandedKeys"
>
<slot
name="item"
:item="item"
:selected="selected"
:index="index"
>
<div
class="item"
:class="{
'is-active': selected?.id == item.id
}"
>
<slot
name="item-name"
:item="item"
:selected="selected"
:index="index"
>
<span>{{ item.name }}</span>
</slot>
<el-icon
class="arrow-right"
v-show="selected?.id == item.id"
>
<arrow-right-bold />
</el-icon>
<template #default="{ data }">
<div class="item" @click="select(data)">
<component :is="data.icon" v-if="data.icon" />
<span>{{ data[tree.props.label] }}</span>
</div>
</slot>
</li>
</template>
</el-tree>
</template>
<el-empty v-if="list.length == 0" :image-size="80" />
</ul>
<!-- 列表类型 -->
<template v-else>
<ul
class="list"
v-infinite-scroll="onMore"
:infinite-scroll-immediate="false"
:infinite-scroll-disabled="loaded"
>
<li
v-for="(item, index) in list"
:key="index"
@click="select(item)"
@contextmenu="
(e) => {
onContextMenu(e, item);
}
"
>
<slot
name="item"
:item="item"
:selected="selected"
:index="index"
>
<div
class="item"
:class="{
'is-active': selected?.id == item.id
}"
>
<slot
name="item-name"
:item="item"
:selected="selected"
:index="index"
>
<span>{{ item.name }}</span>
</slot>
<el-icon
class="arrow-right"
v-show="selected?.id == item.id"
>
<arrow-right-bold />
</el-icon>
</div>
</slot>
</li>
<el-empty v-if="list.length == 0" :image-size="80" />
</ul>
</template>
</el-scrollbar>
</div>
</div>
@ -127,7 +151,8 @@ import { useBrowser } from "/@/cool";
import { ContextMenu, useForm, setFocus } from "@cool-vue/crud";
import { ElMessage, ElMessageBox } from "element-plus";
import { ClViewGroup } from "./hook";
import { isEmpty } from "lodash-es";
import { isEmpty, merge } from "lodash-es";
import { deepTree } from "/@/cool/utils";
const { browser, onScreenChange } = useBrowser();
const slots = useSlots();
@ -169,6 +194,24 @@ const isExpand = ref(true);
//
const selected = ref<ClViewGroup.Item>();
//
const tree = reactive(
merge(
{
visible: !!config.tree,
props: {
label: "name",
children: "children",
disabled: "disabled",
isLeaf: "isLeaf",
class: ""
},
defaultExpandedKeys: [] as number[]
},
config.tree
)
);
//
function expand(value?: boolean) {
isExpand.value = value === undefined ? !isExpand.value : value;
@ -278,12 +321,19 @@ async function refresh(params?: any) {
loading.value = true;
await config.service
.page({
...reqParams,
...config.data
})
.then((res) => {
const data = {
...reqParams,
...config.data
};
let req;
if (tree.visible) {
req = config.service.list(data).then((res) => {
list.value = deepTree(res);
});
} else {
req = config.service.page(data).then((res) => {
const arr = config.onData?.(res.list) || res.list;
if (reqParams.page == 1) {
@ -292,9 +342,19 @@ async function refresh(params?: any) {
list.value.push(...arr);
}
select(selected.value || list.value[0]);
loaded.value = res.pagination.total <= list.value.length;
});
}
await req
.then(() => {
const item = selected.value || list.value[0];
if (item) {
tree.defaultExpandedKeys = [item.id];
}
select(item);
})
.catch((err) => {
ElMessage.error(err.message);
@ -434,11 +494,25 @@ defineExpose({
}
}
.list {
.data {
height: calc(100% - 40px);
box-sizing: border-box;
ul {
:deep(.el-tree-node__content) {
height: 36px;
margin: 0 5px;
}
.tree {
.item {
display: flex;
align-items: center;
line-height: 1;
width: 100%;
}
}
.list {
height: 100%;
li {

View File

@ -1 +1,2 @@
export * from "../components/view/group/hook";
export * from "../components/dept/hook";