@ebiz/designer-components 0.0.37 → 0.0.39

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ebiz/designer-components",
3
- "version": "0.0.37",
3
+ "version": "0.0.39",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -79,7 +79,22 @@ const refreshing = ref(false)
79
79
  const total = ref(0)
80
80
  const pageSizeOptions = ref([10, 20, 50, 100])
81
81
 
82
- const data = ref([]);
82
+ const data = ref([
83
+ {
84
+ id: 1,
85
+ name: '张三',
86
+ age: 18,
87
+ gender: '男',
88
+ address: '北京市海淀区'
89
+ },
90
+ {
91
+ id: 2,
92
+ name: '李四',
93
+ age: 20,
94
+ gender: '女',
95
+ address: '北京市朝阳区'
96
+ }
97
+ ]);
83
98
 
84
99
  const props = defineProps({
85
100
  showPageHeader: {
@@ -334,93 +334,25 @@ const callApi = async (config = props.apiConfig) => {
334
334
  try {
335
335
  apiLoading.value = true
336
336
 
337
- // 克隆配置以避免修改原始对象
338
- const apiConfig = { ...config }
337
+ // 准备请求参数
338
+ const fetchParams = { ...localFormData.value }
339
339
 
340
- // 对于添加和编辑表单,自动附加表单数据
341
- if ((props.dialogType === 'add' || props.dialogType === 'edit') && localFormData.value) {
342
- // 如果没有data字段,创建一个
343
- if (!apiConfig.data) {
344
- apiConfig.data = { ...localFormData.value }
345
- }
346
- // 如果有data字段且是对象,合并表单数据
347
- else if (typeof apiConfig.data === 'object' && apiConfig.data !== null) {
348
- // 深拷贝表单数据,避免引用问题
349
- const formDataCopy = {}
350
- Object.keys(localFormData.value).forEach(key => {
351
- // 处理表单中的引用类型数据
352
- if (typeof localFormData.value[key] === 'object' && localFormData.value[key] !== null) {
353
- formDataCopy[key] = Array.isArray(localFormData.value[key])
354
- ? [...localFormData.value[key]]
355
- : { ...localFormData.value[key] }
356
- } else {
357
- formDataCopy[key] = localFormData.value[key]
358
- }
359
- })
360
-
361
- apiConfig.data = { ...apiConfig.data, ...formDataCopy }
362
- }
363
- }
364
-
365
- // 添加默认的content-type头
366
- if (!apiConfig.headers) {
367
- apiConfig.headers = {}
368
- }
369
-
370
- if (!apiConfig.headers['Content-Type']) {
371
- apiConfig.headers['Content-Type'] = 'application/json'
372
- }
373
-
374
- // 设置默认的请求方法
375
- if (!apiConfig.method) {
376
- // 根据弹窗类型设置默认方法
377
- switch (props.dialogType) {
378
- case 'add':
379
- apiConfig.method = 'post'
380
- break
381
- case 'edit':
382
- apiConfig.method = 'put'
383
- break
384
- case 'delete':
385
- apiConfig.method = 'delete'
386
- break
387
- default:
388
- apiConfig.method = 'post'
389
- }
390
- }
391
-
392
- // 如果是URL形式的API配置
393
- if (typeof apiConfig === 'string') {
394
- apiConfig = { url: apiConfig, method: 'post' }
395
- }
396
-
397
- // 添加自定义请求拦截器
398
- let requestTransformer = null
399
- if (apiConfig.transformRequest) {
400
- requestTransformer = apiConfig.transformRequest
401
- delete apiConfig.transformRequest
340
+ // 如果有ID,添加到请求参数中
341
+ if (currentId.value) {
342
+ fetchParams.id = currentId.value
402
343
  }
403
344
 
404
- // 添加自定义响应拦截器
405
- let responseTransformer = null
406
- if (apiConfig.transformResponse) {
407
- responseTransformer = apiConfig.transformResponse
408
- delete apiConfig.transformResponse
409
- }
410
-
411
- // 处理请求数据
412
- if (requestTransformer && typeof requestTransformer === 'function') {
413
- apiConfig.data = requestTransformer(apiConfig.data)
345
+ // 合并当前参数到请求参数
346
+ if (currentParams.value && Object.keys(currentParams.value).length > 0) {
347
+ Object.keys(currentParams.value).forEach(key => {
348
+ if (key !== 'formData') { // 避免重复添加表单数据
349
+ fetchParams[key] = currentParams.value[key]
350
+ }
351
+ })
414
352
  }
415
353
 
416
- // 调用dataService进行API请求
417
- const response = await dataService.fetch({}, apiConfig)
418
-
419
- // 处理响应数据
420
- let transformedResponse = response
421
- if (responseTransformer && typeof responseTransformer === 'function') {
422
- transformedResponse = responseTransformer(response)
423
- }
354
+ // 调用dataService进行API请求,直接使用config
355
+ const response = await dataService.fetch(fetchParams, config)
424
356
 
425
357
  // 显示成功消息
426
358
  if (props.showResultMessage) {
@@ -435,14 +367,14 @@ const callApi = async (config = props.apiConfig) => {
435
367
  }
436
368
 
437
369
  // 触发成功事件
438
- emit('api-success', transformedResponse)
370
+ emit('api-success', response)
439
371
 
440
372
  // 如果设置了成功后关闭,则关闭弹窗
441
373
  if (props.closeOnSuccess) {
442
374
  dialogVisible.value = false
443
375
  }
444
376
 
445
- return transformedResponse
377
+ return response
446
378
  } catch (error) {
447
379
  // 错误处理和错误消息展示
448
380
  const errorMessage = getErrorMessage(error, props.dialogType)
@@ -481,62 +413,8 @@ const handleDialogConfirm = async (e) => {
481
413
 
482
414
  // 校验成功,执行提交操作
483
415
  if (validateResult === true) {
484
- // 克隆API配置,避免修改原始配置
485
- const apiConfig = { ...props.apiConfig }
486
-
487
- // 对于编辑模式,确保请求中包含ID
488
- if (props.dialogType === 'edit' && currentId.value) {
489
- // 替换URL中的ID参数,支持{id}和:id两种格式
490
- if (apiConfig.url) {
491
- apiConfig.url = apiConfig.url.replace(/\{id\}/g, currentId.value).replace(/:id/g, currentId.value)
492
- }
493
-
494
- // 准备请求参数
495
- if (!apiConfig.params) {
496
- apiConfig.params = {}
497
- }
498
-
499
- // 如果有params参数且没有id,添加id
500
- if (!apiConfig.params.id && currentId.value) {
501
- apiConfig.params.id = currentId.value
502
- }
503
-
504
- // 准备请求数据
505
- if (!apiConfig.data) {
506
- apiConfig.data = {}
507
- }
508
-
509
- // 确保请求体中有ID
510
- if (!apiConfig.data.id && currentId.value) {
511
- apiConfig.data.id = currentId.value
512
- }
513
-
514
- // 合并当前参数中的非表单数据
515
- if (currentParams.value && Object.keys(currentParams.value).length > 0) {
516
- // 过滤掉id和formData,避免重复
517
- const { id: _id, formData: _formData, ...otherParams } = currentParams.value
518
- apiConfig.params = { ...apiConfig.params, ...otherParams }
519
- }
520
-
521
- await callApi(apiConfig)
522
- } else {
523
- // 克隆API配置,确保添加操作有正确的data字段
524
- const addApiConfig = { ...props.apiConfig }
525
-
526
- // 合并当前参数中的非表单数据
527
- if (currentParams.value && Object.keys(currentParams.value).length > 0) {
528
- // 过滤掉id和formData,避免重复
529
- const { id: _id, formData: _formData, ...otherParams } = currentParams.value
530
-
531
- if (!addApiConfig.params) {
532
- addApiConfig.params = {}
533
- }
534
-
535
- addApiConfig.params = { ...addApiConfig.params, ...otherParams }
536
- }
537
-
538
- await callApi(addApiConfig)
539
- }
416
+ // 直接调用callApi传入props.apiConfig
417
+ await callApi(props.apiConfig)
540
418
  } else {
541
419
  // 校验失败,显示第一个错误信息
542
420
  const firstError = validateResult[Object.keys(validateResult)[0]]?.[0]?.message || '表单校验失败'
@@ -557,51 +435,8 @@ const handleDialogConfirm = async (e) => {
557
435
  // 显示加载状态
558
436
  apiLoading.value = true
559
437
 
560
- // 克隆API配置,避免修改原始配置
561
- const deleteApiConfig = { ...props.apiConfig }
562
-
563
- // 对于删除操作,确保包含ID
564
- if (currentId.value) {
565
- // 替换URL中的ID参数
566
- if (deleteApiConfig.url) {
567
- deleteApiConfig.url = deleteApiConfig.url.replace(/\{id\}/g, currentId.value).replace(/:id/g, currentId.value)
568
- }
569
-
570
- // 准备请求参数
571
- if (!deleteApiConfig.params) {
572
- deleteApiConfig.params = {}
573
- }
574
-
575
- // 如果有params参数且没有id,添加id
576
- if (!deleteApiConfig.params.id && currentId.value) {
577
- deleteApiConfig.params.id = currentId.value
578
- }
579
-
580
- // 准备请求数据
581
- if (!deleteApiConfig.data) {
582
- deleteApiConfig.data = {}
583
- }
584
-
585
- // 确保请求体中有ID
586
- if (!deleteApiConfig.data.id && currentId.value) {
587
- deleteApiConfig.data.id = currentId.value
588
- }
589
- }
590
-
591
- // 合并当前参数
592
- if (currentParams.value && Object.keys(currentParams.value).length > 0) {
593
- // 过滤掉id和formData,避免重复
594
- const { id: _id, formData: _formData, ...otherParams } = currentParams.value
595
-
596
- if (!deleteApiConfig.params) {
597
- deleteApiConfig.params = {}
598
- }
599
-
600
- deleteApiConfig.params = { ...deleteApiConfig.params, ...otherParams }
601
- }
602
-
603
438
  // 删除操作直接调用API
604
- await callApi(deleteApiConfig)
439
+ await callApi(props.apiConfig)
605
440
  } catch (error) {
606
441
  // API调用过程中的错误
607
442
  MessagePlugin.error(`删除失败: ${error.message || '未知错误'}`)
@@ -621,19 +456,8 @@ const handleDialogConfirm = async (e) => {
621
456
  // 显示加载状态
622
457
  apiLoading.value = true
623
458
 
624
- // 克隆API配置,避免修改原始配置
625
- const normalApiConfig = { ...props.apiConfig }
626
-
627
- // 合并当前参数
628
- if (currentParams.value && Object.keys(currentParams.value).length > 0) {
629
- if (!normalApiConfig.params) {
630
- normalApiConfig.params = {}
631
- }
632
-
633
- normalApiConfig.params = { ...normalApiConfig.params, ...currentParams.value }
634
- }
635
-
636
- await callApi(normalApiConfig)
459
+ // 直接调用API,不修改apiConfig
460
+ await callApi(props.apiConfig)
637
461
  } catch (error) {
638
462
  // API调用过程中的错误
639
463
  MessagePlugin.error(`操作失败: ${error.message || '未知错误'}`)
@@ -682,35 +506,20 @@ const loadDetailData = async (id) => {
682
506
  // 显示加载状态
683
507
  apiLoading.value = true
684
508
 
685
- // 构建详情请求配置
686
- const requestConfig = {
687
- ...props.detailApiConfig
688
- }
689
-
690
- // 替换URL中的ID参数,支持{id}和:id两种格式
691
- if (requestConfig.url) {
692
- requestConfig.url = requestConfig.url.replace(/\{id\}/g, id).replace(/:id/g, id)
693
- }
694
-
695
- // 处理请求参数
696
- if (!requestConfig.params) {
697
- requestConfig.params = {}
698
- }
509
+ // 准备请求参数
510
+ const fetchParams = { id }
699
511
 
700
- // 如果有params参数且没有id,添加id
701
- if (!requestConfig.params.id && id) {
702
- requestConfig.params.id = id
703
- }
704
-
705
- // 合并当前参数
512
+ // 合并当前参数到请求参数
706
513
  if (currentParams.value && Object.keys(currentParams.value).length > 0) {
707
514
  // 过滤掉id和formData,避免重复
708
515
  const { id: _id, formData: _formData, ...otherParams } = currentParams.value
709
- requestConfig.params = { ...requestConfig.params, ...otherParams }
516
+ Object.keys(otherParams).forEach(key => {
517
+ fetchParams[key] = otherParams[key]
518
+ })
710
519
  }
711
520
 
712
- // 调用dataService进行API请求
713
- const response = await dataService.fetch({}, requestConfig)
521
+ // 调用dataService进行API请求,直接使用detailApiConfig
522
+ const response = await dataService.fetch(fetchParams, props.detailApiConfig)
714
523
 
715
524
  // 获取详情数据
716
525
  const detailData = response.data || response
@@ -0,0 +1,158 @@
1
+ # EbizSForm 高级表单组件
2
+
3
+ EbizSForm是一个基于TDesign Form封装的高级表单组件,提供了丰富的表单功能,包括本地表单数据管理、表单验证、API提交和详情数据加载等。
4
+
5
+ ## 主要特性
6
+
7
+ 1. **本地表单数据管理**:通过`localFormData`管理表单数据,实现数据的双向绑定
8
+ 2. **详情接口支持**:通过`detailApiConfig`配置详情API,支持加载表单详情数据
9
+ 3. **API调用机制**:使用`dataService.fetch(params, apiConfig)`方式调用API,符合系统规范
10
+ 4. **表单验证**:支持完整的表单验证功能,并与API调用无缝衔接
11
+ 5. **丰富的方法支持**:提供`openForm`、`loadDetailData`、`setFormData`等丰富的方法
12
+
13
+ ## 基本用法
14
+
15
+ ```vue
16
+ <template>
17
+ <EbizSForm
18
+ ref="formRef"
19
+ :data="formData"
20
+ :rules="formRules"
21
+ :api-config="apiConfig"
22
+ :detail-api-config="detailApiConfig"
23
+ @success="handleSuccess"
24
+ @error="handleError"
25
+ @detail-loaded="handleDetailLoaded"
26
+ >
27
+ <EbizSFormItem label="用户名" name="username" type="input" />
28
+ <EbizSFormItem label="密码" name="password" type="input" />
29
+ </EbizSForm>
30
+ </template>
31
+
32
+ <script setup>
33
+ import { ref, reactive } from 'vue';
34
+ import { EbizSForm, EbizSFormItem } from '@ebiz/designer-components';
35
+
36
+ const formRef = ref(null);
37
+ const formData = reactive({
38
+ username: '',
39
+ password: ''
40
+ });
41
+
42
+ const formRules = {
43
+ username: [
44
+ { required: true, message: '请输入用户名', trigger: 'blur' }
45
+ ],
46
+ password: [
47
+ { required: true, message: '请输入密码', trigger: 'blur' }
48
+ ]
49
+ };
50
+
51
+ // API配置
52
+ const apiConfig = {
53
+ key: 'userSubmit',
54
+ apiId: 'user.submit',
55
+ apiType: '3'
56
+ };
57
+
58
+ // 详情API配置
59
+ const detailApiConfig = {
60
+ key: 'userDetail',
61
+ apiId: 'user.detail',
62
+ apiType: '1'
63
+ };
64
+
65
+ // 加载详情数据
66
+ const loadDetail = (id) => {
67
+ formRef.value.loadDetailData(id);
68
+ };
69
+
70
+ // 事件处理
71
+ const handleSuccess = (response) => {
72
+ console.log('提交成功:', response);
73
+ };
74
+
75
+ const handleError = (error) => {
76
+ console.error('提交失败:', error);
77
+ };
78
+
79
+ const handleDetailLoaded = (data) => {
80
+ console.log('详情数据加载成功:', data);
81
+ };
82
+ </script>
83
+ ```
84
+
85
+ ## Props
86
+
87
+ | 属性名 | 类型 | 默认值 | 说明 |
88
+ | ----------------- | --------- | --------- | ----------------------------------- |
89
+ | data | Object | {} | 表单数据对象 |
90
+ | labelAlign | String | 'right' | 标签对齐方式:'left'/'right'/'top' |
91
+ | layout | String | 'vertical'| 表单布局方式:'vertical'/'inline' |
92
+ | labelWidth | String | '100px' | 标签宽度 |
93
+ | rules | Object | {} | 表单验证规则 |
94
+ | apiConfig | Object | null | API配置,用于表单提交 |
95
+ | detailApiConfig | Object | null | 详情API配置,用于加载表单数据 |
96
+ | resetOnSuccess | Boolean | false | 提交成功后是否重置表单 |
97
+ | showResultMessage | Boolean | true | 是否显示结果消息 |
98
+
99
+ ## 事件
100
+
101
+ | 事件名 | 说明 | 参数 |
102
+ | ------------ | ----------------------- | ------------------------------ |
103
+ | submit | 表单提交时触发 | formData: 表单数据对象 |
104
+ | success | API调用成功时触发 | response: 成功响应数据 |
105
+ | error | API调用失败时触发 | error: 错误信息 |
106
+ | reset | 表单重置时触发 | context: 重置上下文 |
107
+ | validate | 表单验证时触发 | result: 验证结果 |
108
+ | detail-loaded| 详情数据加载成功时触发 | data: 详情数据 |
109
+ | detail-error | 详情数据加载失败时触发 | error: 错误信息 |
110
+
111
+ ## 方法
112
+
113
+ 通过ref可以调用组件实例的以下方法:
114
+
115
+ | 方法名 | 说明 | 参数 |
116
+ | -------------- | ------------------------ | ------------------------------ |
117
+ | submit | 提交表单 | 无 |
118
+ | reset | 重置表单 | 无 |
119
+ | validate | 验证表单 | 无 |
120
+ | validateFields | 验证指定字段 | fields: 字段名或字段名数组 |
121
+ | clearValidate | 清除验证结果 | fields: 字段名或字段名数组,可选 |
122
+ | openForm | 打开表单并设置参数 | params: 参数对象 |
123
+ | loadDetailData | 加载详情数据 | id: 记录ID |
124
+ | setFormData | 设置表单数据 | data: 要设置的数据对象 |
125
+ | getFormData | 获取表单数据 | 无 |
126
+ | clearFormData | 清空表单数据 | 无 |
127
+
128
+ ## API配置对象说明
129
+
130
+ apiConfig和detailApiConfig的格式如下:
131
+
132
+ ```javascript
133
+ {
134
+ key: 'apiKey', // API的键名
135
+ apiId: 'module.api', // API的标识ID
136
+ apiType: '3' // API类型,对应dataService中的类型
137
+ }
138
+ ```
139
+
140
+ apiType常用值:
141
+ - '0': 列表查询
142
+ - '1': 详情查询
143
+ - '3': 数据新增
144
+ - '5': 数据修改
145
+ - '7': 数据删除
146
+
147
+ ## 与EbizSDialog组件的比较
148
+
149
+ EbizSForm与EbizSDialog组件有相似的API调用和表单数据处理机制,两者都:
150
+
151
+ 1. 使用本地表单数据管理(localFormData)
152
+ 2. 支持详情数据加载(detailApiConfig)
153
+ 3. 采用相同的API调用方式(dataService.fetch)
154
+ 4. 不修改apiConfig对象
155
+
156
+ 选择使用哪个组件取决于具体的场景需求:
157
+ - 如果需要在页面上直接显示表单,使用EbizSForm
158
+ - 如果需要在弹窗中显示表单,使用EbizSDialog