fix(): 优化动态表单项导出#547
Conversation
总览本 PR 通过三个相关联的变更增强动态表单的校验和导出功能。首先在类型层定义校验器回调参数新增 变更说明表单校验和导出功能增强
审查工作量评估🎯 2 (Simple) | ⏱️ ~12 分钟 相关 PR
建议标签
建议审查者
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
bricks/forms/src/dynamic-form-item-v2/ColumnComponent.tsx (1)
117-151:⚠️ Potential issue | 🟡 Minor实现正确;但测试仍未覆盖
column传递
代码在自定义校验器回调上下文中传入了{ formValue, rowValue, rowIndex, column },并将column加入useMemo依赖;但ColumnComponent.spec.tsx的it("validator should work")目前只断言了{ formValue, rowIndex, rowValue },未断言fullValue.column,无法保证新增的column参数传递正确。建议在该用例中补充对
column的断言(例如将期望对象扩展为包含column)。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@bricks/forms/src/dynamic-form-item-v2/ColumnComponent.tsx` around lines 117 - 151, The test it("validator should work") in ColumnComponent.spec.tsx currently asserts the validator callback receives { formValue, rowIndex, rowValue } but doesn't check the injected column; update the spec to expect the full context passed by ColumnComponent's useMemo validator wrapper (the fourth argument to rule.validator) to include column as well — i.e., call the validator in the test and assert the received context object contains formValue, rowValue, rowIndex and the same column object (from the test fixture) so the column parameter delivered by ColumnComponent.rule.validator is covered.
🧹 Nitpick comments (1)
bricks/forms/src/dynamic-form-item-v2/excelUtils.tsx (1)
44-45: ⚡ Quick win建议使用类型安全的方式访问列属性。
使用
as any绕过了 TypeScript 的类型检查。由于Column是一个带有类型判别器的联合类型,可以通过类型守卫或更精确的类型断言来安全访问这些属性。♻️ 建议的类型安全改进
const headers = columns.map((col) => ({ key: col.name, header: col.label || col.name, - type: (col as any).type, - mode: (col as any).props?.mode, + type: col.type, + mode: col.type === 'select' ? col.props?.mode : undefined, }));🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@bricks/forms/src/dynamic-form-item-v2/excelUtils.tsx` around lines 44 - 45, The code currently uses (col as any).type and (col as any).props?.mode which bypasses TypeScript checks; replace these casts with a proper type guard to narrow the Column union before accessing properties: implement a predicate (e.g., isColumnWithProps or similar) that checks the Column discriminant and/or presence of props, then access col.type and col.props.mode only after narrowing; update the usage sites in excelUtils.tsx (the variables col, type, mode) to rely on that guard or a precise type assertion (e.g., ColumnWithProps) instead of as any.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@bricks/forms/src/dynamic-form-item-v2/excelUtils.tsx`:
- Around line 52-68: The export logic in excelUtils.tsx is not symmetric with
validateAndTransformValue: update the array handling in the export loop (where
exportRow[header.header] is assigned) so select multiple values are joined using
the same separator expected by validateAndTransformValue (use ',' with no space
or ensure import trims surrounding spaces) and make cascader exports consistent
with import (either export nested cascader values as JSON.stringify(...) or join
with '/' to match the import parsing); reference the header.type/header.mode
checks, flattenArray, and validateAndTransformValue to ensure round-trip
consistency.
- Around line 52-68: Array elements are being joined directly which yields
"[object Object]" for objects and "null"/"undefined" strings for missing values;
update the Array.isArray(value) branches in excelUtils.tsx (the block handling
header.type === 'select' / 'cascader' / other arrays where value = value.join(',
')) to first map/format each element: for cascader use flattenArray(...) then
map each element to a safe string (convert null/undefined to empty string,
primitives via String(), and objects via JSON.stringify or a custom display
field) and then join with ', '; ensure the same formatting logic is applied for
select (multiple/tags) and the generic array branch before assigning
exportRow[header.header] = value.
---
Outside diff comments:
In `@bricks/forms/src/dynamic-form-item-v2/ColumnComponent.tsx`:
- Around line 117-151: The test it("validator should work") in
ColumnComponent.spec.tsx currently asserts the validator callback receives {
formValue, rowIndex, rowValue } but doesn't check the injected column; update
the spec to expect the full context passed by ColumnComponent's useMemo
validator wrapper (the fourth argument to rule.validator) to include column as
well — i.e., call the validator in the test and assert the received context
object contains formValue, rowValue, rowIndex and the same column object (from
the test fixture) so the column parameter delivered by
ColumnComponent.rule.validator is covered.
---
Nitpick comments:
In `@bricks/forms/src/dynamic-form-item-v2/excelUtils.tsx`:
- Around line 44-45: The code currently uses (col as any).type and (col as
any).props?.mode which bypasses TypeScript checks; replace these casts with a
proper type guard to narrow the Column union before accessing properties:
implement a predicate (e.g., isColumnWithProps or similar) that checks the
Column discriminant and/or presence of props, then access col.type and
col.props.mode only after narrowing; update the usage sites in excelUtils.tsx
(the variables col, type, mode) to rely on that guard or a precise type
assertion (e.g., ColumnWithProps) instead of as any.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: bf97c72c-9bc3-4b54-a35f-d89a5d9f2764
📒 Files selected for processing (3)
bricks/forms/src/dynamic-form-item-v2/ColumnComponent.tsxbricks/forms/src/dynamic-form-item-v2/excelUtils.tsxbricks/forms/src/interfaces/dynamic-form-item-v2.ts
| let value = row[header.key]; | ||
|
|
||
| // 处理数组类型的值(如 select 多选、cascader 多选等) | ||
| if (Array.isArray(value)) { | ||
| // 对于多选模式,将数组转换为逗号分隔的字符串 | ||
| if (header.type === 'select' && (header.mode === 'multiple' || header.mode === 'tags')) { | ||
| value = value.join(', '); | ||
| } else if (header.type === 'cascader') { | ||
| // Cascader 可能是多维数组,递归处理 | ||
| value = flattenArray(value).join(', '); | ||
| } else { | ||
| // 其他数组类型也转换为字符串 | ||
| value = value.join(', '); | ||
| } | ||
| } | ||
|
|
||
| exportRow[header.header] = value; |
There was a problem hiding this comment.
导出和导入逻辑不一致,可能导致数据往返丢失。
当前导出逻辑与 validateAndTransformValue 中的导入逻辑存在不对称:
- Select 多选模式:导出使用
", "连接,但导入时会按逗号或换行符分割(第 282 行)。导出的", "中包含空格,导入时可能产生额外的空白字符。 - Cascader:导出时将嵌套数组展平后用
", "连接,但导入时会按"/"分割(第 263 行)或解析 JSON(第 255 行)。这会导致导出后无法正确还原原始的嵌套结构。
建议统一导出和导入的分隔符及数据格式,确保数据能够正确往返。
💡 建议的一致性改进方案
对于 cascader,建议导出为 JSON 字符串或使用与导入一致的 "/" 分隔符:
} else if (header.type === 'cascader') {
- // Cascader 可能是多维数组,递归处理
- value = flattenArray(value).join(', ');
+ // Cascader 导出为 JSON 格式,与导入逻辑保持一致
+ try {
+ value = JSON.stringify(value);
+ } catch {
+ value = '';
+ }
} else {对于 select 多选,确保导入时正确处理空格:
if (header.type === 'select' && (header.mode === 'multiple' || header.mode === 'tags')) {
- value = value.join(', ');
+ value = value.join(','); // 移除空格,与导入逻辑一致
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| let value = row[header.key]; | |
| // 处理数组类型的值(如 select 多选、cascader 多选等) | |
| if (Array.isArray(value)) { | |
| // 对于多选模式,将数组转换为逗号分隔的字符串 | |
| if (header.type === 'select' && (header.mode === 'multiple' || header.mode === 'tags')) { | |
| value = value.join(', '); | |
| } else if (header.type === 'cascader') { | |
| // Cascader 可能是多维数组,递归处理 | |
| value = flattenArray(value).join(', '); | |
| } else { | |
| // 其他数组类型也转换为字符串 | |
| value = value.join(', '); | |
| } | |
| } | |
| exportRow[header.header] = value; | |
| let value = row[header.key]; | |
| // 处理数组类型的值(如 select 多选、cascader 多选等) | |
| if (Array.isArray(value)) { | |
| // 对于多选模式,将数组转换为逗号分隔的字符串 | |
| if (header.type === 'select' && (header.mode === 'multiple' || header.mode === 'tags')) { | |
| value = value.join(','); // 移除空格,与导入逻辑一致 | |
| } else if (header.type === 'cascader') { | |
| // Cascader 导出为 JSON 格式,与导入逻辑保持一致 | |
| try { | |
| value = JSON.stringify(value); | |
| } catch { | |
| value = ''; | |
| } | |
| } else { | |
| // 其他数组类型也转换为字符串 | |
| value = value.join(', '); | |
| } | |
| } | |
| exportRow[header.header] = value; |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@bricks/forms/src/dynamic-form-item-v2/excelUtils.tsx` around lines 52 - 68,
The export logic in excelUtils.tsx is not symmetric with
validateAndTransformValue: update the array handling in the export loop (where
exportRow[header.header] is assigned) so select multiple values are joined using
the same separator expected by validateAndTransformValue (use ',' with no space
or ensure import trims surrounding spaces) and make cascader exports consistent
with import (either export nested cascader values as JSON.stringify(...) or join
with '/' to match the import parsing); reference the header.type/header.mode
checks, flattenArray, and validateAndTransformValue to ensure round-trip
consistency.
数组值可能包含非原始类型,导致导出结果不正确。
当数组中包含对象时,.join(', ') 会产生 "[object Object]" 这样无意义的字符串。另外,数组中的 null 或 undefined 会被转换为字符串 "null" 或 "undefined"。
建议在执行 join 操作前,先对数组元素进行格式化处理,确保转换为有意义的字符串表示。
🛡️ 建议的修复方案
if (Array.isArray(value)) {
+ // 将数组元素转换为字符串,处理 null/undefined/对象
+ const formatArrayItem = (item: any): string => {
+ if (item === null || item === undefined) return '';
+ if (typeof item === 'object') return JSON.stringify(item);
+ return String(item);
+ };
+
// 对于多选模式,将数组转换为逗号分隔的字符串
if (header.type === 'select' && (header.mode === 'multiple' || header.mode === 'tags')) {
- value = value.join(', ');
+ value = value.map(formatArrayItem).filter(Boolean).join(', ');
} else if (header.type === 'cascader') {
// Cascader 可能是多维数组,递归处理
- value = flattenArray(value).join(', ');
+ value = flattenArray(value).map(formatArrayItem).filter(Boolean).join(', ');
} else {
// 其他数组类型也转换为字符串
- value = value.join(', ');
+ value = value.map(formatArrayItem).filter(Boolean).join(', ');
}
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| let value = row[header.key]; | |
| // 处理数组类型的值(如 select 多选、cascader 多选等) | |
| if (Array.isArray(value)) { | |
| // 对于多选模式,将数组转换为逗号分隔的字符串 | |
| if (header.type === 'select' && (header.mode === 'multiple' || header.mode === 'tags')) { | |
| value = value.join(', '); | |
| } else if (header.type === 'cascader') { | |
| // Cascader 可能是多维数组,递归处理 | |
| value = flattenArray(value).join(', '); | |
| } else { | |
| // 其他数组类型也转换为字符串 | |
| value = value.join(', '); | |
| } | |
| } | |
| exportRow[header.header] = value; | |
| let value = row[header.key]; | |
| // 处理数组类型的值(如 select 多选、cascader 多选等) | |
| if (Array.isArray(value)) { | |
| // 将数组元素转换为字符串,处理 null/undefined/对象 | |
| const formatArrayItem = (item: any): string => { | |
| if (item === null || item === undefined) return ''; | |
| if (typeof item === 'object') return JSON.stringify(item); | |
| return String(item); | |
| }; | |
| // 对于多选模式,将数组转换为逗号分隔的字符串 | |
| if (header.type === 'select' && (header.mode === 'multiple' || header.mode === 'tags')) { | |
| value = value.map(formatArrayItem).filter(Boolean).join(', '); | |
| } else if (header.type === 'cascader') { | |
| // Cascader 可能是多维数组,递归处理 | |
| value = flattenArray(value).map(formatArrayItem).filter(Boolean).join(', '); | |
| } else { | |
| // 其他数组类型也转换为字符串 | |
| value = value.map(formatArrayItem).filter(Boolean).join(', '); | |
| } | |
| } | |
| exportRow[header.header] = value; |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@bricks/forms/src/dynamic-form-item-v2/excelUtils.tsx` around lines 52 - 68,
Array elements are being joined directly which yields "[object Object]" for
objects and "null"/"undefined" strings for missing values; update the
Array.isArray(value) branches in excelUtils.tsx (the block handling header.type
=== 'select' / 'cascader' / other arrays where value = value.join(', ')) to
first map/format each element: for cascader use flattenArray(...) then map each
element to a safe string (convert null/undefined to empty string, primitives via
String(), and objects via JSON.stringify or a custom display field) and then
join with ', '; ensure the same formatting logic is applied for select
(multiple/tags) and the generic array branch before assigning
exportRow[header.header] = value.
依赖检查
组件之间的依赖声明,是微服务组件架构下的重要信息,请确保其正确性。
请勾选以下两组选项其中之一:
或者:
提交信息检查
Git 提交信息将决定包的版本发布及自动生成的 CHANGELOG,请检查工作内容与提交信息是否相符,并在以下每组选项中都依次确认。
破坏性变更:
feat作为提交类型。BREAKING CHANGE: 你的变更说明。新特性:
feat作为提交类型。问题修复:
fix作为提交类型。杂项工作:
即所有对下游使用者无任何影响、且没有必要显示在 CHANGELOG 中的改动,例如修改注释、测试用例、开发文档等:
chore,docs,test等作为提交类型。Summary by CodeRabbit
Release Notes