Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion packages/x/components/sender/SlotTextArea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ const SlotTextArea = React.forwardRef<SlotTextAreaRef>((_, ref) => {
const renderSlot = (node: SlotConfigType, slotSpan: HTMLSpanElement) => {
if (!node.key) return null;
const value = getSlotValues()[node.key];
console.log(node, 'nodeqqqqq');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

这里有一个 console.log 语句,可能是用于调试的。在合并到主分支之前,建议将其移除,以保持代码库的整洁。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

请移除调试用的 console.log

console.log(node, 'nodeqqqqq'); 属于调试残留,保留在组件库中会污染使用方控制台输出,建议删除或改为受控的调试开关。

🤖 Prompt for AI Agents
In packages/x/components/sender/SlotTextArea.tsx around line 143, there is a
leftover debugging statement `console.log(node, 'nodeqqqqq');` that should be
removed from the production component; delete this line (or replace it with a
controlled debug/logging mechanism—e.g., use the library's logger or a
conditional debug flag driven by env or props) so the component no longer
pollutes consumers' consoles.

const renderContent = () => {
switch (node.type) {
case 'input':
Expand Down Expand Up @@ -195,7 +196,31 @@ const SlotTextArea = React.forwardRef<SlotTextAreaRef>((_, ref) => {
</Dropdown>
);
case 'tag':
return <div className={`${prefixCls}-slot-tag`}>{node.props?.label || ''}</div>;
return (
<div className={`${prefixCls}-slot-tag`}>
{node.props?.label || ''}
{node.allowClose && (
<span
className={`${prefixCls}-slot-tag-close`}
onClick={(e) => {
e.stopPropagation();
// 从配置中移除
slotConfigRef.current = slotConfigRef.current.filter(
(item) => item.key !== node.key,
);
// 从DOM中移除
const slotDom = getSlotDom(node.key as string);
slotDom?.parentNode?.removeChild(slotDom);
// 更新状态
const newValue = getEditorValue();
onChange?.(newValue.value, undefined, newValue.config);
}}
Comment on lines +205 to +217
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

这个 onClick 处理器直接修改了DOM (removeChild) 和一个React ref (slotConfigRef.current)。这种做法比较脆弱,并且违反了React的单向数据流原则,可能导致难以预料的bug。

  1. 直接DOM操作: slotDom?.parentNode?.removeChild(slotDom) 会导致React的虚拟DOM和真实DOM之间出现不一致。如果父组件没有正确地通过onChange回调更新slotConfig prop来触发重渲染,UI就会处于一个损坏的状态。
  2. Ref突变: 对slotConfigRef.current的直接修改是多余的,因为getEditorValue()会从DOM中重新生成配置,并且这个ref会在slotConfig prop变化时被重置。这使得代码的意图变得不清晰。

建议重构此逻辑,避免在事件处理器中直接操作DOM和ref。一个更安全的方式是,在临时修改DOM以计算新值后,立即恢复DOM,然后通过onChange将新的配置和值传递给父组件,由父组件来驱动UI的更新。

>
×
</span>
)}
</div>
);
case 'custom':
return node.customRender?.(
value,
Expand Down
17 changes: 17 additions & 0 deletions packages/x/components/sender/demo/agent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ const AgentInfo: {
},
},
{ type: 'text', value: ' and summarize it into a list.' },
{
type: 'tag',
key: 'tag_type',
props: {
value: 'tag1',
label: 'tag 1',
},
},
],
},
ai_code: {
Expand All @@ -52,6 +60,15 @@ const AgentInfo: {
},
},
{ type: 'text', value: ' to write a mini game.' },
{
type: 'tag',
key: 'tag_type',
allowClose: true,
props: {
value: 'tag2',
label: 'tag 2',
},
},
],
},
ai_writing: {
Expand Down
7 changes: 5 additions & 2 deletions packages/x/components/sender/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ interface SlotConfigSelectType extends SlotConfigBaseType {
interface SlotConfigTagType extends SlotConfigBaseType {
type: 'tag';
key: string;
allowClose?: boolean;
props?: {
label: React.ReactNode;
value?: string;
Expand Down Expand Up @@ -97,8 +98,10 @@ export type SlotConfigType =
export type EventType =
| React.FormEvent<HTMLTextAreaElement>
| React.ChangeEvent<HTMLTextAreaElement>;
export interface SenderProps
extends Pick<TextareaProps, 'placeholder' | 'onKeyUp' | 'onFocus' | 'onBlur'> {
export interface SenderProps extends Pick<
TextareaProps,
'placeholder' | 'onKeyUp' | 'onFocus' | 'onBlur'
> {
prefixCls?: string;
defaultValue?: string;
value?: string;
Expand Down