@basestone/hooks 1.3.6 → 1.3.8

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/README.md CHANGED
@@ -1,69 +1,463 @@
1
- # design-hooks
1
+ # @basestone/hooks
2
2
 
3
+ 一套用于 React + Ant Design 应用的生产级 Hooks 库,提供表格管理、模态框管理、表单提交、数据请求等常用功能。
3
4
 
4
- ### 安装
5
+ [![npm version](https://img.shields.io/npm/v/@basestone/hooks.svg)](https://www.npmjs.com/package/@basestone/hooks)
6
+ [![license](https://img.shields.io/npm/l/@basestone/hooks.svg)](https://github.com/base-stone/hooks/blob/master/LICENSE)
5
7
 
6
- ```
8
+ ## ✨ 特性
9
+
10
+ - 🎯 **开箱即用** - 提供常用业务场景的完整解决方案
11
+ - 💪 **TypeScript** - 完整的类型定义和类型推导
12
+ - 🎨 **Ant Design** - 深度集成 Ant Design 组件
13
+ - ⚡️ **性能优化** - 内置性能优化和记忆化
14
+ - 🔧 **灵活配置** - 支持全局配置和局部定制
7
15
 
8
- pnpm add @base-stone/hooks
16
+ ## 📦 安装
9
17
 
18
+ ```bash
19
+ pnpm add @basestone/hooks
20
+ # or
21
+ npm install @basestone/hooks
22
+ # or
23
+ yarn add @basestone/hooks
10
24
  ```
11
25
 
26
+ ## 📚 Hooks 列表
12
27
 
13
- ### useTableList 使用
28
+ - [useTableList](#usetablelist---表格管理) - 表格管理(分页、排序、加载等)
29
+ - [useCreateModal](#usecreatemodal---模态框管理) - 模态框/抽屉管理
30
+ - [useSelectOptions](#useselectoptions---下拉选项管理) - 下拉选项管理
31
+ - [useRequestQuery](#userequestquery---数据请求) - 通用数据请求
32
+ - [useFormSubmit](#useformsubmit---表单提交) - 表单提交处理
33
+ - [useMemoizedFn](#usememoizedfn---函数记忆化) - 函数记忆化
14
34
 
35
+ ## 🔧 Claude Code Skill
15
36
 
16
- ```
37
+ 本库提供了 Claude Code Skill,可以在使用 Claude Code 开发时快速获取帮助和代码示例。
38
+
39
+ 查看 [Skill 文档](./.claude/skills/README.md) 了解如何在你的项目中使用。
40
+
41
+ ## 📖 使用文档
17
42
 
18
- const { tableProps, reload } = useTableList<ListItemData>({
19
- queryFn: getCooperateList,
43
+
44
+ ### useTableList - 表格管理
45
+
46
+ 提供完整的表格管理功能,包括分页、排序、加载状态、行选择等。
47
+
48
+ ```tsx
49
+ import { useTableList } from '@basestone/hooks'
50
+ import { Table } from 'antd'
51
+
52
+ function UserList() {
53
+ const { tableProps, search, refresh, reset, queryParams, selectedRowKeys } = useTableList({
54
+ queryFn: async (params) => {
55
+ // API 返回格式: { status: 'success', data: { list: [], totalCount: 0 } }
56
+ return await getUserList(params)
57
+ },
20
58
  params: {
21
59
  orderField: 'createDate',
22
60
  orderType: 'DESC',
23
- taskStatuses: taskStatusesArr,
24
- scope: scopeType
25
- }
61
+ status: 'active'
62
+ },
63
+ rowSelection: true // 启用行选择
26
64
  })
27
-
28
- <Table rowKey="id" scroll={{ x: 'max-content' }} columns={columns} {...tableProps} />
29
65
 
66
+ return (
67
+ <div>
68
+ <button onClick={() => search({ keyword: 'test' })}>搜索</button>
69
+ <button onClick={() => refresh()}>刷新</button>
70
+ <Table
71
+ rowKey="id"
72
+ scroll={{ x: 'max-content' }}
73
+ columns={columns}
74
+ {...tableProps}
75
+ />
76
+ </div>
77
+ )
78
+ }
30
79
  ```
31
80
 
32
- ### useCreateModal 使用
81
+ **API:**
82
+ - `tableProps` - Ant Design Table 所需的所有属性
83
+ - `search(params)` - 搜索并重置到第一页
84
+ - `refresh(params)` - 刷新当前页
85
+ - `reset(params)` - 重置查询参数
86
+ - `queryParams` - 当前查询参数
87
+ - `selectedRowKeys` - 选中的行 keys
33
88
 
89
+ ### useCreateModal - 模态框管理
34
90
 
35
- ```
91
+ 使用 zustand 管理多个模态框的状态,支持 Modal 和 Drawer。
36
92
 
37
- const { editModal, infoModal, memberModal, toggle } = useCreateModal(['edit', 'member', 'info'])
93
+ ```tsx
94
+ import { useCreateModal } from '@basestone/hooks'
95
+ import { Modal, Drawer } from 'antd'
38
96
 
39
- toggle(type, data)
97
+ function UserManagement() {
98
+ const { editModal, viewModal, open, close, toggle } = useCreateModal({
99
+ edit: {
100
+ width: 600,
101
+ title: (data) => data?.id ? '编辑用户' : '创建用户',
102
+ centered: true,
103
+ maskClosable: false
104
+ },
105
+ view: {
106
+ width: 800,
107
+ title: '用户详情',
108
+ placement: 'right' // Drawer 配置
109
+ }
110
+ })
111
+
112
+ return (
113
+ <div>
114
+ <button onClick={() => open('edit', { id: 1, name: 'John' })}>
115
+ 编辑用户
116
+ </button>
40
117
 
118
+ {/* 作为 Modal 使用 */}
119
+ <Modal {...editModal.modalProps}>
120
+ <div>用户数据: {JSON.stringify(editModal.data)}</div>
121
+ </Modal>
122
+
123
+ {/* 作为 Drawer 使用 */}
124
+ <Drawer {...viewModal.drawerProps}>
125
+ <div>用户详情: {JSON.stringify(viewModal.data)}</div>
126
+ </Drawer>
127
+ </div>
128
+ )
129
+ }
41
130
  ```
42
131
 
132
+ **API:**
133
+ - `{name}Modal.modalProps` - Modal 组件属性
134
+ - `{name}Modal.drawerProps` - Drawer 组件属性
135
+ - `{name}Modal.visible` - 可见状态
136
+ - `{name}Modal.data` - 传入的数据
137
+ - `open(type, data)` - 打开指定模态框
138
+ - `close(type)` - 关闭指定模态框
139
+ - `toggle(type, data)` - 切换指定模态框
140
+
43
141
 
44
- ### useSelectOptions 使用
142
+ ### useSelectOptions - 下拉选项管理
45
143
 
144
+ 自动获取和管理下拉选项,并创建 value-label 映射。
46
145
 
146
+ ```tsx
147
+ import { useSelectOptions } from '@basestone/hooks'
148
+ import { Select } from 'antd'
149
+
150
+ function UserFilter() {
151
+ const { departmentOptions, departmentMap, loading, refresh } = useSelectOptions({
152
+ queryFn: async (params) => {
153
+ // API 返回格式: { status: 'success', data: [] }
154
+ return await getDepartmentList(params)
155
+ },
156
+ params: { active: true },
157
+ dataKey: 'department', // 会创建 departmentOptions 和 departmentMap
158
+ fieldNames: {
159
+ label: 'departmentName',
160
+ value: 'departmentId'
161
+ },
162
+ transform: (data) => data.filter(item => item.visible) // 可选的数据转换
163
+ })
164
+
165
+ return (
166
+ <Select
167
+ options={departmentOptions}
168
+ loading={loading}
169
+ onChange={(value) => {
170
+ console.log('选中值:', value)
171
+ console.log('对应标签:', departmentMap.get(value))
172
+ }}
173
+ />
174
+ )
175
+ }
47
176
  ```
48
- const { sceneOptions, sceneMap } = useSelectOptions<string, 'scene'>({
49
- queryFn: getRecruitSceneList,
50
- dataKey: 'scene',
51
- fieldNames: { label: 'recruitTypeName', value: 'recruitEncrypt' }
177
+
178
+ **API:**
179
+ - `{dataKey}Options` - 格式化后的选项数组 `{ label, value, data }`
180
+ - `{dataKey}Map` - value label 的映射 Map
181
+ - `loading` - 加载状态
182
+ - `refresh()` - 刷新选项
183
+
184
+ ### useRequestQuery - 数据请求
185
+
186
+ 通用的数据请求 Hook,支持 Object 和 Array 类型数据。
187
+
188
+ ```tsx
189
+ import { useRequestQuery } from '@basestone/hooks'
190
+
191
+ function UserProfile({ userId }) {
192
+ // 请求单个对象
193
+ const { userInfo, setUserInfo, loading, refresh } = useRequestQuery({
194
+ queryFn: async (params) => {
195
+ // API 返回格式: { status: 'success', data: {...} }
196
+ return await getUserInfo(params)
197
+ },
198
+ params: { userId },
199
+ dataKey: 'userInfo',
200
+ dataType: 'Object',
201
+ initialValue: { name: '', email: '' },
202
+ transform: (data) => ({
203
+ ...data,
204
+ fullName: `${data.firstName} ${data.lastName}`
205
+ }),
206
+ success: (data) => {
207
+ console.log('数据加载成功:', data)
208
+ }
52
209
  })
53
210
 
211
+ // 请求数组数据
212
+ const { notificationList, setNotificationList } = useRequestQuery({
213
+ queryFn: getNotificationList,
214
+ params: { userId },
215
+ dataKey: 'notificationList',
216
+ dataType: 'Array',
217
+ initialValue: []
218
+ })
219
+
220
+ // 手动更新数据
221
+ const handleUpdateName = () => {
222
+ setUserInfo(prev => ({ ...prev, name: '新名字' }))
223
+ }
224
+
225
+ const markAsRead = (id) => {
226
+ setNotificationList(prev =>
227
+ prev.map(item => item.id === id ? { ...item, read: true } : item)
228
+ )
229
+ }
230
+
231
+ return (
232
+ <div>
233
+ {loading ? '加载中...' : (
234
+ <div>
235
+ <h1>{userInfo?.fullName}</h1>
236
+ <p>{userInfo?.email}</p>
237
+ <button onClick={handleUpdateName}>修改名字</button>
238
+ </div>
239
+ )}
240
+ </div>
241
+ )
242
+ }
54
243
  ```
55
244
 
56
- ### useRequestQuery 使用
245
+ **API:**
246
+ - `{dataKey}` - 请求到的数据
247
+ - `set{DataKey}` - 手动更新数据的函数,支持直接设置或函数式更新
248
+ - `loading` - 加载状态
249
+ - `refresh(params)` - 刷新数据
250
+
251
+ ### useFormSubmit - 表单提交
57
252
 
253
+ 处理表单提交,自动管理加载状态和消息提示。
254
+
255
+ ```tsx
256
+ import { useFormSubmit } from '@basestone/hooks'
257
+ import { Form, Input, Button, App } from 'antd'
258
+
259
+ function UserForm({ onSuccess }) {
260
+ const [form] = Form.useForm()
261
+
262
+ const { loading, submit } = useFormSubmit(
263
+ async (values) => {
264
+ // API 返回格式: { status: 'success', info: '操作成功' }
265
+ return await createUser(values)
266
+ },
267
+ (result) => {
268
+ form.resetFields()
269
+ onSuccess?.(result)
270
+ }
271
+ )
272
+
273
+ return (
274
+ <App> {/* 必需:message API 依赖 */}
275
+ <Form form={form} onFinish={submit}>
276
+ <Form.Item name="name" label="姓名" rules={[{ required: true }]}>
277
+ <Input />
278
+ </Form.Item>
279
+ <Button type="primary" htmlType="submit" loading={loading}>
280
+ 提交
281
+ </Button>
282
+ </Form>
283
+ </App>
284
+ )
285
+ }
58
286
  ```
59
287
 
60
- const { settlementInfo, refresh } = useRequestQuery<ListItemData, 'settlementInfo'>({
61
- queryFn: getSettlementInfo,
62
- dataKey: 'settlementInfo',
63
- dataType: 'Object',
64
- params: {
65
- taskId
288
+ **API:**
289
+ - `loading` - 提交中状态
290
+ - `submit(values)` - 提交函数
291
+
292
+ ### useMemoizedFn - 函数记忆化
293
+
294
+ 创建一个稳定引用的函数,但始终调用最新的实现。
295
+
296
+ ```tsx
297
+ import { useMemoizedFn } from '@basestone/hooks'
298
+ import { useEffect } from 'react'
299
+
300
+ function Component() {
301
+ const [count, setCount] = useState(0)
302
+
303
+ // 函数引用永不改变,但总是调用最新的实现
304
+ const handleClick = useMemoizedFn(() => {
305
+ console.log('当前 count:', count) // 总是打印最新的 count
306
+ setCount(count + 1)
307
+ })
308
+
309
+ useEffect(() => {
310
+ // handleClick 不会导致 effect 重新运行
311
+ }, [handleClick])
312
+
313
+ return <button onClick={handleClick}>点击 {count}</button>
314
+ }
315
+ ```
316
+
317
+ ## 🎯 完整示例
318
+
319
+ ```tsx
320
+ import {
321
+ useTableList,
322
+ useCreateModal,
323
+ useSelectOptions,
324
+ useFormSubmit
325
+ } from '@basestone/hooks'
326
+ import { Table, Modal, Form, Input, Select, Button, Space } from 'antd'
327
+
328
+ function UserManagement() {
329
+ const [form] = Form.useForm()
330
+
331
+ // 表格管理
332
+ const { tableProps, refresh } = useTableList({
333
+ queryFn: getUserList,
334
+ params: { status: 'active' },
335
+ rowSelection: true
336
+ })
337
+
338
+ // 模态框管理
339
+ const { editModal, open, close } = useCreateModal({
340
+ edit: {
341
+ width: 600,
342
+ title: (data) => data?.id ? '编辑' : '创建'
66
343
  }
67
344
  })
68
345
 
346
+ // 下拉选项
347
+ const { roleOptions } = useSelectOptions({
348
+ queryFn: getRoleList,
349
+ dataKey: 'role',
350
+ fieldNames: { label: 'roleName', value: 'roleId' }
351
+ })
352
+
353
+ // 表单提交
354
+ const { loading, submit } = useFormSubmit(
355
+ async (values) => {
356
+ const api = editModal.data?.id ? updateUser : createUser
357
+ return api({ ...values, id: editModal.data?.id })
358
+ },
359
+ () => {
360
+ close('edit')
361
+ refresh()
362
+ }
363
+ )
364
+
365
+ const columns = [
366
+ { title: '姓名', dataIndex: 'name' },
367
+ { title: '邮箱', dataIndex: 'email' },
368
+ {
369
+ title: '操作',
370
+ render: (_, record) => (
371
+ <Space>
372
+ <Button onClick={() => open('edit', record)}>编辑</Button>
373
+ </Space>
374
+ )
375
+ }
376
+ ]
377
+
378
+ return (
379
+ <div>
380
+ <Button onClick={() => open('edit')}>创建用户</Button>
381
+ <Table rowKey="id" columns={columns} {...tableProps} />
382
+
383
+ <Modal {...editModal.modalProps}>
384
+ <Form form={form} onFinish={submit} initialValues={editModal.data}>
385
+ <Form.Item name="name" label="姓名" rules={[{ required: true }]}>
386
+ <Input />
387
+ </Form.Item>
388
+ <Form.Item name="roleId" label="角色">
389
+ <Select options={roleOptions} />
390
+ </Form.Item>
391
+ <Button type="primary" htmlType="submit" loading={loading}>
392
+ 提交
393
+ </Button>
394
+ </Form>
395
+ </Modal>
396
+ </div>
397
+ )
398
+ }
69
399
  ```
400
+
401
+ ## 🔌 API 响应格式
402
+
403
+ 所有请求函数应返回以下格式:
404
+
405
+ ```typescript
406
+ // 成功响应
407
+ {
408
+ status: 'success',
409
+ data: any, // 实际数据
410
+ info?: string // 可选的消息
411
+ }
412
+
413
+ // useTableList 专用格式
414
+ {
415
+ status: 'success',
416
+ data: {
417
+ list: any[], // 数据列表
418
+ totalCount: number // 总数
419
+ }
420
+ }
421
+ ```
422
+
423
+ ## 🎨 全局配置
424
+
425
+ ### 表格全局配置
426
+
427
+ ```typescript
428
+ import { configureTableOption } from '@basestone/hooks'
429
+
430
+ configureTableOption({
431
+ sortField: ['orderType', 'orderField'], // 排序字段名
432
+ sortOrder: ['ASC', 'DESC'], // 排序顺序值
433
+ pageSize: 20 // 默认每页条数
434
+ })
435
+ ```
436
+
437
+ ## 💡 最佳实践
438
+
439
+ 1. **错误处理**: 所有 hooks 内部处理错误,但应确保 API 返回正确的响应格式
440
+ 2. **加载状态**: 利用提供的 loading 状态提升用户体验
441
+ 3. **函数记忆化**: 对于传递给子组件的回调,使用 `useMemoizedFn`
442
+ 4. **模态框状态**: 模态框状态使用 zustand 全局管理,跨渲染保持
443
+ 5. **类型安全**: 使用 TypeScript 泛型获得更好的类型推导
444
+
445
+ ## 📄 依赖
446
+
447
+ - `react` ^19.0.0
448
+ - `antd` ^6.0.0
449
+ - `zustand` ^5.0.0
450
+
451
+ ## 📝 License
452
+
453
+ MIT
454
+
455
+ ## 👨‍💻 Author
456
+
457
+ leafront (leafront@126.com)
458
+
459
+ ## 🔗 相关链接
460
+
461
+ - [GitHub](https://github.com/base-stone/hooks)
462
+ - [NPM](https://www.npmjs.com/package/@basestone/hooks)
463
+ - [Claude Code Skill](./.claude/skills/README.md)
@@ -66,10 +66,6 @@ export declare interface ModalProps {
66
66
  onCancel: () => void;
67
67
  }
68
68
 
69
- declare type noop = (this: any, ...args: any[]) => any;
70
-
71
- declare type PickFunction<T extends noop> = (this: ThisParameterType<T>, ...args: Parameters<T>) => ReturnType<T>;
72
-
73
69
  declare type Placement = 'top' | 'bottom' | 'left' | 'right';
74
70
 
75
71
  declare interface QueryOptions<K extends string, T = Record<string, any>> {
@@ -78,6 +74,7 @@ declare interface QueryOptions<K extends string, T = Record<string, any>> {
78
74
  dataType: DataType;
79
75
  dataKey: K;
80
76
  transform?: (data: unknown) => T;
77
+ success?: (data: unknown) => void;
81
78
  initialValue?: Record<string, any> | Record<string, any>[];
82
79
  }
83
80
 
@@ -106,6 +103,8 @@ declare type QueryResult<K extends string, T = Record<string, any>> = {
106
103
  refresh: (params?: Record<string, any> | undefined) => void;
107
104
  } & {
108
105
  [P in K]?: T;
106
+ } & {
107
+ [P in SetterKey<K>]: (data: T | ((prevData: T) => T)) => void;
109
108
  };
110
109
 
111
110
  declare interface RequestFn {
@@ -142,6 +141,8 @@ declare type SelectOptionsResult<K extends string, V extends string | number = s
142
141
  [P in `${K}Map`]?: MapData<V>;
143
142
  }>;
144
143
 
144
+ declare type SetterKey<K extends string> = `set${Capitalize<K>}`;
145
+
145
146
  declare interface SuccessFn {
146
147
  (data: Record<string, any>): void;
147
148
  }
@@ -198,9 +199,7 @@ export declare function useCreateModal<const T extends Record<string, ModalConfi
198
199
 
199
200
  export declare function useFormSubmit(requestFn: RequestFn, successFn: SuccessFn): FormSubmitResult;
200
201
 
201
- export declare function useMemoizedFn<T extends noop>(fn: T): PickFunction<T>;
202
-
203
- export declare function useRequestQuery<T = Record<string, any> | Record<string, any>[] | undefined, const K extends string = string>({ queryFn, params, dataType, dataKey, initialValue, transform }: QueryOptions<K, T>): QueryResult<K, T>;
202
+ export declare function useRequestQuery<T = Record<string, any> | Record<string, any>[] | undefined, const K extends string = string>({ queryFn, params, dataType, dataKey, initialValue, transform, success }: QueryOptions<K, T>): QueryResult<K, T>;
204
203
 
205
204
  export declare function useSelectOptions<V extends string | number = string | number, const K extends string = string>({ queryFn, params, dataKey, fieldNames, transform }: SelectConfig<K>): SelectOptionsResult<K, V>;
206
205
 
@@ -1,15 +1,15 @@
1
- import { useRef as j, useMemo as V, useState as h, useEffectEvent as A, useEffect as T, useId as W, useCallback as X } from "react";
1
+ import { useRef as _, useMemo as V, useState as h, useEffectEvent as j, useEffect as T, useId as W, useCallback as X } from "react";
2
2
  import { Empty as J, App as K } from "antd";
3
3
  import { create as ee } from "zustand";
4
- var _ = { exports: {} }, C = {};
4
+ var F = { exports: {} }, x = {};
5
5
  var H;
6
6
  function te() {
7
- if (H) return C;
7
+ if (H) return x;
8
8
  H = 1;
9
9
  var r = /* @__PURE__ */ Symbol.for("react.transitional.element"), a = /* @__PURE__ */ Symbol.for("react.fragment");
10
10
  function o(t, s, n) {
11
- var p = null;
12
- if (n !== void 0 && (p = "" + n), s.key !== void 0 && (p = "" + s.key), "key" in s) {
11
+ var d = null;
12
+ if (n !== void 0 && (d = "" + n), s.key !== void 0 && (d = "" + s.key), "key" in s) {
13
13
  n = {};
14
14
  for (var c in s)
15
15
  c !== "key" && (n[c] = s[c]);
@@ -17,34 +17,34 @@ function te() {
17
17
  return s = n.ref, {
18
18
  $$typeof: r,
19
19
  type: t,
20
- key: p,
20
+ key: d,
21
21
  ref: s !== void 0 ? s : null,
22
22
  props: n
23
23
  };
24
24
  }
25
- return C.Fragment = a, C.jsx = o, C.jsxs = o, C;
25
+ return x.Fragment = a, x.jsx = o, x.jsxs = o, x;
26
26
  }
27
27
  var I;
28
28
  function se() {
29
- return I || (I = 1, _.exports = te()), _.exports;
29
+ return I || (I = 1, F.exports = te()), F.exports;
30
30
  }
31
- var ae = se();
31
+ var oe = se();
32
32
  function y(r) {
33
- const a = j(r);
33
+ const a = _(r);
34
34
  a.current = V(() => r, [r]);
35
- const o = j(void 0);
35
+ const o = _(void 0);
36
36
  return o.current || (o.current = function(...t) {
37
37
  return a.current.apply(this, t);
38
38
  }), o.current;
39
39
  }
40
- const w = {
40
+ const P = {
41
41
  sortField: ["orderType", "orderField"],
42
42
  sortOrder: ["ASC", "DESC"],
43
43
  pageSize: 10
44
44
  };
45
45
  function ie(r) {
46
46
  Object.keys(r).forEach((a) => {
47
- w[a] = r[a];
47
+ P[a] = r[a];
48
48
  });
49
49
  }
50
50
  function ce({
@@ -53,7 +53,7 @@ function ce({
53
53
  transform: o,
54
54
  rowSelection: t
55
55
  }) {
56
- const s = w.pageSize, [n, p] = h({
56
+ const s = P.pageSize, [n, d] = h({
57
57
  pagination: {
58
58
  showSizeChanger: !0,
59
59
  showQuickJumper: !0,
@@ -67,57 +67,57 @@ function ce({
67
67
  pageSize: s,
68
68
  ...a
69
69
  }
70
- }), { pagination: c, list: f, queryParams: e } = n, { pageNo: l, pageSize: d } = e, [i, m] = h(!0), [g, M] = h([]), R = V(() => {
70
+ }), { pagination: c, list: f, queryParams: e } = n, { pageNo: u, pageSize: p } = e, [i, v] = h(!0), [g, C] = h([]), R = V(() => {
71
71
  if (t)
72
72
  return {
73
73
  selectedRowKeys: g,
74
- onChange: (u) => M(u)
74
+ onChange: (l) => C(l)
75
75
  };
76
- }, [t, g]), b = y(
77
- (u) => `共 ${u} 条记录 第 ${l}/${Math.ceil(u / d)} 页 `
78
- ), v = async (u) => {
79
- const { pageNo: L } = u;
80
- m(!0);
81
- const E = { ...a, pageSize: d, ...u };
82
- u.pageNo === void 0 && (E.pageNo = 1), u.pageSize === void 0 && (E.pageSize = d);
83
- const { data: D } = await r(E), N = o ? o(D) : D, { list: O = [], totalCount: F = 0 } = N || {};
84
- t && M([]), p({
85
- list: O,
86
- queryParams: E,
76
+ }, [t, g]), M = y(
77
+ (l) => `共 ${l} 条记录 第 ${u}/${Math.ceil(l / p)} 页 `
78
+ ), m = async (l) => {
79
+ const { pageNo: L } = l;
80
+ v(!0);
81
+ const b = { ...a, pageSize: p, ...l };
82
+ l.pageNo === void 0 && (b.pageNo = 1), l.pageSize === void 0 && (b.pageSize = p);
83
+ const { data: z } = await r(b), k = o ? o(z) : z, { list: N = [], totalCount: A = 0 } = k || {};
84
+ t && C([]), d({
85
+ list: N,
86
+ queryParams: b,
87
87
  pagination: {
88
88
  ...c,
89
89
  current: L,
90
- pageSize: E.pageSize,
91
- total: F
90
+ pageSize: b.pageSize,
91
+ total: A
92
92
  }
93
- }), m(!1);
94
- }, P = A(() => {
95
- v({ ...e, pageNo: 1 });
96
- }), x = (u) => {
97
- v({ ...e, ...u, pageNo: 1 });
98
- }, k = (u) => {
99
- v({ ...e, ...u });
100
- }, S = (u) => {
101
- v({ ...u, pageSize: d, pageNo: 1 });
102
- }, z = (u, L, E, D) => {
103
- const { action: N } = D;
104
- if (["paginate", "sort"].includes(N)) {
105
- const { current: O, pageSize: F } = u, { field: G, order: q } = E, [Q, Y] = w.sortField, [Z, B] = w.sortOrder, U = {
93
+ }), v(!1);
94
+ }, E = j(() => {
95
+ m({ ...e, pageNo: 1 });
96
+ }), $ = (l) => {
97
+ m({ ...e, ...l, pageNo: 1 });
98
+ }, O = (l) => {
99
+ m({ ...e, ...l });
100
+ }, S = (l) => {
101
+ m({ ...l, pageSize: p, pageNo: 1 });
102
+ }, D = (l, L, b, z) => {
103
+ const { action: k } = z;
104
+ if (["paginate", "sort"].includes(k)) {
105
+ const { current: N, pageSize: A } = l, { field: G, order: q } = b, [Q, Y] = P.sortField, [U, Z] = P.sortOrder, B = {
106
106
  ...e,
107
- [Q]: q ? q === "ascend" ? Z : B : void 0,
107
+ [Q]: q ? q === "ascend" ? U : Z : void 0,
108
108
  [Y]: G,
109
- pageNo: O,
110
- pageSize: F
109
+ pageNo: N,
110
+ pageSize: A
111
111
  };
112
- v(U);
112
+ m(B);
113
113
  }
114
114
  };
115
115
  return T(() => {
116
- P();
116
+ E();
117
117
  }, []), {
118
118
  queryParams: e,
119
- search: y(x),
120
- refresh: y(k),
119
+ search: y($),
120
+ refresh: y(O),
121
121
  reset: y(S),
122
122
  selectedRowKeys: g,
123
123
  tableProps: {
@@ -127,15 +127,15 @@ function ce({
127
127
  rowSelection: R,
128
128
  loading: i,
129
129
  dataSource: f,
130
- pagination: { ...c, showTotal: b },
131
- onChange: y(z),
130
+ pagination: { ...c, showTotal: M },
131
+ onChange: y(D),
132
132
  locale: {
133
- emptyText: i ? "" : /* @__PURE__ */ ae.jsx(J, { image: J.PRESENTED_IMAGE_SIMPLE })
133
+ emptyText: i ? "" : /* @__PURE__ */ oe.jsx(J, { image: J.PRESENTED_IMAGE_SIMPLE })
134
134
  }
135
135
  }
136
136
  };
137
137
  }
138
- const $ = ee((r) => ({
138
+ const w = ee((r) => ({
139
139
  modals: {},
140
140
  toggleModal: (a, o) => r((t) => {
141
141
  const n = t.modals[a]?.visible || !1;
@@ -166,86 +166,86 @@ const $ = ee((r) => ({
166
166
  })
167
167
  }));
168
168
  function le(r) {
169
- const a = $((e) => e.modals), o = $((e) => e.toggleModal), t = $((e) => e.setModal), s = $((e) => e.clearModals), n = W(), p = j([]), c = Object.keys(r);
170
- T(() => (p.current = c.map(
169
+ const a = w((e) => e.modals), o = w((e) => e.toggleModal), t = w((e) => e.setModal), s = w((e) => e.clearModals), n = W(), d = _([]), c = Object.keys(r);
170
+ T(() => (d.current = c.map(
171
171
  (e) => `${n}-${e}`
172
172
  ), () => {
173
- s(p.current);
173
+ s(d.current);
174
174
  }), []);
175
175
  const f = {};
176
176
  return c.forEach((e) => {
177
- const l = `${n}-${e}`, d = a[l] ?? { visible: !1, data: {} }, i = r[e], m = typeof i.title == "function" ? i.title(d.data) : i.title;
177
+ const u = `${n}-${e}`, p = a[u] ?? { visible: !1, data: {} }, i = r[e], v = typeof i.title == "function" ? i.title(p.data) : i.title;
178
178
  f[`${e}Modal`] = {
179
- visible: d.visible,
180
- data: d.data,
179
+ visible: p.visible,
180
+ data: p.data,
181
181
  modalProps: {
182
182
  width: i.width,
183
- title: m,
184
- open: d.visible,
183
+ title: v,
184
+ open: p.visible,
185
185
  maskClosable: i.maskClosable ?? !1,
186
186
  centered: i.centered ?? !0,
187
187
  destroyOnHidden: i.destroyOnHidden ?? !0,
188
- onCancel: i.onCancel ?? (() => t(l, !1))
188
+ onCancel: i.onCancel ?? (() => t(u, !1))
189
189
  },
190
190
  drawerProps: {
191
191
  size: i.width,
192
- title: m,
193
- open: d.visible,
192
+ title: v,
193
+ open: p.visible,
194
194
  maskClosable: i.maskClosable ?? !0,
195
195
  destroyOnHidden: i.destroyOnHidden ?? !0,
196
196
  placement: i.placement ?? "right",
197
- onClose: i.onClose ?? (() => t(l, !1))
197
+ onClose: i.onClose ?? (() => t(u, !1))
198
198
  },
199
- toggle: (g) => o(l, g),
200
- open: (g) => t(l, !0, g),
201
- close: () => t(l, !1)
199
+ toggle: (g) => o(u, g),
200
+ open: (g) => t(u, !0, g),
201
+ close: () => t(u, !1)
202
202
  };
203
- }), f.toggle = (e, l) => {
204
- o(`${n}-${e}`, l);
205
- }, f.open = (e, l) => {
206
- t(`${n}-${e}`, !0, l);
203
+ }), f.toggle = (e, u) => {
204
+ o(`${n}-${e}`, u);
205
+ }, f.open = (e, u) => {
206
+ t(`${n}-${e}`, !0, u);
207
207
  }, f.close = (e) => {
208
208
  t(`${n}-${e}`, !1);
209
209
  }, f;
210
210
  }
211
211
  function ue({ queryFn: r, params: a, dataKey: o, fieldNames: t, transform: s }) {
212
- const [n, p] = h({
212
+ const [n, d] = h({
213
213
  list: [],
214
214
  mapData: /* @__PURE__ */ new Map()
215
- }), [c, f] = h(!1), e = async () => {
215
+ }), [c, f] = h(!0), e = async () => {
216
216
  f(!0);
217
- const { data: g, status: M } = await r(a);
218
- if (M === "success") {
219
- const b = (s ? s(g) : g) || [], { label: v, value: P } = t, x = /* @__PURE__ */ new Map([]), k = b.map((S) => {
220
- const z = S[P];
221
- return x.set(z, S[v]), {
222
- label: S[v],
223
- value: z,
217
+ const { data: g, status: C } = await r(a);
218
+ if (C === "success") {
219
+ const M = (s ? s(g) : g) || [], { label: m, value: E } = t, $ = /* @__PURE__ */ new Map([]), O = M.map((S) => {
220
+ const D = S[E];
221
+ return $.set(D, S[m]), {
222
+ label: S[m],
223
+ value: D,
224
224
  data: S
225
225
  };
226
226
  });
227
- p((S) => ({ ...S, list: k, mapData: x }));
227
+ d((S) => ({ ...S, list: O, mapData: $ }));
228
228
  }
229
229
  f(!1);
230
- }, l = A(e), d = y(() => {
230
+ }, u = j(e), p = y(() => {
231
231
  e();
232
232
  });
233
233
  T(() => {
234
- l();
234
+ u();
235
235
  }, []);
236
- const { list: i, mapData: m } = n;
236
+ const { list: i, mapData: v } = n;
237
237
  return {
238
238
  loading: c,
239
- refresh: d,
239
+ refresh: p,
240
240
  [`${o}Options`]: i,
241
- [`${o}Map`]: m
241
+ [`${o}Map`]: v
242
242
  };
243
243
  }
244
244
  function de(r, a) {
245
- const [o, t] = h(!1), { message: s } = K.useApp(), n = X(async (p) => {
245
+ const [o, t] = h(!1), { message: s } = K.useApp(), n = X(async (d) => {
246
246
  try {
247
247
  t(!0);
248
- const c = await r(p), { status: f, info: e } = c;
248
+ const c = await r(d), { status: f, info: e } = c;
249
249
  f == "success" && (a(c), s.success(e));
250
250
  } catch {
251
251
  }
@@ -262,34 +262,35 @@ function pe({
262
262
  dataType: o,
263
263
  dataKey: t,
264
264
  initialValue: s,
265
- transform: n
265
+ transform: n,
266
+ success: d
266
267
  }) {
267
- const p = s || (o === "Array" ? [] : /* @__PURE__ */ Object.create({})), [c, f] = h(p), [e, l] = h(!1), d = async (g) => {
268
- l(!0);
269
- const { data: M, status: R } = await r(g ?? a);
270
- if (R === "success") {
271
- const b = n ? n(M) : M;
272
- f(b);
268
+ const c = s || (o === "Array" ? [] : /* @__PURE__ */ Object.create({})), [f, e] = h(c), [u, p] = h(!0), i = async (R) => {
269
+ p(!0);
270
+ const { data: M, status: m } = await r(R ?? a), E = M == null ? M : o === "Array" ? [] : /* @__PURE__ */ Object.create({});
271
+ if (m === "success") {
272
+ const $ = n ? n(E) : E;
273
+ d && d(E), e($);
273
274
  }
274
- l(!1);
275
- }, i = A(d);
275
+ p(!1);
276
+ }, v = j(i);
276
277
  T(() => {
277
- i();
278
+ v();
278
279
  }, []);
279
- const m = y((g) => {
280
- d(g);
281
- });
280
+ const g = y((R) => {
281
+ i(R);
282
+ }), C = `set${t.charAt(0).toUpperCase()}${t.slice(1)}`;
282
283
  return {
283
- [t]: c,
284
- loading: e,
285
- refresh: m
284
+ [t]: f,
285
+ [C]: e,
286
+ loading: u,
287
+ refresh: g
286
288
  };
287
289
  }
288
290
  export {
289
291
  ie as configureTableOption,
290
292
  le as useCreateModal,
291
293
  de as useFormSubmit,
292
- y as useMemoizedFn,
293
294
  pe as useRequestQuery,
294
295
  ue as useSelectOptions,
295
296
  ce as useTableList
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@basestone/hooks",
3
3
  "license": "MIT",
4
- "version": "1.3.6",
4
+ "version": "1.3.8",
5
5
  "author": {
6
6
  "name": "leafront",
7
7
  "email": "leafront@126.com"