@hzab/hierarchical-statistics 1.0.0-beta → 1.0.0-beta2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,15 +1,15 @@
1
- # @hzab/component-boilerplate@0.1.0
2
- - fix: 删掉@hzab/list-render-mobile
3
- - fix: 新增移动端下拉刷新
4
- # @hzab/component-boilerplate@0.0.6
5
- - fix: 修复跳转同路由,listRender参数依赖没有更新问题
6
- # @hzab/component-boilerplate@0.0.5
7
- - fix: 暴露面包屑回显数据breadcrumbData
8
- # @hzab/component-boilerplate@0.0.4
9
- - fix: dependencies改成peerDependencies
10
- - fix: 样式index.module.less改成index.less引入
11
- - fix: 新增className外层类名传递
12
- # @hzab/component-boilerplate@0.0.3
13
- - fix: 适配mobile的ItemRender自定义字段
14
- # @hzab/component-boilerplate@0.0.1
1
+ # @hzab/component-boilerplate@0.1.0
2
+ - fix: 删掉@hzab/list-render-mobile
3
+ - fix: 列表用ScrollList组件
4
+ # @hzab/component-boilerplate@0.0.6
5
+ - fix: 修复跳转同路由,listRender参数依赖没有更新问题
6
+ # @hzab/component-boilerplate@0.0.5
7
+ - fix: 暴露面包屑回显数据breadcrumbData
8
+ # @hzab/component-boilerplate@0.0.4
9
+ - fix: dependencies改成peerDependencies
10
+ - fix: 样式index.module.less改成index.less引入
11
+ - fix: 新增className外层类名传递
12
+ # @hzab/component-boilerplate@0.0.3
13
+ - fix: 适配mobile的ItemRender自定义字段
14
+ # @hzab/component-boilerplate@0.0.1
15
15
  组件初始化
package/README.md CHANGED
@@ -1,127 +1,123 @@
1
- # @hzab/group-user-selector
2
-
3
- 组件模板
4
-
5
- - node@16.16.0
6
-
7
- - 注意:首次克隆先执行 npm run prepare 命令
8
-
9
- # 组件
10
-
11
- ## 示例
12
-
13
- ```jsx
14
- import InfiniteListUi from "@hzab/hierarchical-statistics/src/components/InfiniteListUi";
15
- <InfiniteListUi
16
- ref={listRef}
17
- style={{
18
- maxWidth: "400px",
19
- }}
20
- listModal={
21
- new DataModel({
22
- getListApi: "/api/v1/sysOrg/getDeptTree",
23
- query: {
24
- pageNum: 1,
25
- pageSize: 8,
26
- },
27
- })
28
- }
29
- fieldList={{
30
- value: "orgId",
31
- label: "orgName",
32
- }}
33
- Slots={{
34
- renderItem: (record) => (
35
- <div
36
- onClick={() => {
37
- listRef.current.handleNodeClick(record);
38
- }}
39
- style={{ padding: "12px 30px", border: "1px solid red" }}
40
- >
41
- <div>{record?.orgName}</div>
42
- </div>
43
- )
44
- }}
45
- virtualPagedListProps={{
46
- height: 300,
47
- dynamicHeightMode: true,
48
- noMoreComponent: <div>没有更多数据了</div>,
49
- }}
50
- ></InfiniteListUi>
51
- ```
52
-
53
- ## API
54
-
55
- ### InfoPanel Attributes
56
-
57
- | 参数 | 类型 | 必填 | 默认值 | 说明 |
58
- | -------------------- | ------------------------------| ----- | --------- | ----------------------------------- |
59
- | listModal | Object | | - | 列表数据模型DataModel,必须包含getListApi |
60
- | breadModel | Object | 否 | - | 回显数据模型DataModel,必须包含getApi |
61
- | showHome | Boolean | 否 | - | 是否显示面包屑首页 |
62
- | onNodeClick | function(item) | 否 | - | item点击事件 |
63
- | onNodeSelect | function(item) | 否 | - | item选中事件 |
64
- | onBreadcrumbClick | function(item) | 否 | - | 回显点击事件 |
65
- | fieldList | {value: number, label: string}| 否 | - | 列表默认关联字段 |
66
- | fieldBreadcrumb | {value: number, label: string}| 否 | - | 面包屑显示对应关联字段 |
67
- | parentField | string | 否 | parentId | 请求接口关联字段 |
68
- | homeBreadcrumb | string | 否 | 首页 | 面包屑首页名称 |
69
- | style | CSSProperties | 否 | - | 组件外层样式 |
70
- | listStyle | CSSProperties | 否 | - | 列表外层样式 |
71
- | readcrumbStyle | CSSProperties | 否 | - | 面包屑外层样式 |
72
- | separatorStyle | CSSProperties | 否 | - | 面包屑分割符样式 |
73
- | virtualPagedListProps| Object | | - | virtualPagedList 配置 |
74
- | separator | string | 否 | - | 分隔符 默认"-" |
75
- | Slots | Object | 是 | - | 插槽 |
76
- | isPullRefresh | Boolean | 否 | false | 移动端是否可以下拉刷新 |
77
-
78
-
79
-
80
- ### Slots
81
-
82
- | 参数 | 类型 | 必填 | 默认值 | 说明 |
83
- | -------------------- | -------------------| ----- | ------- | ----------------------------------- |
84
- | fixRenderCenter | Function | 否 | - | 固定在头部 面包屑和列表之间插槽 |
85
- | itemRender | Function | 是 | - | 自定义列表项 |
86
-
87
- # 组件开发流程
88
-
89
- - 在 config/webpack.config.js 中按需修改 library 配置的文件名
90
- - 在 config/webpack.config.js 中按需修改 alias 配置的包名,便于本地调试
91
- - 在 tsconfig.json 中按需修改 paths 配置的包名,解决 ts 报错问题
92
- - npm run dev
93
-
94
- ## 文件目录
95
-
96
- - example 本地开发测试代码
97
- - src 组件源码
98
-
99
- ## 命令
100
-
101
- - Mac 执行该命令,设置 pre-commit 为可执行文件
102
-
103
- - npm run mac-chmod
104
- - chmod +x .husky && chmod +x .husky/pre-commit
105
-
106
- - 生成文档:npm run docs
107
- - 本地运行:npm run dev
108
- - 打包编译:npm run build
109
-
110
- ## 发布
111
-
112
- - 注意:示例代码生效,但发布之后未生效。确认是否执行了编译!!!
113
-
114
- - 编译组件:npm run build
115
- - 命令:npm publish --access public
116
- - 发布目录:
117
- - src
118
-
119
- ## 配置
120
-
121
- ### 配置文件
122
-
123
- - 本地配置文件:config/config.js
124
-
125
- ### webpack 配置文件
126
-
127
- - config/webpack.config.js
1
+ # @hzab/group-user-selector
2
+
3
+ 组件模板
4
+
5
+ - node@16.16.0
6
+
7
+ - 注意:首次克隆先执行 npm run prepare 命令
8
+
9
+ # 组件
10
+
11
+ ## 示例
12
+
13
+ ```jsx
14
+ import InfiniteListUi from "@hzab/hierarchical-statistics/src/components/InfiniteListUi";
15
+ <InfiniteListUi
16
+ ref={listRef}
17
+ style={{
18
+ maxWidth: "400px",
19
+ }}
20
+ listModal={
21
+ new DataModel({
22
+ getListApi: "/api/v1/sysOrg/getDeptTree",
23
+ query: {
24
+ pageNum: 1,
25
+ pageSize: 8,
26
+ },
27
+ })
28
+ }
29
+ fieldList={{
30
+ value: "orgId",
31
+ label: "orgName",
32
+ }}
33
+ Slots={{
34
+ renderItem: ({ item }) => (
35
+ <div
36
+ onClick={() => {
37
+ listRef.current.handleNodeClick(item);
38
+ }}
39
+ style={{ padding: "12px 30px", border: "1px solid red" }}
40
+ >
41
+ <div>{item?.orgName}</div>
42
+ </div>
43
+ )
44
+ }}
45
+ scrollListProps={{
46
+ noMoreComponent: <div>没有更多数据了</div>,
47
+ }}
48
+ ></InfiniteListUi>
49
+ ```
50
+
51
+ ## API
52
+
53
+ ### InfoPanel Attributes
54
+
55
+ | 参数 | 类型 | 必填 | 默认值 | 说明 |
56
+ | -------------------- | ------------------------------| ----- | --------- | ----------------------------------- |
57
+ | listModal | Object | | - | 列表数据模型DataModel,必须包含getListApi |
58
+ | breadModel | Object | | - | 回显数据模型DataModel,必须包含getApi |
59
+ | showHome | Boolean | | - | 是否显示面包屑首页 |
60
+ | onNodeClick | function(item) | 否 | - | item点击事件 |
61
+ | onNodeSelect | function(item) | 否 | - | item选中事件 |
62
+ | onBreadcrumbClick | function(item) | 否 | - | 回显点击事件 |
63
+ | fieldList | {value: number, label: string}| 否 | - | 列表默认关联字段 |
64
+ | fieldBreadcrumb | {value: number, label: string}| 否 | - | 面包屑显示对应关联字段 |
65
+ | parentField | string | 否 | parentId | 请求接口关联字段 |
66
+ | homeBreadcrumb | string | 否 | 首页 | 面包屑首页名称 |
67
+ | style | CSSProperties | 否 | - | 组件外层样式 |
68
+ | listStyle | CSSProperties | 否 | - | 列表外层样式 |
69
+ | readcrumbStyle | CSSProperties | 否 | - | 面包屑外层样式 |
70
+ | separatorStyle | CSSProperties | 否 | - | 面包屑分割符样式 |
71
+ | scrollListProps | Object | 否 | - | scrollListProps 配置 |
72
+ | separator | string | 否 | - | 分隔符 默认"-" |
73
+ | Slots | Object | | - | 插槽 |
74
+
75
+
76
+ ### Slots
77
+
78
+ | 参数 | 类型 | 必填 | 默认值 | 说明 |
79
+ | -------------------- | -------------------| ----- | ------- | ----------------------------------- |
80
+ | fixRenderCenter | Function | 否 | - | 固定在头部 面包屑和列表之间插槽 |
81
+ | itemRender | Function | 是 | - | 自定义列表项 |
82
+
83
+ # 组件开发流程
84
+
85
+ - config/webpack.config.js 中按需修改 library 配置的文件名
86
+ - 在 config/webpack.config.js 中按需修改 alias 配置的包名,便于本地调试
87
+ - 在 tsconfig.json 中按需修改 paths 配置的包名,解决 ts 报错问题
88
+ - npm run dev
89
+
90
+ ## 文件目录
91
+
92
+ - example 本地开发测试代码
93
+ - src 组件源码
94
+
95
+ ## 命令
96
+
97
+ - Mac 执行该命令,设置 pre-commit 为可执行文件
98
+
99
+ - npm run mac-chmod
100
+ - chmod +x .husky && chmod +x .husky/pre-commit
101
+
102
+ - 生成文档:npm run docs
103
+ - 本地运行:npm run dev
104
+ - 打包编译:npm run build
105
+
106
+ ## 发布
107
+
108
+ - 注意:示例代码生效,但发布之后未生效。确认是否执行了编译!!!
109
+
110
+ - 编译组件:npm run build
111
+ - 命令:npm publish --access public
112
+ - 发布目录:
113
+ - src
114
+
115
+ ## 配置
116
+
117
+ ### 配置文件
118
+
119
+ - 本地配置文件:config/config.js
120
+
121
+ ### webpack 配置文件
122
+
123
+ - config/webpack.config.js
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hzab/hierarchical-statistics",
3
- "version": "1.0.0-beta",
3
+ "version": "1.0.0-beta2",
4
4
  "description": "",
5
5
  "main": "src",
6
6
  "scripts": {
@@ -49,9 +49,6 @@
49
49
  },
50
50
  "peerDependencies": {
51
51
  "@hzab/data-model": ">=1.7.5",
52
- "@hzab/headless-components": ">=0.0.3"
53
- },
54
- "dependencies": {
55
- "react-window-pull-refresh": "^1.0.9"
52
+ "@hzab/headless-components": ">=0.0.6"
56
53
  }
57
54
  }
@@ -1,25 +1,25 @@
1
- import "../index.less";
2
- const BreadcrumbUI = (props: any) => {
3
- const { readcrumbStyle, separatorStyle, separator, breadcrumbData, handleBreadcrumbClick } = props;
4
- return (
5
- <div className={`breadcrumb-box`} style={readcrumbStyle}>
6
- {breadcrumbData.map((item, index) => (
7
- <div className="breadcrumb-item" key={index}>
8
- <span
9
- className="breadcrumb-title"
10
- style={{ color: breadcrumbData.length - 1 == index ? "#aeadad" : "#403ef5" }}
11
- key={item?.value}
12
- onClick={() => handleBreadcrumbClick(item, index)}
13
- >
14
- {item?.label}
15
- </span>
16
- <span className="breadcrumb-separator" style={separatorStyle}>
17
- {breadcrumbData?.length - 1 != index ? separator : ""}
18
- </span>
19
- </div>
20
- ))}
21
- </div>
22
- );
23
- };
24
-
25
- export default BreadcrumbUI;
1
+ import "../index.less";
2
+ const BreadcrumbUI = (props: any) => {
3
+ const { readcrumbStyle, separatorStyle, separator, breadcrumbData, handleBreadcrumbClick } = props;
4
+ return (
5
+ <div className={`breadcrumb-box`} style={readcrumbStyle}>
6
+ {breadcrumbData.map((item, index) => (
7
+ <div className="breadcrumb-item" key={index}>
8
+ <span
9
+ className="breadcrumb-title"
10
+ style={{ color: breadcrumbData.length - 1 == index ? "#aeadad" : "#403ef5" }}
11
+ key={item?.value}
12
+ onClick={() => handleBreadcrumbClick(item, index)}
13
+ >
14
+ {item?.label}
15
+ </span>
16
+ <span className="breadcrumb-separator" style={separatorStyle}>
17
+ {breadcrumbData?.length - 1 != index ? separator : ""}
18
+ </span>
19
+ </div>
20
+ ))}
21
+ </div>
22
+ );
23
+ };
24
+
25
+ export default BreadcrumbUI;
@@ -1,103 +1,87 @@
1
- import { ForwardedRef, forwardRef, useImperativeHandle, useRef } from "react";
2
- import { PullToRefresh } from "react-window-pull-refresh";
3
- import VirtualPagedList from "@hzab/headless-components/src/VirtualPagedList";
4
- import { ConfigProvider, Spin, Empty, Button } from "antd";
5
- import { useInfiniteList } from "../../use-infinite-list";
6
- import Breadcrumb from "../Breadcrumb";
7
- import { InfiniteListProps, InfiniteListInstance } from "../../type";
8
- import "../index.less";
9
- const InfiniteListUi = (props: InfiniteListProps, ref: ForwardedRef<InfiniteListInstance>) => {
10
- const {
11
- states: {
12
- listModal,
13
- breadModel,
14
- readcrumbStyle,
15
- separatorStyle,
16
- separator,
17
- style,
18
- selectedLoadIdNode,
19
- breadcrumbData,
20
- Slots,
21
- loading,
22
- listStyle,
23
- listRef,
24
- virtualPagedListProps,
25
- className,
26
- refreshKey,
27
- isPullRefresh,
28
- },
29
- actions: { handleSelectId, handleNodeClick, handleBreadcrumbClick, fetchBreadData, handleListRefresh },
30
- } = useInfiniteList({ ...props });
31
-
32
- useImperativeHandle(ref, () => ({
33
- handleNodeClick,
34
- handleSelectId,
35
- listRef: listRef?.current,
36
- listModal,
37
- breadModel,
38
- fetchBreadData,
39
- breadcrumbData,
40
- handleListRefresh,
41
- }));
42
-
43
- const loadData = async (pageNum) => {
44
- listModal.query = { ...listModal.query, pageNum: pageNum };
45
- const res = await listModal?.getList();
46
- const list = res?.list ?? [];
47
- return {
48
- list,
49
- isMore: res?.pagination?.total > (pageNum - 1) * listModal.query.pageSize + res?.list?.length ? true : false,
50
- };
51
- };
52
-
53
- const JsxDom = (propJsx) => {
54
- let jsx = <></>;
55
- if (isPullRefresh) {
56
- jsx = (
57
- <PullToRefresh handleRefresh={handleListRefresh}>
58
- <VirtualPagedList
59
- key={refreshKey}
60
- ref={listRef}
61
- {...virtualPagedListProps}
62
- renderItem={Slots.renderItem}
63
- loadMoreItems={loadData}
64
- />
65
- </PullToRefresh>
66
- );
67
- } else {
68
- jsx = (
69
- <VirtualPagedList
70
- key={refreshKey}
71
- ref={listRef}
72
- {...virtualPagedListProps}
73
- renderItem={Slots.renderItem}
74
- loadMoreItems={loadData}
75
- />
76
- );
77
- }
78
- return jsx;
79
- };
80
-
81
- return (
82
- <div className={`infinite-level-box ${className || ""}`} style={style}>
83
- <Spin spinning={loading}>
84
- {/* 面包屑导航 */}
85
- <div className="infinite-level-breadcrumb-position">
86
- <Breadcrumb
87
- readcrumbStyle={readcrumbStyle}
88
- separatorStyle={separatorStyle}
89
- separator={separator}
90
- breadcrumbData={breadcrumbData}
91
- handleBreadcrumbClick={handleBreadcrumbClick}
92
- ></Breadcrumb>
93
- {Slots?.fixRenderCenter && <Slots.fixRenderCenter></Slots.fixRenderCenter>}
94
- </div>
95
- <div className="infinite-level-list-box" style={listStyle}>
96
- <JsxDom></JsxDom>
97
- </div>
98
- </Spin>
99
- </div>
100
- );
101
- };
102
-
103
- export default forwardRef<InfiniteListInstance, InfiniteListProps>(InfiniteListUi);
1
+ import { ForwardedRef, forwardRef, useImperativeHandle, useRef } from "react";
2
+ import ScrollList from "@hzab/headless-components/src/ScrollList";
3
+ import { ConfigProvider, Spin, Empty, Button } from "antd";
4
+ import { useInfiniteList } from "../../use-infinite-list";
5
+ import Breadcrumb from "../Breadcrumb";
6
+ import { InfiniteListProps, InfiniteListInstance } from "../../type";
7
+ import "../index.less";
8
+ const InfiniteListUi = (props: InfiniteListProps, ref: ForwardedRef<InfiniteListInstance>) => {
9
+ const {
10
+ states: {
11
+ listModal,
12
+ breadModel,
13
+ readcrumbStyle,
14
+ separatorStyle,
15
+ separator,
16
+ style,
17
+ breadcrumbData,
18
+ Slots,
19
+ loading,
20
+ listStyle,
21
+ scrollListProps,
22
+ className,
23
+ refreshKey,
24
+ },
25
+ actions: { handleSelectId, handleNodeClick, handleBreadcrumbClick, fetchBreadData, handleListRefresh },
26
+ } = useInfiniteList({ ...props });
27
+
28
+ useImperativeHandle(ref, () => ({
29
+ handleNodeClick,
30
+ handleSelectId,
31
+ listModal,
32
+ breadModel,
33
+ fetchBreadData,
34
+ breadcrumbData,
35
+ handleListRefresh,
36
+ }));
37
+
38
+ const loadData = async (pageNum) => {
39
+ listModal.query = { ...listModal.query, pageNum: pageNum };
40
+ const res = await listModal?.getList();
41
+ const list = res?.list ?? [];
42
+ const pageSize = listModal.query.pageSize ?? 10;
43
+ return {
44
+ list,
45
+ isMore: res?.pagination?.total > (pageNum - 1) * pageSize + res?.list?.length ? true : false,
46
+ };
47
+ };
48
+
49
+ return (
50
+ <div className={`infinite-level-box ${className || ""}`} style={style}>
51
+ <Spin spinning={loading}>
52
+ {/* 面包屑导航 */}
53
+ <div className="infinite-level-breadcrumb-position">
54
+ <Breadcrumb
55
+ readcrumbStyle={readcrumbStyle}
56
+ separatorStyle={separatorStyle}
57
+ separator={separator}
58
+ breadcrumbData={breadcrumbData}
59
+ handleBreadcrumbClick={handleBreadcrumbClick}
60
+ ></Breadcrumb>
61
+ {Slots?.fixRenderCenter && <Slots.fixRenderCenter></Slots.fixRenderCenter>}
62
+ </div>
63
+ <div className="infinite-level-list-box" style={listStyle}>
64
+ {Slots?.pullToRefresh ? (
65
+ <Slots.pullToRefresh>
66
+ <ScrollList
67
+ key={refreshKey}
68
+ {...scrollListProps}
69
+ ItemRender={Slots.renderItem}
70
+ onLoadMore={scrollListProps?.onLoadMore ?? loadData}
71
+ />
72
+ </Slots.pullToRefresh>
73
+ ) : (
74
+ <ScrollList
75
+ key={refreshKey}
76
+ {...scrollListProps}
77
+ ItemRender={Slots.renderItem}
78
+ onLoadMore={scrollListProps?.onLoadMore ?? loadData}
79
+ />
80
+ )}
81
+ </div>
82
+ </Spin>
83
+ </div>
84
+ );
85
+ };
86
+
87
+ export default forwardRef<InfiniteListInstance, InfiniteListProps>(InfiniteListUi);
package/src/index.tsx CHANGED
@@ -0,0 +1 @@
1
+ export {};
package/src/type.d.ts CHANGED
@@ -1,81 +1,98 @@
1
- export type ListItem = {
2
- children?: ListItem[];
3
- value: number;
4
- label: string;
5
- [key: string]: any;
6
- };
7
-
8
- export type FieldItem = {
9
- /** 选中当前关联id */
10
- value: string;
11
- /** 选中当前关联名称 */
12
- label: string;
13
- };
14
- export type PathItem = {
15
- value: number;
16
- label: string;
17
- };
18
- export type InitSelectItem = PathItem;
19
- export type OnNodeBreadcrumbClickType = PathItem & { index: number };
20
- export interface InfiniteListInstance {
21
- /** 点击下级节点事件 */
22
- handleNodeClick?: (item: ListItem) => void;
23
- /** 选中事件 */
24
- handleSelectId?: (item: ListItem) => void;
25
- listRef?: any;
26
- listModal?: any;
27
- breadModel?: any;
28
- /** 面包屑回显数据 */
29
- breadcrumbData?: any;
30
- /** 面包屑数据请求方法 */
31
- fetchBreadData?: () => Promise<void>;
32
- /** 列表刷新 */
33
- handleListRefresh?: () => void;
34
- }
35
- export interface InfiniteListProps {
36
- /** 添加外层类名 */
37
- className?: string;
38
- /** 面包屑显示对应关联字段默认 value,label */
39
- fieldBreadcrumb?: FieldItem;
40
- /** 是否有首页,默认false */
41
- showHome?: boolean;
42
- /** 关联字段默认 value,label */
43
- fieldList?: FieldItem;
44
- /** 列表请求接口下一级关联字段 */
45
- parentField?: string;
46
- /** 面包屑首页名称 */
47
- homeBreadcrumb?: string;
48
- /** 自定义面包屑 自定义列表 */
49
- Slots: {
50
- /** 固定在头部 面包屑和列表之间插槽 */
51
- fixRenderCenter?: any;
52
- /** 自定义列表项 */
53
- renderItem: any;
54
- };
55
- /** 面包屑分割符 */
56
- separator?: string;
57
- /** 组件外层样式 */
58
- style?: object;
59
- /** 面包屑分割符css 样式 */
60
- separatorStyle?: object;
61
- /** 面包屑外层 自定义css 样式 */
62
- readcrumbStyle?: object;
63
- /** 列表外层 css 样式 */
64
- listStyle?: object;
65
- /** list modal */
66
- listModal: any;
67
- /** bread modal */
68
- breadModel?: any;
69
- /** list-render-mobile配置 */
70
- listRenderProps?: object;
71
- /** virtualPagedList 配置 */
72
- virtualPagedListProps?: any;
73
- /** 是否可下拉刷新 */
74
- isPullRefresh?: boolean;
75
- /** 选中点击事件 */
76
- onNodeClick?: (node: ListItem) => void;
77
- /** 选中id */
78
- onNodeSelect?: (node: ListItem) => void;
79
- /** 选中回显点击事件 */
80
- onBreadcrumbClick?: (node: OnNodeBreadcrumbClickType) => void;
81
- }
1
+ /**
2
+ * 泛型基础类型,用于表示带有 label 和 value 的通用项。
3
+ * @template T - value 属性的类型。
4
+ */
5
+ export type BaseItem<T> = {
6
+ label: string;
7
+ value: T;
8
+ };
9
+
10
+ /**
11
+ * 列表项,继承自 BaseItem<number>,并额外拥有子节点和任意属性。
12
+ */
13
+ export type ListItem = BaseItem<number> & {
14
+ children?: ListItem[];
15
+ [key: string]: any;
16
+ };
17
+
18
+ /**
19
+ * 字段项,直接等同于 BaseItem<string>。
20
+ */
21
+ export type FieldItem = BaseItem<string>;
22
+
23
+ /**
24
+ * 路径项,直接等同于 BaseItem<number>。
25
+ */
26
+ export type PathItem = BaseItem<number>;
27
+
28
+ export type InitSelectItem = PathItem;
29
+
30
+ export type OnNodeBreadcrumbClickType = PathItem & { index: number };
31
+
32
+ /**
33
+ * 定义一个用于包裹内容并提供下拉刷新功能的组件类型。
34
+ * 它接收 `children` 作为 props,并返回一个 React 节点。
35
+ */
36
+ export type PullToRefreshWrapper = (props: { children: React.ReactNode }) => React.ReactElement | null;
37
+
38
+ export interface InfiniteListInstance {
39
+ /** 点击下级节点事件 */
40
+ handleNodeClick?: (item: ListItem) => void;
41
+ /** 选中事件 */
42
+ handleSelectId?: (item: ListItem) => void;
43
+ listModal?: any;
44
+ breadModel?: any;
45
+ /** 面包屑回显数据 */
46
+ breadcrumbData?: any;
47
+ /** 面包屑数据请求方法 */
48
+ fetchBreadData?: () => Promise<void>;
49
+ /** 列表刷新 */
50
+ handleListRefresh?: () => void;
51
+ }
52
+ export interface InfiniteListProps {
53
+ /** 添加外层类名 */
54
+ className?: string;
55
+ /** 面包屑显示对应关联字段默认 value,label */
56
+ fieldBreadcrumb?: FieldItem;
57
+ /** 是否有首页,默认false */
58
+ showHome?: boolean;
59
+ /** 关联字段默认 value,label */
60
+ fieldList?: FieldItem;
61
+ /** 列表请求接口下一级关联字段 */
62
+ parentField?: string;
63
+ /** 面包屑首页名称 */
64
+ homeBreadcrumb?: string;
65
+ /** 自定义面包屑 自定义列表 */
66
+ Slots: {
67
+ /** 固定在头部 面包屑和列表之间插槽 */
68
+ fixRenderCenter?: any;
69
+ /** 自定义列表项 */
70
+ renderItem: any;
71
+ /** 自定义下拉刷新组件 */
72
+ pullToRefresh?: PullToRefreshWrapper;
73
+ };
74
+ /** 面包屑分割符 */
75
+ separator?: string;
76
+ /** 组件外层样式 */
77
+ style?: object;
78
+ /** 面包屑分割符css 样式 */
79
+ separatorStyle?: object;
80
+ /** 面包屑外层 自定义css 样式 */
81
+ readcrumbStyle?: object;
82
+ /** 列表外层 css 样式 */
83
+ listStyle?: object;
84
+ /** list modal */
85
+ listModal: any;
86
+ /** bread modal */
87
+ breadModel?: any;
88
+ /** list-render-mobile配置 */
89
+ listRenderProps?: object;
90
+ /** scrollListProps 配置 */
91
+ scrollListProps?: any;
92
+ /** 选中点击事件 */
93
+ onNodeClick?: (node: ListItem) => void;
94
+ /** 选中id */
95
+ onNodeSelect?: (node: ListItem) => void;
96
+ /** 选中回显点击事件 */
97
+ onBreadcrumbClick?: (node: OnNodeBreadcrumbClickType) => void;
98
+ }
@@ -1,154 +1,145 @@
1
- import { useState, useEffect, useRef } from "react";
2
- import { ListItem, PathItem, InfiniteListProps } from "./type";
3
-
4
- export function useInfiniteList(props: InfiniteListProps) {
5
- const {
6
- style,
7
- listStyle,
8
- separatorStyle,
9
- readcrumbStyle,
10
- listRenderProps,
11
- showHome = true,
12
- onNodeClick,
13
- onNodeSelect,
14
- onBreadcrumbClick,
15
- parentField = "parentId",
16
- homeBreadcrumb = "首页",
17
- fieldBreadcrumb = {
18
- value: "value",
19
- label: "label",
20
- },
21
- fieldList = {
22
- value: "value",
23
- label: "label",
24
- ...props?.fieldList,
25
- },
26
- Slots,
27
- separator = "/",
28
- listModal,
29
- breadModel,
30
- virtualPagedListProps,
31
- className,
32
- isPullRefresh = false,
33
- } = props;
34
- const [loading, setLoading] = useState(false);
35
- const [selectedLoadIdNode, setSelectedLoadIdNode] = useState<number | null>(null);
36
- const [selecteId, setSelectedId] = useState<number | null>();
37
- const [breadcrumbData, setBreadcrumbData] = useState<PathItem[]>(
38
- showHome ? [{ value: 0, label: homeBreadcrumb }] : [],
39
- );
40
- const [refreshKey, setRefreshKey] = useState(1);
41
- const listRef = useRef<any>(null);
42
-
43
- /**
44
- * 下一级请求函数
45
- * @param {ListItem} item - 选中的节点数据
46
- *
47
- */
48
- const handleNodeClick = (item: ListItem) => {
49
- onNodeClick?.({
50
- ...item,
51
- value: item[fieldList.value],
52
- label: item[fieldList.label],
53
- });
54
- listModal.query = { ...listModal.query, [parentField]: item[fieldList.value] };
55
- setSelectedLoadIdNode(item[fieldList.value]);
56
- setBreadcrumbData((pre) => [
57
- ...pre,
58
- {
59
- value: item[fieldList.value],
60
- label: item[fieldList.label],
61
- },
62
- ]);
63
- setRefreshKey((pre) => pre + 1);
64
- };
65
-
66
- /**
67
- * 选中节点id
68
- * @param {ListItem} item - 选中的节点
69
- *
70
- */
71
- const handleSelectId = (item: ListItem) => {
72
- setSelectedId(item[fieldList.value]);
73
- onNodeSelect?.({ ...item });
74
- };
75
-
76
- /**
77
- * 处理面包屑点击事件
78
- * @param {PathItem} item - 被点击的面包屑节点
79
- * @param {number} index - 被点击的面包屑节点的索引
80
- */
81
- const handleBreadcrumbClick = (item: PathItem, index: number) => {
82
- if (breadcrumbData.length - 1 == index) return;
83
- onBreadcrumbClick?.({
84
- ...item,
85
- index: index,
86
- });
87
- listModal.query = { ...listModal.query, [parentField]: item.value };
88
- setSelectedLoadIdNode(item.value);
89
- setBreadcrumbData(breadcrumbData.slice(0, index + 1));
90
- setRefreshKey((pre) => pre + 1);
91
- };
92
-
93
- /**
94
- * 面包屑数据回显
95
- *
96
- */
97
- const fetchBreadData = async () => {
98
- setLoading(true);
99
- try {
100
- const res = await breadModel?.get();
101
- if (!res && !Array.isArray(res)) return;
102
- let relPath =
103
- res[0]?.path?.map((v: any) => {
104
- return {
105
- ...v,
106
- value: v[fieldBreadcrumb.value],
107
- label: v[fieldBreadcrumb.label],
108
- };
109
- }) || [];
110
- relPath && setBreadcrumbData(relPath);
111
- } finally {
112
- setLoading(false);
113
- }
114
- };
115
- /** 列表刷新 */
116
- const handleListRefresh = async () => {
117
- listModal.query = { ...listModal.query, pageNum: 1 };
118
- setRefreshKey((pre) => pre + 1);
119
- };
120
-
121
- useEffect(() => {
122
- fetchBreadData();
123
- }, []);
124
-
125
- return {
126
- states: {
127
- style,
128
- listStyle,
129
- separatorStyle,
130
- readcrumbStyle,
131
- selectedLoadIdNode,
132
- breadcrumbData,
133
- Slots,
134
- listRenderProps,
135
- separator,
136
- loading,
137
- selecteId,
138
- listRef,
139
- virtualPagedListProps,
140
- listModal,
141
- breadModel,
142
- className,
143
- refreshKey,
144
- isPullRefresh,
145
- },
146
- actions: {
147
- handleSelectId,
148
- handleNodeClick,
149
- handleBreadcrumbClick,
150
- fetchBreadData,
151
- handleListRefresh,
152
- },
153
- };
154
- }
1
+ import { useState, useEffect, useRef } from "react";
2
+ import { ListItem, PathItem, InfiniteListProps } from "./type";
3
+
4
+ export function useInfiniteList(props: InfiniteListProps) {
5
+ const {
6
+ style,
7
+ listStyle,
8
+ separatorStyle,
9
+ readcrumbStyle,
10
+ listRenderProps,
11
+ showHome = true,
12
+ onNodeClick,
13
+ onNodeSelect,
14
+ onBreadcrumbClick,
15
+ parentField = "parentId",
16
+ homeBreadcrumb = "首页",
17
+ fieldBreadcrumb = {
18
+ value: "value",
19
+ label: "label",
20
+ },
21
+ fieldList = {
22
+ value: "value",
23
+ label: "label",
24
+ ...props?.fieldList,
25
+ },
26
+ Slots,
27
+ separator = "/",
28
+ listModal,
29
+ breadModel,
30
+ scrollListProps,
31
+ className,
32
+ } = props;
33
+ const [loading, setLoading] = useState(false);
34
+ const [selecteId, setSelectedId] = useState<number | null>();
35
+ const [breadcrumbData, setBreadcrumbData] = useState<PathItem[]>(
36
+ showHome ? [{ value: 0, label: homeBreadcrumb }] : [],
37
+ );
38
+ const [refreshKey, setRefreshKey] = useState(1);
39
+ /**
40
+ * 下一级请求函数
41
+ * @param {ListItem} item - 选中的节点数据
42
+ *
43
+ */
44
+ const handleNodeClick = (item: ListItem) => {
45
+ onNodeClick?.({
46
+ ...item,
47
+ value: item[fieldList.value],
48
+ label: item[fieldList.label],
49
+ });
50
+ listModal.query = { ...listModal.query, [parentField]: item[fieldList.value] };
51
+ setBreadcrumbData((pre) => [
52
+ ...pre,
53
+ {
54
+ value: item[fieldList.value],
55
+ label: item[fieldList.label],
56
+ },
57
+ ]);
58
+ setRefreshKey((pre) => pre + 1);
59
+ };
60
+
61
+ /**
62
+ * 选中节点id
63
+ * @param {ListItem} item - 选中的节点
64
+ *
65
+ */
66
+ const handleSelectId = (item: ListItem) => {
67
+ setSelectedId(item[fieldList.value]);
68
+ onNodeSelect?.({ ...item });
69
+ };
70
+
71
+ /**
72
+ * 处理面包屑点击事件
73
+ * @param {PathItem} item - 被点击的面包屑节点
74
+ * @param {number} index - 被点击的面包屑节点的索引
75
+ */
76
+ const handleBreadcrumbClick = (item: PathItem, index: number) => {
77
+ if (breadcrumbData.length - 1 == index) return;
78
+ onBreadcrumbClick?.({
79
+ ...item,
80
+ index: index,
81
+ });
82
+ listModal.query = { ...listModal.query, [parentField]: item.value };
83
+ setBreadcrumbData(breadcrumbData.slice(0, index + 1));
84
+ setRefreshKey((pre) => pre + 1);
85
+ };
86
+
87
+ /**
88
+ * 面包屑数据回显
89
+ *
90
+ */
91
+ const fetchBreadData = async () => {
92
+ setLoading(true);
93
+ try {
94
+ const res = await breadModel?.get();
95
+ if (!res && !Array.isArray(res)) return;
96
+ let relPath =
97
+ res[0]?.path?.map((v: any) => {
98
+ return {
99
+ ...v,
100
+ value: v[fieldBreadcrumb.value],
101
+ label: v[fieldBreadcrumb.label],
102
+ };
103
+ }) || [];
104
+ relPath && setBreadcrumbData(relPath);
105
+ } finally {
106
+ setLoading(false);
107
+ }
108
+ };
109
+ /** 列表刷新 */
110
+ const handleListRefresh = async () => {
111
+ listModal.query = { ...listModal.query, pageNum: 1 };
112
+ setRefreshKey((pre) => pre + 1);
113
+ };
114
+
115
+ useEffect(() => {
116
+ fetchBreadData();
117
+ }, []);
118
+
119
+ return {
120
+ states: {
121
+ style,
122
+ listStyle,
123
+ separatorStyle,
124
+ readcrumbStyle,
125
+ breadcrumbData,
126
+ Slots,
127
+ listRenderProps,
128
+ separator,
129
+ loading,
130
+ selecteId,
131
+ scrollListProps,
132
+ listModal,
133
+ breadModel,
134
+ className,
135
+ refreshKey,
136
+ },
137
+ actions: {
138
+ handleSelectId,
139
+ handleNodeClick,
140
+ handleBreadcrumbClick,
141
+ fetchBreadData,
142
+ handleListRefresh,
143
+ },
144
+ };
145
+ }