@quansitech/antd-admin 1.2.9 → 1.3.1

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
@@ -170,10 +170,670 @@ container.register('Column.Readonly.Action.组件名', () => import('[组件路
170
170
 
171
171
  - 若要补充组件库,请把组件放``` compontents/Column/Readonly/Action/ ``` 目录下
172
172
 
173
- ## 更新日志
173
+ ## 常用扩展功能
174
+
175
+ ### 弹窗(Modal)使用
176
+
177
+ 框架提供了 `modalShow` 函数用于显示弹窗,支持在弹窗中嵌套 Table、Form、Tabs 等组件。
178
+
179
+ #### 基本用法
180
+
181
+ ```tsx
182
+ import {modalShow} from "@quansitech/antd-admin/lib/helpers";
183
+
184
+ // 显示弹窗
185
+ await modalShow({
186
+ title: '弹窗标题',
187
+ content: {
188
+ type: 'form', // 支持 'form' | 'table' | 'tabs'
189
+ props: {
190
+ // 传递给组件的 props
191
+ },
192
+ url: '/api/modal-content' // 可选:从 URL 获取弹窗内容
193
+ },
194
+ contexts: {
195
+ // 传递给弹窗的上下文数据
196
+ tableContext,
197
+ customData: 'value'
198
+ }
199
+ })
200
+ ```
201
+
202
+ #### 在弹窗中使用上下文
203
+
204
+ 弹窗内的组件通过 `ModalContext` 访问上下文:
205
+
206
+ ```tsx
207
+ import {ModalContext} from "@quansitech/antd-admin/components/ModalContext";
208
+
209
+ export default function MyComponent() {
210
+ const modalContext = useContext(ModalContext)
211
+
212
+ // 关闭弹窗
213
+ const close = () => {
214
+ modalContext.closeModal()
215
+ }
216
+
217
+ // 设置关闭后的回调
218
+ modalContext.setAfterClose(() => {
219
+ console.log('弹窗已关闭')
220
+ })
221
+
222
+ // 访问传递的上下文数据
223
+ const tableContext = modalContext.contexts?.tableContext
224
+
225
+ return <div>弹窗内容</div>
226
+ }
227
+ ```
228
+
229
+ #### 支持的弹窗类型
230
+
231
+ - **form**: 表单弹窗,组件路径 `Modal.Form`
232
+ - **table**: 表格弹窗,组件路径 `Modal.Table`
233
+ - **tabs**: 标签页弹窗,组件路径 `Modal.Tabs`
234
+
235
+ #### 自定义弹窗组件
236
+
237
+ ```tsx
238
+ // 1. 创建弹窗组件
239
+ import {ModalContext} from "@quansitech/antd-admin/components/ModalContext";
240
+
241
+ export default function CustomModal({title, data}: any) {
242
+ const modalContext = useContext(ModalContext)
243
+
244
+ return (
245
+ <div>
246
+ <h2>{title}</h2>
247
+ <p>{data}</p>
248
+ <Button onClick={modalContext.closeModal}>关闭</Button>
249
+ </div>
250
+ )
251
+ }
252
+
253
+ // 2. 注册弹窗组件
254
+ import container from "@quansitech/antd-admin/lib/container";
255
+
256
+ container.register('Modal.Custom', () => import('./components/CustomModal'))
257
+
258
+ // 3. 使用自定义弹窗
259
+ await modalShow({
260
+ content: {
261
+ type: 'custom',
262
+ props: {
263
+ title: '自定义弹窗',
264
+ data: 'some data'
265
+ }
266
+ }
267
+ })
268
+ ```
269
+
270
+ ### 页面跳转
271
+
272
+ 框架提供了 `routerNavigateTo` 函数用于页面跳转,基于 Inertia.js 实现。
273
+
274
+ #### 基本用法
275
+
276
+ ```tsx
277
+ import {routerNavigateTo} from "@quansitech/antd-admin/lib/helpers";
278
+
279
+ // 简单跳转
280
+ routerNavigateTo('/admin/user')
281
+
282
+ // 带配置的跳转
283
+ routerNavigateTo('/admin/user', {
284
+ onSuccess: () => {
285
+ console.log('跳转成功')
286
+ },
287
+ onError: (errors) => {
288
+ console.error('跳转失败', errors)
289
+ },
290
+ preserveState: true, // 保留页面状态
291
+ replace: false // 不替换历史记录
292
+ })
293
+ ```
294
+
295
+ #### 在组件中使用
296
+
297
+ ```tsx
298
+ // 按钮点击跳转
299
+ <Button onClick={() => routerNavigateTo('/admin/create')}>
300
+ 新建
301
+ </Button>
302
+
303
+ // JavaScript 协议链接(会使用 window.location.href)
304
+ routerNavigateTo('javascript:history.back()')
305
+ ```
306
+
307
+ ### 消息提示
308
+
309
+ 框架通过 `global` 对象提供了消息提示功能,包括成功、错误、警告、信息等提示。
310
+
311
+ #### 使用方式
312
+
313
+ ```tsx
314
+ import global from "@quansitech/antd-admin/lib/global";
315
+
316
+ // 成功提示
317
+ global.notification.success({
318
+ message: '操作成功',
319
+ description: '数据已保存'
320
+ })
321
+
322
+ // 错误提示
323
+ global.notification.error({
324
+ message: '操作失败',
325
+ description: '请稍后重试'
326
+ })
327
+
328
+ // 警告提示
329
+ global.notification.warning({
330
+ message: '警告',
331
+ description: '请注意检查数据'
332
+ })
333
+
334
+ // 信息提示
335
+ global.notification.info({
336
+ message: '提示信息'
337
+ })
338
+
339
+ // 简单消息提示
340
+ global.message.success('保存成功')
341
+ global.message.error('保存失败')
342
+ global.message.warning('请检查输入')
343
+ global.message.info('提示信息')
344
+ global.message.loading('加载中...')
345
+ ```
346
+
347
+ #### HTTP 自动消息处理
348
+
349
+ HTTP 拦截器会自动处理后端返回的消息:
350
+
351
+ ```tsx
352
+ // 后端返回格式
353
+ {
354
+ status: 1, // 1=成功, 0=失败
355
+ info: '操作成功', // 会自动显示提示
356
+ url: '/admin/list' // 可选:自动跳转
357
+ }
358
+
359
+ // 前端请求
360
+ await http({url: '/api/save'})
361
+ // 会自动显示成功/失败提示
362
+ // 如果返回 url,2秒后自动跳转
363
+ ```
364
+
365
+ #### 禁用自动消息
366
+
367
+ ```tsx
368
+ await http({
369
+ url: '/api/data',
370
+ fetchOptions: {
371
+ noHandle: true // 不自动处理消息和跳转
372
+ }
373
+ })
374
+ ```
375
+
376
+ ### 确认框(Confirm)
377
+
378
+ 在需要用户确认的操作时使用确认框。
379
+
380
+ #### 在 Action 组件中使用
381
+
382
+ ```tsx
383
+ // Table Action
384
+ {
385
+ title: '删除',
386
+ request: {
387
+ url: '/admin/delete/__id__',
388
+ method: 'post',
389
+ confirm: '确定要删除这条记录吗?' // 显示确认框
390
+ }
391
+ }
392
+
393
+ // Form Action
394
+ {
395
+ title: '保存',
396
+ submit: true,
397
+ confirm: '确定要保存吗?' // 提交前确认
398
+ }
399
+ ```
400
+
401
+ #### 手动使用确认框
402
+
403
+ ```tsx
404
+ import {Modal} from "antd";
405
+
406
+ Modal.confirm({
407
+ title: '确认操作',
408
+ content: '确定要执行此操作吗?',
409
+ onOk() {
410
+ console.log('确认')
411
+ },
412
+ onCancel() {
413
+ console.log('取消')
414
+ }
415
+ })
416
+ ```
417
+
418
+ ### HTTP 请求
419
+
420
+ 框架封装了 `http` 实例,基于 Axios,提供了统一的请求处理。
421
+
422
+ #### 基本用法
423
+
424
+ ```tsx
425
+ import http from "@quansitech/antd-admin/lib/http";
426
+
427
+ // GET 请求
428
+ const res = await http({
429
+ method: 'get',
430
+ url: '/api/user/list'
431
+ })
174
432
 
175
- ### 1.1.0
433
+ // POST 请求
434
+ const res = await http({
435
+ method: 'post',
436
+ url: '/api/user/create',
437
+ data: {
438
+ name: '张三',
439
+ email: 'test@example.com'
440
+ }
441
+ })
442
+
443
+ // 带请求头
444
+ const res = await http({
445
+ method: 'post',
446
+ url: '/api/data',
447
+ headers: {
448
+ 'X-Custom-Header': 'value'
449
+ },
450
+ data: {}
451
+ })
452
+ ```
453
+
454
+ #### 参数替换
455
+
456
+ 支持使用 `__field__` 格式进行动态参数替换:
457
+
458
+ ```tsx
459
+ // URL 参数替换
460
+ const url = replaceUrl('/admin/user/edit/__id__', {id: 123})
461
+ // 结果: '/admin/user/edit/123'
462
+
463
+ // 请求参数替换
464
+ const data = replaceParams({
465
+ name: '__username__',
466
+ age: '__userage__'
467
+ }, {username: '张三', userage: 25})
468
+ // 结果: {name: '张三', age: 25}
469
+ ```
470
+
471
+ #### 错误处理
472
+
473
+ ```tsx
474
+ try {
475
+ await http({
476
+ method: 'post',
477
+ url: '/api/save',
478
+ data: {}
479
+ })
480
+ } catch (error) {
481
+ // 错误会自动显示通知
482
+ // 这里可以添加额外处理
483
+ console.error('保存失败', error)
484
+ }
485
+ ```
486
+
487
+ ### 树形数据处理
488
+
489
+ 框架提供了多个树形数据处理的工具函数。
490
+
491
+ #### treeToList - 树形转列表
492
+
493
+ ```tsx
494
+ import {treeToList} from "@quansitech/antd-admin/lib/helpers";
495
+
496
+ const tree = [
497
+ {
498
+ id: 1,
499
+ name: '节点1',
500
+ children: [
501
+ {id: 11, name: '子节点1.1', children: []},
502
+ {id: 12, name: '子节点1.2', children: []}
503
+ ]
504
+ },
505
+ {
506
+ id: 2,
507
+ name: '节点2',
508
+ children: []
509
+ }
510
+ ]
511
+
512
+ const list = treeToList(tree, 'children')
513
+ // 结果: [{id:1, name:'节点1'}, {id:11, name:'子节点1.1'}, {id:12, name:'子节点1.2'}, {id:2, name:'节点2'}]
514
+ ```
515
+
516
+ #### diffTree - 对比树形差异
517
+
518
+ ```tsx
519
+ import {diffTree} from "@quansitech/antd-admin/lib/helpers";
520
+
521
+ const oldTree = [{id: 1, name: 'A', children: []}]
522
+ const newTree = [{id: 1, name: 'A', children: []}, {id: 2, name: 'B', children: []}]
523
+
524
+ const added = diffTree(oldTree, newTree, 'children')
525
+ // 结果: [{id: 2, name: 'B'}] - 新增的节点
526
+ ```
527
+
528
+ #### findValuePath - 查找值路径
529
+
530
+ ```tsx
531
+ import {findValuePath} from "@quansitech/antd-admin/lib/helpers";
532
+
533
+ const obj = {
534
+ a: {
535
+ b: {
536
+ c: 'target'
537
+ }
538
+ }
539
+ }
540
+
541
+ const path = findValuePath(obj, 'target')
542
+ // 结果: ['a', 'b', 'c']
543
+ ```
544
+
545
+ #### getValueByPath - 根据路径取值
546
+
547
+ ```tsx
548
+ import {getValueByPath} from "@quansitech/antd-admin/lib/helpers";
549
+
550
+ const obj = {a: {b: {c: 'value'}}}
551
+
552
+ const value = getValueByPath(obj, ['a', 'b', 'c'])
553
+ // 结果: 'value'
554
+ ```
555
+
556
+ ### 条件判断
557
+
558
+ 使用 `handleCondition` 函数进行条件判断:
559
+
560
+ ```tsx
561
+ import {handleCondition} from "@quansitech/antd-admin/lib/helpers";
562
+
563
+ // 支持的操作符
564
+ const conditions = [
565
+ {field: 'age', operator: '>', value: 18}, // gt, gte, lt, lte
566
+ {field: 'status', operator: '=', value: 1}, // eq, neq
567
+ {field: 'type', operator: 'in', value: [1, 2, 3]}, // in, not in
568
+ ]
569
+
570
+ const data = {age: 20, status: 1, type: 2}
571
+
572
+ conditions.forEach(cond => {
573
+ const result = handleCondition(cond, data)
574
+ console.log(`条件${cond.field} ${cond.operator} ${cond.value}:`, result)
575
+ })
576
+ ```
176
577
 
177
- * 增加composer包注册组件机制
578
+ ### Context 使用
579
+
580
+ 框架提供了多个 Context 用于在不同组件间共享数据。
581
+
582
+ #### TableContext
583
+
584
+ 表格上下文,提供表格相关的操作:
585
+
586
+ ```tsx
587
+ import {TableContext} from "@quansitech/antd-admin/components/TableContext";
588
+
589
+ const tableContext = useContext(TableContext)
590
+
591
+ // 重新加载表格
592
+ await tableContext.getActionRef()?.reload()
593
+
594
+ // 获取选中的行
595
+ const selectedRows = tableContext.getSelectedRows()
596
+
597
+ // 清空选中
598
+ tableContext.getActionRef()?.clearSelected()
599
+
600
+ // 获取编辑的值
601
+ const editedValues = tableContext.getEditedValues()
602
+
603
+ // 获取数据源
604
+ const dataSource = tableContext.getDataSource()
605
+
606
+ // 获取表格配置
607
+ const tableProps = tableContext.getTableProps()
608
+ ```
609
+
610
+ #### FormContext
611
+
612
+ 表单上下文,提供表单相关的操作:
613
+
614
+ ```tsx
615
+ import {FormContext} from "@quansitech/antd-admin/components/FormContext";
616
+
617
+ const formContext = useContext(FormContext)
618
+
619
+ // 获取表单引用
620
+ const formRef = formContext.getFormRef()
621
+
622
+ // 获取表单值
623
+ const values = await formRef?.getFieldsValue()
624
+
625
+ // 设置表单值
626
+ formRef?.setFieldsValue({name: '张三'})
627
+
628
+ // 重置表单
629
+ formRef?.resetFields()
630
+
631
+ // 提交表单
632
+ formRef?.submit()
633
+ ```
634
+
635
+ #### ModalContext
636
+
637
+ 弹窗上下文,提供弹窗相关的操作:
638
+
639
+ ```tsx
640
+ import {ModalContext} from "@quansitech/antd-admin/components/ModalContext";
641
+
642
+ const modalContext = useContext(ModalContext)
643
+
644
+ // 是否在弹窗中
645
+ const inModal = modalContext.inModal
646
+
647
+ // 关闭弹窗
648
+ modalContext.closeModal()
649
+
650
+ // 设置关闭后的回调
651
+ modalContext.setAfterClose(() => {
652
+ console.log('弹窗关闭后执行')
653
+ })
654
+
655
+ // 访问传递的上下文
656
+ const contexts = modalContext.contexts
657
+ ```
658
+
659
+ ### 完整示例
660
+
661
+ #### 表格操作按钮
662
+
663
+ ```tsx
664
+ // 后端配置
665
+ {
666
+ title: '操作',
667
+ actions: [
668
+ {
669
+ type: 'Button', // 使用自定义按钮组件
670
+ props: {
671
+ type: 'primary',
672
+ title: '编辑',
673
+ relateSelection: false, // 不关联选中行
674
+ link: {
675
+ url: '/admin/edit/__id__' // 跳转链接
676
+ }
677
+ }
678
+ },
679
+ {
680
+ type: 'Button',
681
+ props: {
682
+ type: 'default',
683
+ title: '审核',
684
+ request: {
685
+ url: '/admin/audit',
686
+ method: 'post',
687
+ data: {id: '__id__'},
688
+ confirm: '确定要审核通过吗?' // 确认框
689
+ }
690
+ }
691
+ },
692
+ {
693
+ type: 'Button',
694
+ props: {
695
+ type: 'default',
696
+ title: '查看详情',
697
+ modal: {
698
+ title: '详情',
699
+ content: {
700
+ type: 'form',
701
+ url: '/admin/detail/__id__'
702
+ }
703
+ }
704
+ }
705
+ },
706
+ {
707
+ type: 'Button',
708
+ props: {
709
+ type: 'primary',
710
+ title: '批量删除',
711
+ relateSelection: true, // 关联选中行
712
+ request: {
713
+ url: '/admin/batch-delete',
714
+ method: 'post',
715
+ confirm: '确定要删除选中的记录吗?'
716
+ }
717
+ }
718
+ }
719
+ ]
720
+ }
721
+ ```
722
+
723
+ #### 表单操作按钮
724
+
725
+ ```tsx
726
+ // 后端配置
727
+ {
728
+ title: '操作',
729
+ actions: [
730
+ {
731
+ type: 'Button',
732
+ props: {
733
+ title: '保存',
734
+ submit: true // 提交表单
735
+ }
736
+ },
737
+ {
738
+ type: 'Button',
739
+ props: {
740
+ title: '保存并新增',
741
+ request: {
742
+ url: '/admin/save',
743
+ method: 'post',
744
+ afterAction: ['tableReload', 'closeModal'] // 操作后执行
745
+ }
746
+ }
747
+ },
748
+ {
749
+ type: 'Button',
750
+ props: {
751
+ title: '重置',
752
+ reset: true // 重置表单
753
+ }
754
+ },
755
+ {
756
+ type: 'Button',
757
+ props: {
758
+ title: '返回',
759
+ back: true // 返回上一页
760
+ }
761
+ },
762
+ {
763
+ type: 'Button',
764
+ props: {
765
+ title: '打开子表单',
766
+ modal: {
767
+ title: '子表单',
768
+ content: {
769
+ type: 'form',
770
+ url: '/admin/subform/__id__'
771
+ }
772
+ }
773
+ }
774
+ }
775
+ ]
776
+ }
777
+ ```
778
+
779
+ ## 更新日志
178
780
 
781
+ ### 1.3.0 (2026-02-11)
782
+
783
+ **新增功能**
784
+ - **Table 组件优化**:添加表格默认搜索值初始化和加载状态处理
785
+ - **树形数据处理**:新增树形数据处理工具函数(`treeToList`、`diffTree`、`findValuePath`、`getValueByPath`)
786
+ - **布局组件优化**:优化布局组件的渲染逻辑和用户体验
787
+
788
+ **Bug 修复**
789
+ - 修复 Cascader 组件值比较逻辑问题
790
+ - 修复表格搜索 URL 处理逻辑
791
+ - 修复文件上传组件的 multiple 属性判断逻辑
792
+
793
+ ### 1.2.0 (2025-09-29)
794
+
795
+ **新增功能**
796
+ - **SelectText 组件**:新增键值对输入组件,支持灵活的数据输入方式
797
+ - **Table 组件增强**:
798
+ - 添加表格描述功能
799
+ - 增加日期范围搜索功能
800
+ - 优化列处理逻辑和搜索表单初始值处理
801
+ - **File 组件增强**:支持多文件选择上传功能
802
+ - **类型支持**:添加 scss 模块声明文件支持
803
+
804
+ **组件优化**
805
+ - 优化 SelectText 组件样式与功能
806
+ - 优化 textarea 渲染逻辑
807
+ - 优化上传组件的校验逻辑
808
+
809
+ ### 1.1.0 (2024-11-14)
810
+
811
+ **新增功能**
812
+ - **Composer 包自动注册**:支持自动分析并注册 Composer 包中的组件
813
+ - **Table 组件增强**:
814
+ - 添加表格树型结构支持
815
+ - 增加表格右侧操作的数据字段渲染功能
816
+ - 新增 Link 表格组件
817
+ - 支持选项设置、隐藏列配置及行宽设置
818
+ - **Form 组件增强**:
819
+ - 新增 Dependency 表单项,支持依赖项处理
820
+ - 新增 formList 表单列表组件
821
+ - 提交失败后自动滚动到第一个错误表单项
822
+ - **Layout 组件优化**:
823
+ - 新增 Layout Replacement 组件,支持单独变更属性
824
+ - 支持自定义 headerActions 和 footer
825
+ - **文件上传增强**:增加图片裁剪质量选项
826
+ - **主题支持**:添加暗黑模式切换功能
827
+
828
+ **组件优化**
829
+ - 优化级联初始化机制和省市区组件
830
+ - 增加注入自定义组件验证
831
+ - 优化文件上传请求,统一文件名后缀大小写
832
+ - 添加 hidden 字段适配
833
+ - 优化布局组件并添加自定义路由映射
834
+ - 添加 useWindowResize 自定义钩子处理窗口大小变化
835
+
836
+ **类型支持**
837
+ - 将 lodash 引入方式改为花括号形式,优化打包体积
838
+ - 增加引入部分类型定义
179
839